diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/AppCore.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/AppCore.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..b5c156a91b7402c846b359ae58ee5a2841f263a7
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/AppCore.xcscheme
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1410"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "AppCore"
+               BuildableName = "AppCore"
+               BlueprintName = "AppCore"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "AppCore"
+            BuildableName = "AppCore"
+            BlueprintName = "AppCore"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/BackupFeature.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/BackupFeature.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..c1eeaf920bb20f7f66ef27f50c0bdfc24728e417
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/BackupFeature.xcscheme
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1410"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "BackupFeature"
+               BuildableName = "BackupFeature"
+               BlueprintName = "BackupFeature"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "BackupFeature"
+            BuildableName = "BackupFeature"
+            BlueprintName = "BackupFeature"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/Countries.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/Countries.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..4c7d001db37cb451452f23627813acfe6b17b4d1
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/Countries.xcscheme
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1410"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "Countries"
+               BuildableName = "Countries"
+               BlueprintName = "Countries"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "Countries"
+            BuildableName = "Countries"
+            BlueprintName = "Countries"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/LaunchFeature 1.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/LaunchFeature 1.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..550e1ea22c75a628d02430c276f3fe8f14053252
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/LaunchFeature 1.xcscheme	
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1410"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "LaunchFeature"
+               BuildableName = "LaunchFeature"
+               BlueprintName = "LaunchFeature"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "LaunchFeature"
+            BuildableName = "LaunchFeature"
+            BlueprintName = "LaunchFeature"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/OnboardingFeature.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/OnboardingFeature.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..16cd9172dfb7808e9dfad0db2323fbeda4c764c3
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/OnboardingFeature.xcscheme
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1410"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "OnboardingFeature"
+               BuildableName = "OnboardingFeature"
+               BlueprintName = "OnboardingFeature"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "OnboardingFeature"
+            BuildableName = "OnboardingFeature"
+            BlueprintName = "OnboardingFeature"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/.swiftpm/xcode/xcshareddata/xcschemes/StatusBarFeature.xcscheme b/.swiftpm/xcode/xcshareddata/xcschemes/StatusBarFeature.xcscheme
new file mode 100644
index 0000000000000000000000000000000000000000..34f2d75bb6289d7283a321a3574f369a72da8605
--- /dev/null
+++ b/.swiftpm/xcode/xcshareddata/xcschemes/StatusBarFeature.xcscheme
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+   LastUpgradeVersion = "1410"
+   version = "1.3">
+   <BuildAction
+      parallelizeBuildables = "YES"
+      buildImplicitDependencies = "YES">
+      <BuildActionEntries>
+         <BuildActionEntry
+            buildForTesting = "YES"
+            buildForRunning = "YES"
+            buildForProfiling = "YES"
+            buildForArchiving = "YES"
+            buildForAnalyzing = "YES">
+            <BuildableReference
+               BuildableIdentifier = "primary"
+               BlueprintIdentifier = "StatusBarFeature"
+               BuildableName = "StatusBarFeature"
+               BlueprintName = "StatusBarFeature"
+               ReferencedContainer = "container:">
+            </BuildableReference>
+         </BuildActionEntry>
+      </BuildActionEntries>
+   </BuildAction>
+   <TestAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      shouldUseLaunchSchemeArgsEnv = "YES">
+      <Testables>
+      </Testables>
+   </TestAction>
+   <LaunchAction
+      buildConfiguration = "Debug"
+      selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+      selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+      launchStyle = "0"
+      useCustomWorkingDirectory = "NO"
+      ignoresPersistentStateOnLaunch = "NO"
+      debugDocumentVersioning = "YES"
+      debugServiceExtension = "internal"
+      allowLocationSimulation = "YES">
+   </LaunchAction>
+   <ProfileAction
+      buildConfiguration = "Release"
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      savedToolIdentifier = ""
+      useCustomWorkingDirectory = "NO"
+      debugDocumentVersioning = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "StatusBarFeature"
+            BuildableName = "StatusBarFeature"
+            BlueprintName = "StatusBarFeature"
+            ReferencedContainer = "container:">
+         </BuildableReference>
+      </MacroExpansion>
+   </ProfileAction>
+   <AnalyzeAction
+      buildConfiguration = "Debug">
+   </AnalyzeAction>
+   <ArchiveAction
+      buildConfiguration = "Release"
+      revealArchiveInOrganizer = "YES">
+   </ArchiveAction>
+</Scheme>
diff --git a/App/client-ios.xcodeproj/project.pbxproj b/App/client-ios.xcodeproj/project.pbxproj
index b173e088056b9a96da598954f6a23b4d0024d8d0..b13be6187f4691c5ee9d95e4db8864367a979327 100644
--- a/App/client-ios.xcodeproj/project.pbxproj
+++ b/App/client-ios.xcodeproj/project.pbxproj
@@ -13,10 +13,10 @@
 		02FDD07021EDA39B000F1286 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 02FDD06E21EDA39B000F1286 /* LaunchScreen.storyboard */; };
 		32179BA826410149008B26EC /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32179BA726410149008B26EC /* NotificationService.swift */; };
 		32179BAC26410149008B26EC /* NotificationExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 32179BA526410149008B26EC /* NotificationExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
-		3273327126C7391D0027D79D /* App in Frameworks */ = {isa = PBXBuildFile; productRef = 3273327026C7391D0027D79D /* App */; };
+		3242BD412921DC950045E647 /* AppFeature in Frameworks */ = {isa = PBXBuildFile; productRef = 3242BD402921DC950045E647 /* AppFeature */; };
+		3242BD432921DC9E0045E647 /* AppFeature in Frameworks */ = {isa = PBXBuildFile; productRef = 3242BD422921DC9E0045E647 /* AppFeature */; };
 		32C194E02808C65500876917 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 32C194DF2808C65500876917 /* GoogleService-Info.plist */; };
 		32C194E12808C65500876917 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 32C194DF2808C65500876917 /* GoogleService-Info.plist */; };
-		32CAAFAE2845836100446BB9 /* App in Frameworks */ = {isa = PBXBuildFile; productRef = 32CAAFAD2845836100446BB9 /* App */; };
 /* End PBXBuildFile section */
 
 /* Begin PBXContainerItemProxy section */
@@ -64,8 +64,8 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				3273327126C7391D0027D79D /* App in Frameworks */,
 				026135B321F2729900038B5E /* libsqlite3.tbd in Frameworks */,
+				3242BD432921DC9E0045E647 /* AppFeature in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -73,7 +73,7 @@
 			isa = PBXFrameworksBuildPhase;
 			buildActionMask = 2147483647;
 			files = (
-				32CAAFAE2845836100446BB9 /* App in Frameworks */,
+				3242BD412921DC950045E647 /* AppFeature in Frameworks */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -159,7 +159,7 @@
 			);
 			name = "client-ios";
 			packageProductDependencies = (
-				3273327026C7391D0027D79D /* App */,
+				3242BD422921DC9E0045E647 /* AppFeature */,
 			);
 			productName = "client-ios";
 			productReference = 02FDD06221EDA39A000F1286 /* client-ios.app */;
@@ -179,7 +179,7 @@
 			);
 			name = NotificationExtension;
 			packageProductDependencies = (
-				32CAAFAD2845836100446BB9 /* App */,
+				3242BD402921DC950045E647 /* AppFeature */,
 			);
 			productName = NotificationExtension;
 			productReference = 32179BA526410149008B26EC /* NotificationExtension.appex */;
@@ -610,13 +610,13 @@
 /* End XCConfigurationList section */
 
 /* Begin XCSwiftPackageProductDependency section */
-		3273327026C7391D0027D79D /* App */ = {
+		3242BD402921DC950045E647 /* AppFeature */ = {
 			isa = XCSwiftPackageProductDependency;
-			productName = App;
+			productName = AppFeature;
 		};
-		32CAAFAD2845836100446BB9 /* App */ = {
+		3242BD422921DC9E0045E647 /* AppFeature */ = {
 			isa = XCSwiftPackageProductDependency;
-			productName = App;
+			productName = AppFeature;
 		};
 /* End XCSwiftPackageProductDependency section */
 	};
diff --git a/App/client-ios/Resources/GoogleService-Info.plist b/App/client-ios/Resources/GoogleService-Info.plist
index 676030ed57400f2bf5a72dc61d4ba5ed3e5263cb..10566b5ece72bfa2c34ad23c1d289d327d757327 100644
--- a/App/client-ios/Resources/GoogleService-Info.plist
+++ b/App/client-ios/Resources/GoogleService-Info.plist
@@ -1,36 +1,36 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 <plist version="1.0">
-    <dict>
-        <key>CLIENT_ID</key>
-        <string>662236151640-herpu89qikpfs9m4kvbi9bs5fpdji5de.apps.googleusercontent.com</string>
-        <key>REVERSED_CLIENT_ID</key>
-        <string>com.googleusercontent.apps.662236151640-herpu89qikpfs9m4kvbi9bs5fpdji5de</string>
-        <key>ANDROID_CLIENT_ID</key>
-        <string>662236151640-2ughgo2dvc59dm4o39b45lbdungp2mct.apps.googleusercontent.com</string>
-        <key>API_KEY</key>
-        <string>AIzaSyCbI2yQ7pbuVSRvraqanjGcS9CDrjD7lNU</string>
-        <key>GCM_SENDER_ID</key>
-        <string>662236151640</string>
-        <key>PLIST_VERSION</key>
-        <string>1</string>
-        <key>BUNDLE_ID</key>
-        <string>io.xxlabs.messenger</string>
-        <key>PROJECT_ID</key>
-        <string>xx-messenger-6e03e</string>
-        <key>STORAGE_BUCKET</key>
-        <string>xx-messenger-6e03e.appspot.com</string>
-        <key>IS_ADS_ENABLED</key>
-        <false></false>
-        <key>IS_ANALYTICS_ENABLED</key>
-        <false></false>
-        <key>IS_APPINVITE_ENABLED</key>
-        <true></true>
-        <key>IS_GCM_ENABLED</key>
-        <true></true>
-        <key>IS_SIGNIN_ENABLED</key>
-        <true></true>
-        <key>GOOGLE_APP_ID</key>
-        <string>1:662236151640:ios:24badb58ab07515d8cef2d</string>
-    </dict>
+<dict>
+	<key>CLIENT_ID</key>
+	<string>662236151640-r1lrlppqdcmhb4p8urq32fo7784cdoal.apps.googleusercontent.com</string>
+	<key>REVERSED_CLIENT_ID</key>
+	<string>com.googleusercontent.apps.662236151640-r1lrlppqdcmhb4p8urq32fo7784cdoal</string>
+	<key>ANDROID_CLIENT_ID</key>
+	<string>662236151640-2ughgo2dvc59dm4o39b45lbdungp2mct.apps.googleusercontent.com</string>
+	<key>API_KEY</key>
+	<string>AIzaSyCbI2yQ7pbuVSRvraqanjGcS9CDrjD7lNU</string>
+	<key>GCM_SENDER_ID</key>
+	<string>662236151640</string>
+	<key>PLIST_VERSION</key>
+	<string>1</string>
+	<key>BUNDLE_ID</key>
+	<string>io.xxlabs.messenger</string>
+	<key>PROJECT_ID</key>
+	<string>xx-messenger-6e03e</string>
+	<key>STORAGE_BUCKET</key>
+	<string>xx-messenger-6e03e.appspot.com</string>
+	<key>IS_ADS_ENABLED</key>
+	<false/>
+	<key>IS_ANALYTICS_ENABLED</key>
+	<false/>
+	<key>IS_APPINVITE_ENABLED</key>
+	<true/>
+	<key>IS_GCM_ENABLED</key>
+	<true/>
+	<key>IS_SIGNIN_ENABLED</key>
+	<true/>
+	<key>GOOGLE_APP_ID</key>
+	<string>1:662236151640:ios:24badb58ab07515d8cef2d</string>
+</dict>
 </plist>
diff --git a/App/client-ios/main.swift b/App/client-ios/main.swift
index 00c22b5303b5134db6e20ca68475518f8105efc7..3d2972992b1778100134c827e9c22617f3837ad1 100644
--- a/App/client-ios/main.swift
+++ b/App/client-ios/main.swift
@@ -1,5 +1,5 @@
-import App
 import UIKit
+import AppFeature
 
 let appDelegate: String? =
     NSClassFromString("XCTestCase") == nil
diff --git a/Package.swift b/Package.swift
index 2162bd759f6d261ecd4b2a85b2329e4add3cbe79..79eb6ae391a45399efb0dce157a0239cdfa40c29 100644
--- a/Package.swift
+++ b/Package.swift
@@ -8,40 +8,38 @@ let package = Package(
     .iOS(.v14),
   ],
   products: [
-    .library(name: "App", targets: ["App"]),
     .library(name: "Shared", targets: ["Shared"]),
-    .library(name: "XXLogger", targets: ["XXLogger"]),
+    .library(name: "AppCore", targets: ["AppCore"]),
     .library(name: "Defaults", targets: ["Defaults"]),
     .library(name: "Keychain", targets: ["Keychain"]),
-    .library(name: "Voxophone", targets: ["Voxophone"]),
-    .library(name: "Countries", targets: ["Countries"]),
+    .library(name: "AppFeature", targets: ["AppFeature"]),
     .library(name: "InputField", targets: ["InputField"]),
     .library(name: "ScanFeature", targets: ["ScanFeature"]),
-    .library(name: "Permissions", targets: ["Permissions"]),
     .library(name: "MenuFeature", targets: ["MenuFeature"]),
     .library(name: "ChatFeature", targets: ["ChatFeature"]),
     .library(name: "PushFeature", targets: ["PushFeature"]),
+    .library(name: "AppResources", targets: ["AppResources"]),
     .library(name: "CrashService", targets: ["CrashService"]),
     .library(name: "TermsFeature", targets: ["TermsFeature"]),
-    .library(name: "Presentation", targets: ["Presentation"]),
     .library(name: "BackupFeature", targets: ["BackupFeature"]),
     .library(name: "LaunchFeature", targets: ["LaunchFeature"]),
     .library(name: "SearchFeature", targets: ["SearchFeature"]),
     .library(name: "DrawerFeature", targets: ["DrawerFeature"]),
-    .library(name: "CollectionView", targets: ["CollectionView"]),
     .library(name: "RestoreFeature", targets: ["RestoreFeature"]),
     .library(name: "CrashReporting", targets: ["CrashReporting"]),
     .library(name: "ProfileFeature", targets: ["ProfileFeature"]),
     .library(name: "ContactFeature", targets: ["ContactFeature"]),
-    .library(name: "NetworkMonitor", targets: ["NetworkMonitor"]),
-    .library(name: "VersionChecking", targets: ["VersionChecking"]),
     .library(name: "SettingsFeature", targets: ["SettingsFeature"]),
     .library(name: "ChatListFeature", targets: ["ChatListFeature"]),
     .library(name: "RequestsFeature", targets: ["RequestsFeature"]),
+    .library(name: "ReportingFeature", targets: ["ReportingFeature"]),
+    .library(name: "StatusBarFeature", targets: ["StatusBarFeature"]),
     .library(name: "ChatInputFeature", targets: ["ChatInputFeature"]),
     .library(name: "OnboardingFeature", targets: ["OnboardingFeature"]),
+    .library(name: "CountryListFeature", targets: ["CountryListFeature"]),
+    .library(name: "PermissionsFeature", targets: ["PermissionsFeature"]),
     .library(name: "ContactListFeature", targets: ["ContactListFeature"]),
-    .library(name: "ReportingFeature", targets: ["ReportingFeature"])
+    .library(name: "RequestPermissionFeature", targets: ["RequestPermissionFeature"]),
   ],
   dependencies: [
     .package(
@@ -72,10 +70,6 @@ let package = Package(
       url: "https://github.com/apple/swift-protobuf",
       .upToNextMajor(from: "1.14.0")
     ),
-    .package(
-      url: "https://github.com/SwiftyBeaver/SwiftyBeaver.git",
-      .upToNextMajor(from: "1.9.5")
-    ),
     .package(
       url: "https://github.com/darrarski/ScrollViewController",
       .upToNextMajor(from: "1.2.0")
@@ -106,7 +100,7 @@ let package = Package(
     ),
     .package(
       url: "https://github.com/pointfreeco/swift-composable-architecture.git",
-      .upToNextMajor(from: "0.32.0")
+      .upToNextMajor(from: "0.43.0")
     ),
     .package(
       url: "https://github.com/pointfreeco/swift-custom-dump.git",
@@ -116,25 +110,28 @@ let package = Package(
       url: "https://github.com/swiftcsv/SwiftCSV.git",
       from: "0.8.0"
     ),
+    .package(
+      url: "https://github.com/apple/swift-log.git",
+      .upToNextMajor(from: "1.4.4")
+    ),
     .package(
       url: "https://github.com/pointfreeco/xctest-dynamic-overlay.git",
       .upToNextMajor(from: "0.3.3")
     ),
     .package(
-      url: "https://git.xx.network/elixxir/xxm-di.git",
-      .upToNextMajor(from: "1.0.0")
+      path: "../xxm-navigation"
     ),
     .package(
-      path: "../xxm-navigation"
+      url: "https://git.xx.network/elixxir/xxm-di",
+      .upToNextMajor(from: "1.0.0")
     )
   ],
   targets: [
     .target(
-      name: "App",
+      name: "AppFeature",
       dependencies: [
+        .target(name: "AppCore"),
         .target(name: "Keychain"),
-        .target(name: "Voxophone"),
-        .target(name: "Permissions"),
         .target(name: "ScanFeature"),
         .target(name: "ChatFeature"),
         .target(name: "MenuFeature"),
@@ -154,26 +151,66 @@ let package = Package(
         .target(name: "ReportingFeature"),
         .target(name: "OnboardingFeature"),
         .target(name: "ContactListFeature"),
+        .target(name: "RequestPermissionFeature"),
         .product(name: "DependencyInjection", package: "xxm-di"),
       ]
     ),
     .testTarget(
-      name: "AppTests",
+      name: "AppFeatureTests",
+      dependencies: [
+        .target(name: "AppFeature"),
+      ]
+    ),
+    .target(
+      name: "AppCore",
       dependencies: [
-        .target(name: "App"),
+        .target(name: "Shared"),
+        .target(name: "AppResources"),
+        .target(name: "StatusBarFeature"),
+        .product(name: "SnapKit", package: "SnapKit"),
+        .product(name: "Logging", package: "swift-log"),
+        .product(name: "XXModels", package: "client-ios-db"),
+        .product(name: "XXDatabase", package: "client-ios-db"),
+        .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
+        .product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
+        .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"),
+        .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
       ]
     ),
     .target(
       name: "CrashReporting"
     ),
     .target(
-      name: "NetworkMonitor",
+      name: "PermissionsFeature",
       dependencies: [
-        .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
+        .product(
+          name: "XCTestDynamicOverlay",
+          package: "xctest-dynamic-overlay"
+        ),
+        .product(
+          name: "ComposableArchitecture",
+          package: "swift-composable-architecture"
+        ),
       ]
     ),
     .target(
-      name: "VersionChecking"
+      name: "StatusBarFeature",
+      dependencies: [
+        .product(
+          name: "XCTestDynamicOverlay",
+          package: "xctest-dynamic-overlay"
+        ),
+        .product(
+          name: "ComposableArchitecture",
+          package: "swift-composable-architecture"
+        ),
+      ]
+    ),
+    .target(
+      name: "AppResources",
+      resources: [
+        .process("Resources")
+      ]
     ),
     .target(
       name: "InputField",
@@ -182,11 +219,15 @@ let package = Package(
       ]
     ),
     .target(
-      name: "Permissions",
+      name: "RequestPermissionFeature",
       dependencies: [
         .target(name: "Shared"),
-        .product(name: "Navigation", package: "xxm-navigation"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
+        .target(name: "AppResources"),
+        .target(name: "PermissionsFeature"),
+        .product(
+          name: "ComposableArchitecture",
+          package: "swift-composable-architecture"
+        ),
       ]
     ),
     .target(
@@ -206,12 +247,6 @@ let package = Package(
         .product(name: "KeychainAccess", package: "KeychainAccess"),
       ]
     ),
-    .target(
-      name: "Voxophone",
-      dependencies: [
-        .target(name: "Shared"),
-      ]
-    ),
     .target(
       name: "Defaults",
       dependencies: [
@@ -226,10 +261,10 @@ let package = Package(
       ]
     ),
     .target(
-      name: "Countries",
+      name: "CountryListFeature",
       dependencies: [
         .target(name: "Shared"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
+        .target(name: "StatusBarFeature")
       ]
     ),
     .target(
@@ -240,12 +275,6 @@ let package = Package(
         .product(name: "ScrollViewController", package: "ScrollViewController"),
       ]
     ),
-    .target(
-      name: "XXLogger",
-      dependencies: [
-        .product(name: "SwiftyBeaver", package: "SwiftyBeaver"),
-      ]
-    ),
     .target(
       name: "Shared",
       dependencies: [
@@ -261,33 +290,19 @@ let package = Package(
         .process("Resources"),
       ]
     ),
-    .target(
-      name: "Presentation",
-      dependencies: [
-        .target(name: "Shared"),
-        .product(name: "SnapKit", package: "SnapKit"),
-      ]
-    ),
-    .testTarget(
-      name: "PresentationTests",
-      dependencies: [
-        .target(name: "Presentation"),
-        .product(name: "Quick", package: "Quick"),
-        .product(name: "Nimble", package: "Nimble"),
-      ]
-    ),
     .target(
       name: "ChatInputFeature",
       dependencies: [
-        .target(name: "Voxophone"),
-        .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
+        .product(
+          name: "ComposableArchitecture",
+          package: "swift-composable-architecture"
+        ),
       ]
     ),
     .target(
       name: "RestoreFeature",
       dependencies: [
         .target(name: "Shared"),
-        .target(name: "Presentation"),
         .product(name: "XXDatabase", package: "client-ios-db"),
         .product(name: "Navigation", package: "xxm-navigation"),
         .product(name: "DependencyInjection", package: "xxm-di"),
@@ -304,7 +319,6 @@ let package = Package(
         .target(name: "Shared"),
         .target(name: "InputField"),
         .target(name: "ChatFeature"),
-        .target(name: "Presentation"),
         .product(name: "CombineSchedulers", package: "combine-schedulers"),
         .product(name: "ScrollViewController", package: "ScrollViewController"),
       ]
@@ -315,29 +329,26 @@ let package = Package(
         .target(name: "Shared"),
         .target(name: "Defaults"),
         .target(name: "Keychain"),
-        .target(name: "Voxophone"),
-        .target(name: "Permissions"),
-        .target(name: "Presentation"),
         .target(name: "DrawerFeature"),
         .target(name: "ChatInputFeature"),
         .target(name: "ReportingFeature"),
+        .target(name: "RequestPermissionFeature"),
         .product(name: "DependencyInjection", package: "xxm-di"),
         .product(name: "ChatLayout", package: "ChatLayout"),
         .product(name: "DifferenceKit", package: "DifferenceKit"),
         .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
         .product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
         .product(name: "ScrollViewController", package: "ScrollViewController"),
+        .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"),
       ]
     ),
     .target(
       name: "SearchFeature",
       dependencies: [
         .target(name: "Shared"),
-        .target(name: "Countries"),
         .target(name: "PushFeature"),
-        .target(name: "Presentation"),
         .target(name: "ContactFeature"),
-        .target(name: "NetworkMonitor"),
+        .target(name: "CountryListFeature"),
         .product(name: "Retry", package: "Retry"),
         .product(name: "XXDatabase", package: "client-ios-db"),
         .product(name: "DependencyInjection", package: "xxm-di"),
@@ -349,11 +360,9 @@ let package = Package(
         .target(name: "Shared"),
         .target(name: "Defaults"),
         .target(name: "PushFeature"),
-        .target(name: "Permissions"),
         .target(name: "BackupFeature"),
-        .target(name: "VersionChecking"),
         .target(name: "ReportingFeature"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
+        .target(name: "RequestPermissionFeature"),
         .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
         .product(name: "CloudFilesSFTP", package: "xxm-cloud-providers"),
         .product(name: "CombineSchedulers", package: "combine-schedulers"),
@@ -367,7 +376,6 @@ let package = Package(
       dependencies: [
         .target(name: "Shared"),
         .target(name: "Defaults"),
-        .target(name: "Presentation"),
         .product(name: "Navigation", package: "xxm-navigation"),
       ]
     ),
@@ -386,13 +394,12 @@ let package = Package(
         .target(name: "Shared"),
         .target(name: "Keychain"),
         .target(name: "Defaults"),
-        .target(name: "Countries"),
         .target(name: "InputField"),
         .target(name: "MenuFeature"),
-        .target(name: "Permissions"),
-        .target(name: "Presentation"),
         .target(name: "DrawerFeature"),
         .target(name: "BackupFeature"),
+        .target(name: "CountryListFeature"),
+        .target(name: "RequestPermissionFeature"),
         .product(name: "Navigation", package: "xxm-navigation"),
         .product(name: "DependencyInjection", package: "xxm-di"),
         .product(name: "CombineSchedulers", package: "combine-schedulers"),
@@ -419,18 +426,17 @@ let package = Package(
       name: "OnboardingFeature",
       dependencies: [
         .target(name: "Shared"),
+        .target(name: "AppCore"),
         .target(name: "Defaults"),
         .target(name: "Keychain"),
-        .target(name: "Countries"),
         .target(name: "InputField"),
-        .target(name: "Permissions"),
         .target(name: "PushFeature"),
-        .target(name: "Presentation"),
         .target(name: "DrawerFeature"),
-        .target(name: "VersionChecking"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
+        .target(name: "CountryListFeature"),
+        .target(name: "RequestPermissionFeature"),
         .product(name: "CombineSchedulers", package: "combine-schedulers"),
         .product(name: "ScrollViewController", package: "ScrollViewController"),
+        .product(name: "ComposableArchitecture", package: "swift-composable-architecture"),
       ]
     ),
     .target(
@@ -438,7 +444,6 @@ let package = Package(
       dependencies: [
         .target(name: "Shared"),
         .target(name: "Defaults"),
-        .target(name: "Presentation"),
         .target(name: "DrawerFeature"),
         .target(name: "ReportingFeature"),
         .product(name: "Navigation", package: "xxm-navigation"),
@@ -450,29 +455,50 @@ let package = Package(
       name: "BackupFeature",
       dependencies: [
         .target(name: "Shared"),
+        .target(name: "AppCore"),
         .target(name: "InputField"),
-        .target(name: "Presentation"),
         .target(name: "DrawerFeature"),
-        .target(name: "NetworkMonitor"),
-        .product(name: "Navigation", package: "xxm-navigation"),
-        .product(name: "DependencyInjection", package: "xxm-di"),
-        .product(name: "XXClient", package: "elixxir-dapps-sdk-swift"),
-        .product(name: "CloudFilesSFTP", package: "xxm-cloud-providers"),
-        .product(name: "CloudFilesDrive", package: "xxm-cloud-providers"),
-        .product(name: "CloudFilesICloud", package: "xxm-cloud-providers"),
-        .product(name: "CloudFilesDropbox", package: "xxm-cloud-providers"),
-        .product(name: "XXMessengerClient", package: "elixxir-dapps-sdk-swift"),
+        .product(
+          name: "Navigation",
+          package: "xxm-navigation"
+        ),
+        .product(
+          name: "XXClient",
+          package: "elixxir-dapps-sdk-swift"
+        ),
+        .product(
+          name: "CloudFilesSFTP",
+          package: "xxm-cloud-providers"
+        ),
+        .product(
+          name: "CloudFilesDrive",
+          package: "xxm-cloud-providers"
+        ),
+        .product(
+          name: "CloudFilesICloud",
+          package: "xxm-cloud-providers"
+        ),
+        .product(
+          name: "CloudFilesDropbox",
+          package: "xxm-cloud-providers"
+        ),
+        .product(
+          name: "XXMessengerClient",
+          package: "elixxir-dapps-sdk-swift"
+        ),
+        .product(
+          name: "ComposableArchitecture",
+          package: "swift-composable-architecture"
+        ),
       ]
     ),
     .target(
       name: "ScanFeature",
       dependencies: [
         .target(name: "Shared"),
-        .target(name: "Countries"),
-        .target(name: "Permissions"),
-        .target(name: "Presentation"),
         .target(name: "ContactFeature"),
-        .target(name: "NetworkMonitor"),
+        .target(name: "CountryListFeature"),
+        .target(name: "RequestPermissionFeature"),
         .product(name: "DependencyInjection", package: "xxm-di"),
         .product(name: "SnapKit", package: "SnapKit"),
       ]
@@ -481,7 +507,6 @@ let package = Package(
       name: "ContactListFeature",
       dependencies: [
         .target(name: "Shared"),
-        .target(name: "Presentation"),
         .target(name: "ContactFeature"),
         .product(name: "DependencyInjection", package: "xxm-di"),
         .product(name: "DifferenceKit", package: "DifferenceKit"),
@@ -493,32 +518,16 @@ let package = Package(
         .target(name: "Shared"),
         .target(name: "Defaults"),
         .target(name: "Keychain"),
-        .target(name: "XXLogger"),
         .target(name: "InputField"),
         .target(name: "PushFeature"),
-        .target(name: "Permissions"),
         .target(name: "MenuFeature"),
-        .target(name: "Presentation"),
         .target(name: "DrawerFeature"),
+        .target(name: "RequestPermissionFeature"),
         .product(name: "DependencyInjection", package: "xxm-di"),
         .product(name: "CombineSchedulers", package: "combine-schedulers"),
         .product(name: "ScrollViewController", package: "ScrollViewController"),
       ]
     ),
-    .target(
-      name: "CollectionView",
-      dependencies: [
-        .product(name: "ChatLayout", package: "ChatLayout"),
-        .product(name: "XCTestDynamicOverlay", package: "xctest-dynamic-overlay"),
-      ]
-    ),
-    .testTarget(
-      name: "CollectionViewTests",
-      dependencies: [
-        .target(name: "CollectionView"),
-        .product(name: "CustomDump", package: "swift-custom-dump"),
-      ]
-    ),
     .target(
       name: "ReportingFeature",
       dependencies: [
diff --git a/Sources/App/DependencyRegistrator.swift b/Sources/App/DependencyRegistrator.swift
deleted file mode 100644
index f562bd38e398632c5c5539762316d0ee69dfda58..0000000000000000000000000000000000000000
--- a/Sources/App/DependencyRegistrator.swift
+++ /dev/null
@@ -1,316 +0,0 @@
-// MARK: SDK
-
-import UIKit
-import Network
-import QuickLook
-import MobileCoreServices
-
-// MARK: Isolated features
-
-import Bindings
-import XXLogger
-import Keychain
-import Defaults
-import Countries
-import Voxophone
-import Permissions
-import PushFeature
-import CrashService
-import CrashReporting
-import NetworkMonitor
-import VersionChecking
-import ReportingFeature
-import DI
-
-// MARK: UI Features
-
-import ScanFeature
-import ChatFeature
-import MenuFeature
-import TermsFeature
-import BackupFeature
-import DrawerFeature
-import SearchFeature
-import LaunchFeature
-import RestoreFeature
-import ContactFeature
-import ProfileFeature
-import ChatListFeature
-import SettingsFeature
-import RequestsFeature
-import OnboardingFeature
-import ContactListFeature
-
-import Shared
-import XXClient
-import Navigation
-import KeychainAccess
-import XXMessengerClient
-
-struct DependencyRegistrator {
-  static private let container = DI.Container.shared
-
-  static func registerDependencies() {
-    #if DEBUG
-    DependencyRegistrator.registerForMock()
-    #else
-    DependencyRegistrator.registerForLive()
-    #endif
-  }
-
-  // MARK: MOCK
-
-  static func registerForMock() {
-    container.register(XXLogger.noop)
-    container.register(VersionCheck.mock)
-    container.register(CrashReporter.noop)
-    container.register(ReportingStatus.mock())
-    container.register(SendReport.mock())
-    container.register(MockNetworkMonitor() as NetworkMonitoring)
-    container.register(KeyObjectStore.userDefaults)
-    container.register(MockPushHandler() as PushHandling)
-    container.register(MockKeychainHandler() as KeychainHandling)
-    container.register(MockPermissionHandler() as PermissionHandling)
-
-    registerCommonDependencies()
-  }
-
-  // MARK: LIVE
-
-  static func registerForLive() {
-    let cMixManager = CMixManager.live(passwordStorage: .keychain)
-    container.register(cMixManager)
-
-    container.register(GetIdFromContact.live)
-    container.register(GetFactsFromContact.live)
-
-    container.register(KeyObjectStore.userDefaults)
-    container.register(XXLogger.live())
-    container.register(VersionCheck.live)
-    container.register(CrashReporter.live)
-    container.register(ReportingStatus.live())
-    container.register(SendReport.live)
-
-    container.register(NetworkMonitor() as NetworkMonitoring)
-    container.register(PushHandler() as PushHandling)
-    container.register(KeychainHandler() as KeychainHandling)
-    container.register(PermissionHandler() as PermissionHandling)
-
-    registerCommonDependencies()
-  }
-
-  // MARK: COMMON
-
-  static public func registerNavigators(_ navController: UINavigationController) {
-    container.register(CombinedNavigator(
-      PresentModalNavigator(),
-      DismissModalNavigator(),
-      PushNavigator(),
-      PopToRootNavigator(),
-      PopToNavigator(),
-      SetStackNavigator(),
-
-      OpenUpNavigator(),
-      OpenLeftNavigator(),
-
-      PresentOnboardingStartNavigator(
-        screen: OnboardingStartController.init,
-        navigationController: { navController }
-      ),
-      PresentChatListNavigator(
-        screen: ChatListController.init,
-        navigationController: { navController }
-      ),
-      PresentTermsAndConditionsNavigator(
-        screen: TermsConditionsController.init,
-        navigationController: { navController }
-      ),
-      PresentSearchNavigator(
-        screen: SearchContainerController.init(_:),
-        navigationController: { navController }
-      ),
-      PresentRequestsNavigator(
-        screen: RequestsContainerController.init,
-        navigationController: { navController }
-      ),
-      PresentChatNavigator(
-        screen: SingleChatController.init(_:),
-        navigationController: { navController }
-      ),
-      PresentGroupChatNavigator(
-        screen: GroupChatController.init(_:),
-        navigationController: { navController }
-      ),
-      PresentOnboardingWelcomeNavigator(
-        screen: OnboardingWelcomeController.init,
-        navigationController: { navController }
-      ),
-      PresentOnboardingUsernameNavigator(
-        screen: OnboardingUsernameController.init,
-        navigationController: { navController }
-      ),
-      PresentRestoreListNavigator(
-        screen: RestoreListController.init,
-        navigationController: { navController }
-      ),
-      PresentOnboardingEmailNavigator(
-        screen: OnboardingEmailController.init,
-        navigationController: { navController }
-      ),
-      PresentOnboardingPhoneNavigator(
-        screen: OnboardingPhoneController.init,
-        navigationController: { navController }
-      ),
-      PresentOnboardingCodeNavigator(
-        screen: OnboardingCodeController.init(_:_:_:),
-        navigationController: { navController }
-      ),
-      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 }
-      )
-    ) as Navigator)
-  }
-
-  static private func registerCommonDependencies() {
-    var environment: MessengerEnvironment = .live()
-    environment.ndfEnvironment = .mainnet
-    environment.serviceList = .userDefaults(
-      key: "preImage",
-      userDefaults: UserDefaults(suiteName: "group.elixxir.messenger")!
-    )
-    environment.udEnvironment = .init(
-      address: AlternativeUDConstants.address,
-      cert: AlternativeUDConstants.cert.data(using: .utf8)!,
-      contact: AlternativeUDConstants.contact.data(using: .utf8)!
-    )
-    container.register(Messenger.live(environment))
-
-    container.register(Voxophone())
-    container.register(BackupService())
-    container.register(MakeAppScreenshot.live)
-    container.register(FetchBannedList.live)
-    container.register(ProcessBannedList.live)
-    container.register(MakeReportDrawer.live)
-
-    // MARK: Isolated
-
-    container.register(HUDController())
-    container.register(ToastController())
-    container.register(StatusBarStylist())
-  }
-}
-
-extension PasswordStorage {
-  static let keychain: PasswordStorage = {
-    let keychain = KeychainAccess.Keychain(
-      service: "XXM"
-    )
-    return PasswordStorage(
-      save: { password in keychain[data: "password"] = password},
-      load: { try keychain[data: "password"] ?? { throw MissingPasswordError() }() },
-      remove: { try keychain.remove("password") }
-    )
-  }()
-}
-
-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-----
-"""
-  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/App/PushRouter.swift b/Sources/App/PushRouter.swift
deleted file mode 100644
index acebc7b3677915766a6f302a46d2b65cbba3cf07..0000000000000000000000000000000000000000
--- a/Sources/App/PushRouter.swift
+++ /dev/null
@@ -1,57 +0,0 @@
-import UIKit
-import PushFeature
-import ChatFeature
-import SearchFeature
-import LaunchFeature
-import ChatListFeature
-import RequestsFeature
-import DI
-import XXModels
-import XXMessengerClient
-
-extension PushRouter {
-    static func live(navigationController: UINavigationController) -> PushRouter {
-        PushRouter { route, completion in
-            if let launchController = navigationController.viewControllers.last as? LaunchController {
-                launchController.pendingPushRoute = route
-            } else {
-                switch route {
-                case .requests:
-                    if !(navigationController.viewControllers.last is RequestsContainerController) {
-                        navigationController.setViewControllers([RequestsContainerController()], animated: true)
-                    }
-                case .search(username: let username):
-                    if let messenger = try? DI.Container.shared.resolve() as Messenger,
-                       let _ = try? messenger.ud.get()?.getContact() {
-                        if !(navigationController.viewControllers.last is SearchContainerController) {
-                            navigationController.setViewControllers([
-                                ChatListController(),
-                                SearchContainerController(username)
-                            ], animated: true)
-                        } else {
-                            (navigationController.viewControllers.last as? SearchContainerController)?.startSearchingFor(username)
-                        }
-                    }
-                case .contactChat(id: let id):
-                    if let database: Database = try? DI.Container.shared.resolve(),
-                       let contact = try? database.fetchContacts(.init(id: [id])).first {
-                        navigationController.setViewControllers([
-                            ChatListController(),
-                            SingleChatController(contact)
-                        ], animated: true)
-                    }
-                case .groupChat(id: let id):
-                    if let database: Database = try? DI.Container.shared.resolve(),
-                       let info = try? database.fetchGroupInfos(.init(groupId: id)).first {
-                        navigationController.setViewControllers([
-                            ChatListController(),
-                            GroupChatController(info)
-                        ], animated: true)
-                    }
-                }
-            }
-
-            completion()
-        }
-    }
-}
diff --git a/Sources/AppCore/AppDependencies.swift b/Sources/AppCore/AppDependencies.swift
new file mode 100644
index 0000000000000000000000000000000000000000..1f3ec64e5898e606f93ed1e8957a6f7a2279d3ba
--- /dev/null
+++ b/Sources/AppCore/AppDependencies.swift
@@ -0,0 +1,144 @@
+import Foundation
+import XXMessengerClient
+import XCTestDynamicOverlay
+import ComposableArchitecture
+
+public struct AppDependencies {
+  public var networkMonitor: NetworkMonitorManager
+  public var toastManager: ToastManager
+  public var hudManager: HUDManager
+  public var dbManager: DBManager
+  public var messenger: Messenger
+  public var authHandler: AuthCallbackHandler
+  public var backupStorage: BackupStorage
+  public var mainQueue: AnySchedulerOf<DispatchQueue>
+  public var bgQueue: AnySchedulerOf<DispatchQueue>
+  public var now: () -> Date
+  public var sendMessage: SendMessage
+  public var sendImage: SendImage
+  public var messageListener: MessageListenerHandler
+  public var receiveFileHandler: ReceiveFileHandler
+  public var log: Logger
+  public var loadData: URLDataLoader
+}
+
+extension AppDependencies {
+  public static func live() -> AppDependencies {
+    let dbManager = DBManager.live()
+    var messengerEnv = MessengerEnvironment.live()
+    messengerEnv.udEnvironment = .init(
+      address: Constants.address,
+      cert: Constants.cert.data(using: .utf8)!,
+      contact: Constants.contact.data(using: .utf8)!
+    )
+    messengerEnv.serviceList = .userDefaults(
+      key: "preImage",
+      userDefaults: UserDefaults(suiteName: "group.elixxir.messenger")!
+    )
+    let messenger = Messenger.live(messengerEnv)
+    let now: () -> Date = Date.init
+
+    return AppDependencies(
+      networkMonitor: .live(),
+      toastManager: .live(),
+      hudManager: .live(),
+      dbManager: dbManager,
+      messenger: messenger,
+      authHandler: .live(
+        messenger: messenger,
+        handleRequest: .live(db: dbManager.getDB, now: now),
+        handleConfirm: .live(db: dbManager.getDB),
+        handleReset: .live(db: dbManager.getDB)
+      ),
+      backupStorage: .onDisk(),
+      mainQueue: DispatchQueue.main.eraseToAnyScheduler(),
+      bgQueue: DispatchQueue.global(qos: .background).eraseToAnyScheduler(),
+      now: now,
+      sendMessage: .live(
+        messenger: messenger,
+        db: dbManager.getDB,
+        now: now
+      ),
+      sendImage: .live(
+        messenger: messenger,
+        db: dbManager.getDB,
+        now: now
+      ),
+      messageListener: .live(
+        messenger: messenger,
+        db: dbManager.getDB
+      ),
+      receiveFileHandler: .live(
+        messenger: messenger,
+        db: dbManager.getDB,
+        now: now
+      ),
+      log: .live(),
+      loadData: .live
+    )
+  }
+
+  public static let unimplemented = AppDependencies(
+    networkMonitor: .unimplemented,
+    toastManager: .unimplemented,
+    hudManager: .unimplemented,
+    dbManager: .unimplemented,
+    messenger: .unimplemented,
+    authHandler: .unimplemented,
+    backupStorage: .unimplemented,
+    mainQueue: .unimplemented,
+    bgQueue: .unimplemented,
+    now: XCTestDynamicOverlay.unimplemented(
+      "\(Self.self)",
+      placeholder: Date(timeIntervalSince1970: 0)
+    ),
+    sendMessage: .unimplemented,
+    sendImage: .unimplemented,
+    messageListener: .unimplemented,
+    receiveFileHandler: .unimplemented,
+    log: .unimplemented,
+    loadData: .unimplemented
+  )
+}
+
+private enum AppDependenciesKey: DependencyKey {
+  static let liveValue: AppDependencies = .live()
+  static let testValue: AppDependencies = .unimplemented
+}
+
+extension DependencyValues {
+  public var app: AppDependencies {
+    get { self[AppDependenciesKey.self] }
+    set { self[AppDependenciesKey.self] = newValue }
+  }
+}
+
+private enum Constants {
+  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-----
+"""
+  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/AppCore/AuthCallbackHandler/AuthCallbackHandler.swift b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandler.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c6e03cbedb7f1d0020d11a94c6fc0172a5fc5247
--- /dev/null
+++ b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandler.swift
@@ -0,0 +1,49 @@
+import Foundation
+import XCTestDynamicOverlay
+import XXClient
+import XXMessengerClient
+import XXModels
+
+public struct AuthCallbackHandler {
+  public typealias OnError = (Error) -> Void
+
+  public var run: (@escaping OnError) -> Cancellable
+
+  public func callAsFunction(onError: @escaping OnError) -> Cancellable {
+    run(onError)
+  }
+}
+
+extension AuthCallbackHandler {
+  public static func live(
+    messenger: Messenger,
+    handleRequest: AuthCallbackHandlerRequest,
+    handleConfirm: AuthCallbackHandlerConfirm,
+    handleReset: AuthCallbackHandlerReset
+  ) -> AuthCallbackHandler {
+    AuthCallbackHandler { onError in
+      messenger.registerAuthCallbacks(.init { callback in
+        do {
+          switch callback {
+          case .request(let contact, _, _, _):
+            try handleRequest(contact)
+
+          case .confirm(let contact, _, _, _):
+            try handleConfirm(contact)
+
+          case .reset(let contact, _, _, _):
+            try handleReset(contact)
+          }
+        } catch {
+          onError(error)
+        }
+      })
+    }
+  }
+}
+
+extension AuthCallbackHandler {
+  public static let unimplemented = AuthCallbackHandler(
+    run: XCTUnimplemented("\(Self.self)", placeholder: Cancellable {})
+  )
+}
diff --git a/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerConfirm.swift b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerConfirm.swift
new file mode 100644
index 0000000000000000000000000000000000000000..2aa6787fff741651d649fb8f88397669b448d92f
--- /dev/null
+++ b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerConfirm.swift
@@ -0,0 +1,31 @@
+import Foundation
+import XCTestDynamicOverlay
+import XXClient
+import XXModels
+
+public struct AuthCallbackHandlerConfirm {
+  public var run: (XXClient.Contact) throws -> Void
+
+  public func callAsFunction(_ contact: XXClient.Contact) throws {
+    try run(contact)
+  }
+}
+
+extension AuthCallbackHandlerConfirm {
+  public static func live(db: DBManagerGetDB) -> AuthCallbackHandlerConfirm {
+    AuthCallbackHandlerConfirm { xxContact in
+      let id = try xxContact.getId()
+      guard var dbContact = try db().fetchContacts(.init(id: [id])).first else {
+        return
+      }
+      dbContact.authStatus = .friend
+      dbContact = try db().saveContact(dbContact)
+    }
+  }
+}
+
+extension AuthCallbackHandlerConfirm {
+  public static let unimplemented = AuthCallbackHandlerConfirm(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerRequest.swift b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerRequest.swift
new file mode 100644
index 0000000000000000000000000000000000000000..6d1943e923732bc6dbdafe053deeb962191b7d13
--- /dev/null
+++ b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerRequest.swift
@@ -0,0 +1,41 @@
+import Foundation
+import XCTestDynamicOverlay
+import XXClient
+import XXMessengerClient
+import XXModels
+
+public struct AuthCallbackHandlerRequest {
+  public var run: (XXClient.Contact) throws -> Void
+
+  public func callAsFunction(_ contact: XXClient.Contact) throws {
+    try run(contact)
+  }
+}
+
+extension AuthCallbackHandlerRequest {
+  public static func live(
+    db: DBManagerGetDB,
+    now: @escaping () -> Date
+  ) -> AuthCallbackHandlerRequest {
+    AuthCallbackHandlerRequest { xxContact in
+      let id = try xxContact.getId()
+      guard try db().fetchContacts(.init(id: [id])).isEmpty else {
+        return
+      }
+      var dbContact = XXModels.Contact(id: id)
+      dbContact.marshaled = xxContact.data
+      dbContact.username = try xxContact.getFact(.username)?.value
+      dbContact.email = try xxContact.getFact(.email)?.value
+      dbContact.phone = try xxContact.getFact(.phone)?.value
+      dbContact.authStatus = .stranger
+      dbContact.createdAt = now()
+      dbContact = try db().saveContact(dbContact)
+    }
+  }
+}
+
+extension AuthCallbackHandlerRequest {
+  public static let unimplemented = AuthCallbackHandlerRequest(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerReset.swift b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerReset.swift
new file mode 100644
index 0000000000000000000000000000000000000000..a894b5e79200fb13b3986840410492050510e768
--- /dev/null
+++ b/Sources/AppCore/AuthCallbackHandler/AuthCallbackHandlerReset.swift
@@ -0,0 +1,31 @@
+import Foundation
+import XCTestDynamicOverlay
+import XXClient
+import XXModels
+
+public struct AuthCallbackHandlerReset {
+  public var run: (XXClient.Contact) throws -> Void
+
+  public func callAsFunction(_ contact: XXClient.Contact) throws {
+    try run(contact)
+  }
+}
+
+extension AuthCallbackHandlerReset {
+  public static func live(db: DBManagerGetDB) -> AuthCallbackHandlerReset {
+    AuthCallbackHandlerReset { xxContact in
+      let id = try xxContact.getId()
+      guard var dbContact = try db().fetchContacts(.init(id: [id])).first else {
+        return
+      }
+      dbContact.authStatus = .friend
+      dbContact = try db().saveContact(dbContact)
+    }
+  }
+}
+
+extension AuthCallbackHandlerReset {
+  public static let unimplemented = AuthCallbackHandlerReset(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/DBManager/DBManager.swift b/Sources/AppCore/DBManager/DBManager.swift
new file mode 100644
index 0000000000000000000000000000000000000000..b66fb3d731f3cb53cfb463ae84b516e98927430d
--- /dev/null
+++ b/Sources/AppCore/DBManager/DBManager.swift
@@ -0,0 +1,40 @@
+import XXModels
+import Foundation
+
+public struct DBManager {
+  public var hasDB: DBManagerHasDB
+  public var makeDB: DBManagerMakeDB
+  public var getDB: DBManagerGetDB
+  public var removeDB: DBManagerRemoveDB
+}
+
+extension DBManager {
+  public static func live(
+    url: URL = FileManager.default
+      .urls(for: .applicationSupportDirectory, in: .userDomainMask)
+      .first!
+      .appendingPathComponent("database")
+  ) -> DBManager {
+    class Container {
+      var db: Database?
+    }
+
+    let container = Container()
+
+    return DBManager(
+      hasDB: .init { container.db != nil },
+      makeDB: .live(url: url, setDB: { container.db = $0 }),
+      getDB: .live(getDB: { container.db }),
+      removeDB: .live(url: url, getDB: { container.db }, unsetDB: { container.db = nil })
+    )
+  }
+}
+
+extension DBManager {
+  public static let unimplemented = DBManager(
+    hasDB: .unimplemented,
+    makeDB: .unimplemented,
+    getDB: .unimplemented,
+    removeDB: .unimplemented
+  )
+}
diff --git a/Sources/AppCore/DBManager/DBManagerGetDB.swift b/Sources/AppCore/DBManager/DBManagerGetDB.swift
new file mode 100644
index 0000000000000000000000000000000000000000..aae596a1b98cf5993181400242ab4ce11189b3e6
--- /dev/null
+++ b/Sources/AppCore/DBManager/DBManagerGetDB.swift
@@ -0,0 +1,33 @@
+import XXModels
+import XCTestDynamicOverlay
+
+public struct DBManagerGetDB {
+  public enum Error: Swift.Error, Equatable {
+    case missingDB
+  }
+
+  public var run: () throws -> Database
+
+  public func callAsFunction() throws -> Database {
+    try run()
+  }
+}
+
+extension DBManagerGetDB {
+  public static func live(
+    getDB: @escaping () -> Database?
+  ) -> DBManagerGetDB {
+    DBManagerGetDB {
+      guard let db = getDB() else {
+        throw Error.missingDB
+      }
+      return db
+    }
+  }
+}
+
+extension DBManagerGetDB {
+  public static let unimplemented = DBManagerGetDB(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/DBManager/DBManagerHasDB.swift b/Sources/AppCore/DBManager/DBManagerHasDB.swift
new file mode 100644
index 0000000000000000000000000000000000000000..12fb1bb34ca0882404bf765f640e61496cbaedd5
--- /dev/null
+++ b/Sources/AppCore/DBManager/DBManagerHasDB.swift
@@ -0,0 +1,19 @@
+import XCTestDynamicOverlay
+
+public struct DBManagerHasDB {
+  init(run: @escaping () -> Bool) {
+    self.run = run
+  }
+
+  public var run: () -> Bool
+
+  public func callAsFunction() -> Bool {
+    run()
+  }
+}
+
+extension DBManagerHasDB {
+  public static let unimplemented = DBManagerHasDB(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/DBManager/DBManagerMakeDB.swift b/Sources/AppCore/DBManager/DBManagerMakeDB.swift
new file mode 100644
index 0000000000000000000000000000000000000000..4376f12fb3e5630ce0f9d05cd27474b9dd75515c
--- /dev/null
+++ b/Sources/AppCore/DBManager/DBManagerMakeDB.swift
@@ -0,0 +1,37 @@
+import XXModels
+import Foundation
+import XXDatabase
+import XCTestDynamicOverlay
+
+public struct DBManagerMakeDB {
+  public var run: () throws -> Void
+
+  public func callAsFunction() throws -> Void {
+    try run()
+  }
+}
+
+extension DBManagerMakeDB {
+  public static func live(
+    url: URL,
+    setDB: @escaping (Database) -> Void
+  ) -> DBManagerMakeDB {
+    DBManagerMakeDB {
+      try? FileManager.default
+        .createDirectory(at: url, withIntermediateDirectories: true)
+
+      let dbFilePath = url
+        .appendingPathComponent("db")
+        .appendingPathExtension("sqlite")
+        .path
+
+      setDB(try Database.onDisk(path: dbFilePath))
+    }
+  }
+}
+
+extension DBManagerMakeDB {
+  public static let unimplemented = DBManagerMakeDB(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/DBManager/DBManagerRemoveDB.swift b/Sources/AppCore/DBManager/DBManagerRemoveDB.swift
new file mode 100644
index 0000000000000000000000000000000000000000..9b6c14d4830d63fd70f8e54ac977fa652df28495
--- /dev/null
+++ b/Sources/AppCore/DBManager/DBManagerRemoveDB.swift
@@ -0,0 +1,36 @@
+import XXModels
+import Foundation
+import XXDatabase
+import XCTestDynamicOverlay
+
+public struct DBManagerRemoveDB {
+  public var run: () throws -> Void
+
+  public func callAsFunction() throws -> Void {
+    try run()
+  }
+}
+
+extension DBManagerRemoveDB {
+  public static func live(
+    url: URL,
+    getDB: @escaping () -> Database?,
+    unsetDB: @escaping () -> Void
+  ) -> DBManagerRemoveDB {
+    DBManagerRemoveDB {
+      let db = getDB()
+      unsetDB()
+      try db?.drop()
+      let fm = FileManager.default
+      if fm.fileExists(atPath: url.path) {
+        try fm.removeItem(atPath: url.path)
+      }
+    }
+  }
+}
+
+extension DBManagerRemoveDB {
+  public static let unimplemented = DBManagerRemoveDB(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/HUDManager/HUDHide.swift b/Sources/AppCore/HUDManager/HUDHide.swift
new file mode 100644
index 0000000000000000000000000000000000000000..fe96ef1faacb7a9c59d58b96407a1de8573bc77d
--- /dev/null
+++ b/Sources/AppCore/HUDManager/HUDHide.swift
@@ -0,0 +1,19 @@
+import XCTestDynamicOverlay
+
+public struct HUDHide {
+  init(run: @escaping () -> Void) {
+    self.run = run
+  }
+
+  public var run: () -> Void
+
+  public func callAsFunction() -> Void {
+    run()
+  }
+}
+
+extension HUDHide {
+  public static let unimplemented = HUDHide(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/HUDManager/HUDManager.swift b/Sources/AppCore/HUDManager/HUDManager.swift
new file mode 100644
index 0000000000000000000000000000000000000000..2c402e3b6b55677fbb3066ddb32777fd20d8224b
--- /dev/null
+++ b/Sources/AppCore/HUDManager/HUDManager.swift
@@ -0,0 +1,49 @@
+import Combine
+import Foundation
+import XCTestDynamicOverlay
+
+public struct HUDManager {
+  public var show: HUDShow
+  public var hide: HUDHide
+  public var observe: HUDObserve
+}
+
+extension HUDManager {
+  public static func live() -> HUDManager {
+    class Context {
+      var timer: Timer?
+      let modelSubject = PassthroughSubject<HUDModel?, Never>()
+    }
+
+    let context = Context()
+
+    return .init(
+      show: .init {
+        guard let model = $0 else {
+          context.modelSubject.send(.init(hasDotAnimation: true))
+          return
+        }
+        if model.isAutoDismissable {
+          DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
+            context.modelSubject.send(nil)
+          }
+        }
+        context.modelSubject.send(model)
+      },
+      hide: .init {
+        context.modelSubject.send(nil)
+      },
+      observe: .init {
+        context.modelSubject.eraseToAnyPublisher()
+      }
+    )
+  }
+}
+
+extension HUDManager {
+  public static let unimplemented = HUDManager(
+    show: .unimplemented,
+    hide: .unimplemented,
+    observe: .unimplemented
+  )
+}
diff --git a/Sources/AppCore/HUDManager/HUDObserve.swift b/Sources/AppCore/HUDManager/HUDObserve.swift
new file mode 100644
index 0000000000000000000000000000000000000000..c4257fdfc52b9d49bd199747a033cb51ccd18904
--- /dev/null
+++ b/Sources/AppCore/HUDManager/HUDObserve.swift
@@ -0,0 +1,16 @@
+import Combine
+import XCTestDynamicOverlay
+
+public struct HUDObserve {
+  public var run: () -> AnyPublisher<HUDModel?, Never>
+
+  public func callAsFunction() -> AnyPublisher<HUDModel?, Never> {
+    run()
+  }
+}
+
+extension HUDObserve {
+  public static let unimplemented = HUDObserve(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/HUDManager/HUDShow.swift b/Sources/AppCore/HUDManager/HUDShow.swift
new file mode 100644
index 0000000000000000000000000000000000000000..81038e4e2799a5681c0de3aa92ad0816ff77646b
--- /dev/null
+++ b/Sources/AppCore/HUDManager/HUDShow.swift
@@ -0,0 +1,19 @@
+import XCTestDynamicOverlay
+
+public struct HUDShow {
+  init(run: @escaping (HUDModel?) -> Void) {
+    self.run = run
+  }
+
+  public var run: (HUDModel?) -> Void
+
+  public func callAsFunction(_ model: HUDModel? = nil) -> Void {
+    run(model)
+  }
+}
+
+extension HUDShow {
+  public static let unimplemented = HUDShow(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/Logger/Logger.swift b/Sources/AppCore/Logger/Logger.swift
new file mode 100644
index 0000000000000000000000000000000000000000..fbb48f0d2dff23711420e5d7bf80bc3c8a160198
--- /dev/null
+++ b/Sources/AppCore/Logger/Logger.swift
@@ -0,0 +1,43 @@
+import Logging
+import Foundation
+import XCTestDynamicOverlay
+
+public struct Logger {
+  public enum Message: Equatable {
+    case error(NSError)
+  }
+
+  public var run: (Message, String, String, UInt) -> Void
+
+  public func callAsFunction(
+    _ msg: Message,
+    file: String = #file,
+    function: String = #function,
+    line: UInt = #line
+  ) {
+    run(msg, file, function, line)
+  }
+}
+
+extension Logger {
+  public static func live() -> Logger {
+    let logger = Logging.Logger(label: "xx.messenger")
+    return Logger { msg, file, function, line in
+      switch msg {
+      case .error(let error):
+        logger.error(
+          .init(stringLiteral: error.localizedDescription),
+          file: file,
+          function: function,
+          line: line
+        )
+      }
+    }
+  }
+}
+
+extension Logger {
+  public static let unimplemented = Logger(
+    run: XCTUnimplemented("\(Self.self).error")
+  )
+}
diff --git a/Sources/AppCore/MessageListenerHandler/MessageListenerHandler.swift b/Sources/AppCore/MessageListenerHandler/MessageListenerHandler.swift
new file mode 100644
index 0000000000000000000000000000000000000000..70fbace772986d506de4ee2338445a7c656bae8e
--- /dev/null
+++ b/Sources/AppCore/MessageListenerHandler/MessageListenerHandler.swift
@@ -0,0 +1,50 @@
+import Foundation
+import XCTestDynamicOverlay
+import XXClient
+import XXMessengerClient
+import XXModels
+
+public struct MessageListenerHandler {
+  public typealias OnError = (Error) -> Void
+
+  public var run: (@escaping OnError) -> Cancellable
+
+  public func callAsFunction(onError: @escaping OnError) -> Cancellable {
+    run(onError)
+  }
+}
+
+extension MessageListenerHandler {
+  public static func live(
+    messenger: Messenger,
+    db: DBManagerGetDB
+  ) -> MessageListenerHandler {
+    MessageListenerHandler { onError in
+      let listener = Listener { message in
+        do {
+          let payload = try MessagePayload.decode(message.payload)
+          try db().saveMessage(.init(
+            networkId: message.id,
+            senderId: message.sender,
+            recipientId: message.recipientId,
+            groupId: nil,
+            date: Date(timeIntervalSince1970: TimeInterval(message.timestamp) / 1_000_000_000),
+            status: .received,
+            isUnread: true,
+            text: payload.text,
+            roundURL: message.roundURL
+          ))
+        } catch {
+          onError(error)
+        }
+      }
+      return messenger.registerMessageListener(listener)
+    }
+  }
+}
+
+extension MessageListenerHandler {
+  public static let unimplemented = MessageListenerHandler(
+    run: XCTUnimplemented("\(Self.self)", placeholder: Cancellable {})
+  )
+}
diff --git a/Sources/Shared/Models/HUDModel.swift b/Sources/AppCore/Models/HUDModel.swift
similarity index 98%
rename from Sources/Shared/Models/HUDModel.swift
rename to Sources/AppCore/Models/HUDModel.swift
index c77d5607aca8b33031373e17d47d087d36aedce8..8d2679e6e870fa7507d8593ae683ee3b76ab0fcb 100644
--- a/Sources/Shared/Models/HUDModel.swift
+++ b/Sources/AppCore/Models/HUDModel.swift
@@ -1,4 +1,5 @@
 import UIKit
+import AppResources
 
 public struct HUDModel {
   var title: String?
diff --git a/Sources/AppCore/Models/MessagePayload.swift b/Sources/AppCore/Models/MessagePayload.swift
new file mode 100644
index 0000000000000000000000000000000000000000..67fb94d905b06ad25816ca8c4d11081c72053f19
--- /dev/null
+++ b/Sources/AppCore/Models/MessagePayload.swift
@@ -0,0 +1,23 @@
+import Foundation
+
+public struct MessagePayload: Equatable {
+  public init(text: String) {
+    self.text = text
+  }
+
+  public var text: String
+}
+
+extension MessagePayload: Codable {
+  enum CodingKeys: String, CodingKey {
+    case text
+  }
+
+  public static func decode(_ data: Data) throws -> Self {
+    try JSONDecoder().decode(Self.self, from: data)
+  }
+
+  public func encode() throws -> Data {
+    try JSONEncoder().encode(self)
+  }
+}
diff --git a/Sources/AppCore/Models/ToastModel.swift b/Sources/AppCore/Models/ToastModel.swift
new file mode 100644
index 0000000000000000000000000000000000000000..7758f11c162fa0931b0fe344c4319a934f5f29ed
--- /dev/null
+++ b/Sources/AppCore/Models/ToastModel.swift
@@ -0,0 +1,36 @@
+import UIKit
+import AppResources
+
+public struct ToastModel {
+  let id: UUID
+  let title: String
+  let color: UIColor
+  let subtitle: String?
+  let leftImage: UIImage
+  let timeToLive: Int
+  let buttonTitle: String?
+  let autodismissable: Bool
+  let onTapClosure: (() -> Void)?
+  
+  public init(
+    id: UUID = UUID(),
+    title: String,
+    color: UIColor = Asset.neutralOverlay.color,
+    subtitle: String? = nil,
+    leftImage: UIImage,
+    timeToLive: Int = 4,
+    buttonTitle: String? = nil,
+    onTapClosure: (() -> Void)? = nil,
+    autodismissable: Bool = true
+  ) {
+    self.id = id
+    self.title = title
+    self.color = color
+    self.subtitle = subtitle
+    self.leftImage = leftImage
+    self.timeToLive = timeToLive
+    self.buttonTitle = buttonTitle
+    self.onTapClosure = onTapClosure
+    self.autodismissable = autodismissable
+  }
+}
diff --git a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorConnType.swift b/Sources/AppCore/NetworkMonitorManager/NetworkMonitorConnType.swift
new file mode 100644
index 0000000000000000000000000000000000000000..8340f33fd448d9dfd87d76c30dc736a452375c38
--- /dev/null
+++ b/Sources/AppCore/NetworkMonitorManager/NetworkMonitorConnType.swift
@@ -0,0 +1,19 @@
+import XCTestDynamicOverlay
+
+public struct NetworkMonitorConnType {
+  public init(run: @escaping () -> NetworkMonitorManager.ConnType) {
+    self.run = run
+  }
+
+  public var run: () -> NetworkMonitorManager.ConnType
+
+  public func callAsFunction() -> NetworkMonitorManager.ConnType {
+    run()
+  }
+}
+
+extension NetworkMonitorConnType {
+  public static let unimplemented = NetworkMonitorConnType(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorManager.swift b/Sources/AppCore/NetworkMonitorManager/NetworkMonitorManager.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e77d4c63087711bff028f6cd78f1b896b399a888
--- /dev/null
+++ b/Sources/AppCore/NetworkMonitorManager/NetworkMonitorManager.swift
@@ -0,0 +1,77 @@
+import Combine
+import Network
+
+public struct NetworkMonitorManager {
+  public enum Status: Equatable {
+    case unknown
+    case available
+    case xxNotAvailable
+    case internetNotAvailable
+  }
+  public enum ConnType: Equatable {
+    case unknown
+    case wifi
+    case ethernet
+    case cellular
+  }
+
+  public var start: NetworkMonitorStart
+  public var update: NetworkMonitorUpdate
+  public var status: NetworkMonitorStatus
+  public var connType: NetworkMonitorConnType
+}
+
+extension NetworkMonitorManager {
+  public static func live() -> NetworkMonitorManager {
+    class Context {
+      var monitor = NWPathMonitor()
+      let xxAvailability = CurrentValueSubject<Bool?, Never>(nil)
+      let internetAvailability = CurrentValueSubject<Bool?, Never>(nil)
+      let currentConnType = CurrentValueSubject<ConnType, Never>(.unknown)
+    }
+
+    let context = Context()
+
+    return .init(
+      start: .init {
+        context.monitor.pathUpdateHandler = {
+          let currentInterface: ConnType
+
+          if $0.usesInterfaceType(.wifi) {
+            currentInterface = .wifi
+          } else if $0.usesInterfaceType(.wiredEthernet) {
+            currentInterface = .ethernet
+          } else if $0.usesInterfaceType(.cellular) {
+            currentInterface = .cellular
+          } else {
+            currentInterface = .unknown
+          }
+          context.currentConnType.send(currentInterface)
+          context.internetAvailability.send($0.status == .satisfied)
+        }
+        context.monitor.start(queue: .global())
+      },
+      update: .init {
+        context.xxAvailability.send($0)
+      },
+      status: .init {
+        guard let xxAvailability = context.xxAvailability.value else {
+          return .xxNotAvailable
+        }
+        return xxAvailability ? .available : .xxNotAvailable
+      },
+      connType: .init {
+        context.currentConnType.value
+      }
+    )
+  }
+}
+
+extension NetworkMonitorManager {
+  public static let unimplemented = NetworkMonitorManager(
+    start: .unimplemented,
+    update: .unimplemented,
+    status: .unimplemented,
+    connType: .unimplemented
+  )
+}
diff --git a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorStart.swift b/Sources/AppCore/NetworkMonitorManager/NetworkMonitorStart.swift
new file mode 100644
index 0000000000000000000000000000000000000000..4bb08bdbdd23a28b04c3b7f1a13bfbf53995e0a1
--- /dev/null
+++ b/Sources/AppCore/NetworkMonitorManager/NetworkMonitorStart.swift
@@ -0,0 +1,20 @@
+import XCTestDynamicOverlay
+
+public struct NetworkMonitorStart {
+  public init(run: @escaping () -> Void) {
+    self.run = run
+  }
+
+  public var run: () -> Void
+
+  public func callAsFunction() -> Void {
+    run()
+  }
+}
+
+extension NetworkMonitorStart {
+  public static let unimplemented = NetworkMonitorStart(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
+
diff --git a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorStatus.swift b/Sources/AppCore/NetworkMonitorManager/NetworkMonitorStatus.swift
new file mode 100644
index 0000000000000000000000000000000000000000..afc3169ce97622e94ec6bf74259512cc3e378d44
--- /dev/null
+++ b/Sources/AppCore/NetworkMonitorManager/NetworkMonitorStatus.swift
@@ -0,0 +1,19 @@
+import XCTestDynamicOverlay
+
+public struct NetworkMonitorStatus {
+  public init(run: @escaping () -> NetworkMonitorManager.Status) {
+    self.run = run
+  }
+
+  public var run: () -> NetworkMonitorManager.Status
+
+  public func callAsFunction() -> NetworkMonitorManager.Status {
+    run()
+  }
+}
+
+extension NetworkMonitorStatus {
+  public static let unimplemented = NetworkMonitorStatus(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/NetworkMonitorManager/NetworkMonitorUpdate.swift b/Sources/AppCore/NetworkMonitorManager/NetworkMonitorUpdate.swift
new file mode 100644
index 0000000000000000000000000000000000000000..6659aad330ce06f45306cd484c24835d67d83e30
--- /dev/null
+++ b/Sources/AppCore/NetworkMonitorManager/NetworkMonitorUpdate.swift
@@ -0,0 +1,19 @@
+import XCTestDynamicOverlay
+
+public struct NetworkMonitorUpdate {
+  public init(run: @escaping (Bool) -> Void) {
+    self.run = run
+  }
+
+  public var run: (Bool) -> Void
+
+  public func callAsFunction(_ status: Bool) -> Void {
+    run(status)
+  }
+}
+
+extension NetworkMonitorUpdate {
+  public static let unimplemented = NetworkMonitorUpdate(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/ReceiveFileHandler/ReceiveFileHandler.swift b/Sources/AppCore/ReceiveFileHandler/ReceiveFileHandler.swift
new file mode 100644
index 0000000000000000000000000000000000000000..187963707ea131e8f10de1e3dcf0ea0de4972620
--- /dev/null
+++ b/Sources/AppCore/ReceiveFileHandler/ReceiveFileHandler.swift
@@ -0,0 +1,117 @@
+import XXModels
+import XXClient
+import Foundation
+import XXMessengerClient
+import XCTestDynamicOverlay
+
+public struct ReceiveFileHandler {
+  public typealias OnError = (Error) -> Void
+
+  public var run: (@escaping OnError) -> Cancellable
+
+  public func callAsFunction(onError: @escaping OnError) -> Cancellable {
+    run(onError)
+  }
+}
+
+extension ReceiveFileHandler {
+  public static func live(
+    messenger: Messenger,
+    db: DBManagerGetDB,
+    now: @escaping () -> Date
+  ) -> ReceiveFileHandler {
+    ReceiveFileHandler { onError in
+      func receiveFile(_ file: ReceivedFile) {
+        do {
+          let date = now()
+          try db().saveFileTransfer(XXModels.FileTransfer(
+            id: file.transferId,
+            contactId: file.senderId,
+            name: file.name,
+            type: file.type,
+            data: nil,
+            progress: 0,
+            isIncoming: true,
+            createdAt: date
+          ))
+          try db().saveMessage(XXModels.Message(
+            senderId: file.senderId,
+            recipientId: try messenger.e2e.tryGet().getContact().getId(),
+            groupId: nil,
+            date: date,
+            status: .received,
+            isUnread: false,
+            text: "",
+            fileTransferId: file.transferId
+          ))
+          try messenger.receiveFile(.init(
+            transferId: file.transferId,
+            callbackIntervalMS: 500
+          )) { info in
+            switch info {
+            case .progress(let transmitted, let total):
+              updateProgress(
+                transferId: file.transferId,
+                transmitted: transmitted,
+                total: total
+              )
+
+            case .finished(let data):
+              saveData(
+                transferId: file.transferId,
+                data: data
+              )
+
+            case .failed(.receive(let error)):
+              onError(error)
+
+            case .failed(.callback(let error)):
+              onError(error)
+            }
+          }
+        } catch {
+          onError(error)
+        }
+      }
+
+      func updateProgress(transferId: Data, transmitted: Int, total: Int) {
+        do {
+          if var transfer = try db().fetchFileTransfers(.init(id: [transferId])).first {
+            transfer.progress = total > 0 ? Float(transmitted) / Float(total) : 0
+            try db().saveFileTransfer(transfer)
+          }
+        } catch {
+          onError(error)
+        }
+      }
+
+      func saveData(transferId: Data, data: Data) {
+        do {
+          if var transfer = try db().fetchFileTransfers(.init(id: [transferId])).first {
+            transfer.progress = 1
+            transfer.data = data
+            try db().saveFileTransfer(transfer)
+          }
+        } catch {
+          onError(error)
+        }
+      }
+
+      return messenger.registerReceiveFileCallback(.init { result in
+        switch result {
+        case .success(let file):
+          receiveFile(file)
+
+        case .failure(let error):
+          onError(error)
+        }
+      })
+    }
+  }
+}
+
+extension ReceiveFileHandler {
+  public static let unimplemented = ReceiveFileHandler(
+    run: XCTUnimplemented("\(Self.self)", placeholder: Cancellable {})
+  )
+}
diff --git a/Sources/Shared/Controllers/RootViewController.swift b/Sources/AppCore/RootViewController.swift
similarity index 92%
rename from Sources/Shared/Controllers/RootViewController.swift
rename to Sources/AppCore/RootViewController.swift
index a0ca01e577f3a811e501414f0cf6ce3d21c169f6..eb7db899e63a9c1687ba4b9d6ab22f9abbf58a62 100644
--- a/Sources/Shared/Controllers/RootViewController.swift
+++ b/Sources/AppCore/RootViewController.swift
@@ -1,60 +1,61 @@
 import UIKit
 import Combine
-import DI
+import StatusBarFeature
+import ComposableArchitecture
 
 public final class RootViewController: UIViewController {
-  @Dependency var barStylist: StatusBarStylist
-  @Dependency var hudDispatcher: HUDController
-  @Dependency var toastDispatcher: ToastController
-
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
+  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
+  @Dependency(\.app.toastManager) var toastManager: ToastManager
+  
   var hud: HUDView?
   var cancellables = Set<AnyCancellable>()
   public let navController: UINavigationController
-
+  
   var toastTimer: Timer?
   let toastTopPadding: CGFloat = 10
   var topToastConstraint: NSLayoutConstraint?
-
+  
   public init(_ content: UINavigationController) {
     self.navController = content
     super.init(nibName: nil, bundle: nil)
   }
-
+  
   required init?(coder: NSCoder) { nil }
-
+  
   public override var preferredStatusBarStyle: UIStatusBarStyle  {
-    barStylist.styleSubject.value
+    statusBar.current()
   }
-
+  
   public override func viewDidLoad() {
     super.viewDidLoad()
-
+    
     addChild(navController)
     view.addSubview(navController.view)
     navController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
     navController.view.frame = view.bounds
     navController.didMove(toParent: self)
-
-    barStylist
-      .styleSubject
+    
+    statusBar
+      .observe()
       .receive(on: DispatchQueue.main)
       .sink { [weak self] _ in
         UIView.animate(withDuration: 0.2) {
           self?.setNeedsStatusBarAppearanceUpdate()
         }
       }.store(in: &cancellables)
-
-    toastDispatcher
-      .currentToast
+    
+    toastManager
+      .observe()
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] model in
         let toastView = ToastView(model: model)
         add(toastView: toastView)
         present(toastView: toastView)
       }.store(in: &cancellables)
-
-    hudDispatcher
-      .modelPublisher
+    
+    hudManager
+      .observe()
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] model in
         guard let model else {
@@ -77,35 +78,35 @@ public final class RootViewController: UIViewController {
 extension RootViewController {
   @objc private func didPanToast(_ sender: UIPanGestureRecognizer) {
     guard let toastView = sender.view else { return }
-
+    
     switch sender.state {
     case .began, .changed:
       toastTimer?.invalidate()
       let padding = toastTopPadding + min(0, sender.translation(in: view).y)
       topToastConstraint?.constant = padding
-
+      
     case .cancelled, .ended, .failed:
       let halfFrameHeight = -0.5 * toastView.frame.height
       let verticalTranslation = sender.translation(in: toastView).y
       let didSwipeAboveHalf = verticalTranslation < halfFrameHeight
-
+      
       if didSwipeAboveHalf {
         dismiss(toastView: toastView)
       } else {
         present(toastView: toastView)
       }
-
+      
     case .possible:
       break
     @unknown default:
       break
     }
   }
-
+  
   private func dismiss(toastView: UIView) {
     toastView.isUserInteractionEnabled = false
     topToastConstraint?.constant = -(toastView.frame.height + view.safeAreaLayoutGuide.layoutFrame.minY)
-
+    
     topToastConstraint = nil
     UIView.animate(withDuration: 0.25) {
       self.view.setNeedsLayout()
@@ -113,38 +114,38 @@ extension RootViewController {
     } completion: { _ in
       toastView.isUserInteractionEnabled = true
       toastView.removeFromSuperview()
-      self.toastDispatcher.dismissCurrentToast()
+      self.toastManager.dismiss()
     }
   }
-
+  
   private func add(toastView: UIView) {
     let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(didPanToast(_:)))
     toastView.addGestureRecognizer(gestureRecognizer)
-
+    
     toastView.translatesAutoresizingMaskIntoConstraints = false
     view.addSubview(toastView)
-
+    
     NSLayoutConstraint.activate([
       toastView.heightAnchor.constraint(equalToConstant: 78),
       toastView.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: 20),
       toastView.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor, constant: -20)
     ])
-
+    
     topToastConstraint = toastView.topAnchor.constraint(
       equalTo: view.safeAreaLayoutGuide.topAnchor,
       constant: -(toastView.frame.height + view.safeAreaLayoutGuide.layoutFrame.height)
     )
-
+    
     topToastConstraint?.isActive = true
-
+    
     view.setNeedsLayout()
     view.layoutIfNeeded()
   }
-
+  
   private func present(toastView: UIView) {
     toastView.isUserInteractionEnabled = false
     topToastConstraint?.constant = toastTopPadding
-
+    
     UIView.animate(
       withDuration: 0.5,
       delay: 0,
@@ -156,7 +157,7 @@ extension RootViewController {
       self.view.layoutIfNeeded()
     } completion: { _ in
       toastView.isUserInteractionEnabled = true
-
+      
       self.toastTimer?.invalidate()
       self.toastTimer = Timer.scheduledTimer(withTimeInterval: 5, repeats: false) { [weak self] _ in
         guard let self else { return }
@@ -174,28 +175,28 @@ extension RootViewController {
       hud.removeFromSuperview()
       self.hud = nil
     }
-
+    
     hudView.alpha = 0.0
     hudView.translatesAutoresizingMaskIntoConstraints = false
     view.addSubview(hudView)
-
+    
     NSLayoutConstraint.activate([
       hudView.topAnchor.constraint(equalTo: view.topAnchor),
       hudView.leftAnchor.constraint(equalTo: view.leftAnchor),
       hudView.rightAnchor.constraint(equalTo: view.rightAnchor),
       hudView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
     ])
-
+    
     view.setNeedsLayout()
     view.layoutIfNeeded()
-
+    
     UIView.animate(withDuration: 0.2) {
       hudView.alpha = 1.0
     }
-
+    
     hud = hudView
   }
-
+  
   //    if statusSubject.value.isPresented == true && status.isPresented == true {
   //      self.errorView = nil
   //      self.animation = nil
@@ -225,7 +226,7 @@ extension RootViewController {
   //
   //      showWindow()
   //    }
-
+  
   //    if statusSubject.value.isPresented == false && status.isPresented == true {
   //        switch status {
   //        case .on:
@@ -249,7 +250,7 @@ extension RootViewController {
   //
   //        showWindow()
   //    }
-
+  
   //    if statusSubject.value.isPresented == true && status.isPresented == false {
   //        hideWindow()
   //    }
diff --git a/Sources/AppCore/SendImage/SendImage.swift b/Sources/AppCore/SendImage/SendImage.swift
new file mode 100644
index 0000000000000000000000000000000000000000..04d7b69ee9dbaa6d845eaa944176b160f9117a55
--- /dev/null
+++ b/Sources/AppCore/SendImage/SendImage.swift
@@ -0,0 +1,108 @@
+import XXModels
+import XXClient
+import Foundation
+import XXMessengerClient
+import XCTestDynamicOverlay
+
+public struct SendImage {
+  public typealias OnError = (Error) -> Void
+  public typealias Completion = () -> Void
+
+  public var run: (Data, Data, @escaping OnError, @escaping Completion) -> Void
+
+  public func callAsFunction(
+    _ image: Data,
+    to recipientId: Data,
+    onError: @escaping OnError,
+    completion: @escaping Completion
+  ) {
+    run(image, recipientId, onError, completion)
+  }
+}
+
+extension SendImage {
+  public static func live(
+    messenger: Messenger,
+    db: DBManagerGetDB,
+    now: @escaping () -> Date
+  ) -> SendImage {
+    SendImage { image, recipientId, onError, completion in
+      func updateProgress(transferId: Data, progress: Float) {
+        do {
+          if var transfer = try db().fetchFileTransfers(.init(id: [transferId])).first {
+            transfer.progress = progress
+            try db().saveFileTransfer(transfer)
+          }
+        } catch {
+          onError(error)
+        }
+      }
+
+      let file = FileSend(
+        name: "image.jpg",
+        type: "image",
+        preview: nil,
+        contents: image
+      )
+      let params = MessengerSendFile.Params(
+        file: file,
+        recipientId: recipientId,
+        retry: 2,
+        callbackIntervalMS: 500
+      )
+      do {
+        let date = now()
+        let myContactId = try messenger.e2e.tryGet().getContact().getId()
+        let transferId = try messenger.sendFile(params) { info in
+          switch info {
+          case .progress(let transferId, let transmitted, let total):
+            updateProgress(
+              transferId: transferId,
+              progress: total > 0 ? Float(transmitted) / Float(total) : 0
+            )
+
+          case .finished(let transferId):
+            updateProgress(
+              transferId: transferId,
+              progress: 1
+            )
+
+          case .failed(_, .callback(let error)):
+            onError(error)
+
+          case .failed(_, .close(let error)):
+            onError(error)
+          }
+        }
+        try db().saveFileTransfer(XXModels.FileTransfer(
+          id: transferId,
+          contactId: myContactId,
+          name: file.name,
+          type: file.type,
+          data: image,
+          progress: 0,
+          isIncoming: false,
+          createdAt: date
+        ))
+        try db().saveMessage(XXModels.Message(
+          senderId: myContactId,
+          recipientId: recipientId,
+          groupId: nil,
+          date: date,
+          status: .sent,
+          isUnread: false,
+          text: "",
+          fileTransferId: transferId
+        ))
+      } catch {
+        onError(error)
+      }
+    }
+  }
+}
+
+extension SendImage {
+  public static let unimplemented = SendImage(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/SendMessage/SendMessage.swift b/Sources/AppCore/SendMessage/SendMessage.swift
new file mode 100644
index 0000000000000000000000000000000000000000..f675dc0d2322cbe3b7611d92823eece9b5420d42
--- /dev/null
+++ b/Sources/AppCore/SendMessage/SendMessage.swift
@@ -0,0 +1,84 @@
+import XXModels
+import XXClient
+import Foundation
+import XXMessengerClient
+import XCTestDynamicOverlay
+
+public struct SendMessage {
+  public typealias OnError = (Error) -> Void
+  public typealias Completion = () -> Void
+
+  public var run: (String, Data, @escaping OnError, @escaping Completion) -> Void
+
+  public func callAsFunction(
+    text: String,
+    to recipientId: Data,
+    onError: @escaping OnError,
+    completion: @escaping Completion
+  ) {
+    run(text, recipientId, onError, completion)
+  }
+}
+
+extension SendMessage {
+  public static func live(
+    messenger: Messenger,
+    db: DBManagerGetDB,
+    now: @escaping () -> Date
+  ) -> SendMessage {
+    SendMessage { text, recipientId, onError, completion in
+      do {
+        let myContactId = try messenger.e2e.tryGet().getContact().getId()
+        let message = try db().saveMessage(.init(
+          senderId: myContactId,
+          recipientId: recipientId,
+          groupId: nil,
+          date: now(),
+          status: .sending,
+          isUnread: false,
+          text: text
+        ))
+        let payload = MessagePayload(text: message.text)
+        let report = try messenger.sendMessage(
+          recipientId: recipientId,
+          payload: try payload.encode(),
+          deliveryCallback: { deliveryReport in
+            let status: XXModels.Message.Status
+            switch deliveryReport.result {
+            case .delivered:
+              status = .sent
+            case .notDelivered(let timedOut):
+              status = timedOut ? .sendingTimedOut : .sendingFailed
+            case .failure(let error):
+              status = .sendingFailed
+              onError(error)
+            }
+            do {
+              try db().bulkUpdateMessages(
+                .init(id: [message.id]),
+                .init(status: status)
+              )
+            } catch {
+              onError(error)
+            }
+            completion()
+          }
+        )
+        if var message = try db().fetchMessages(.init(id: [message.id])).first {
+          message.networkId = report.messageId
+          message.roundURL = report.roundURL
+          _ = try db().saveMessage(message)
+        }
+      } catch {
+        onError(error)
+        completion()
+      }
+    }
+  }
+}
+
+extension SendMessage {
+  public static let unimplemented = SendMessage(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/ToastManager/ToastDismiss.swift b/Sources/AppCore/ToastManager/ToastDismiss.swift
new file mode 100644
index 0000000000000000000000000000000000000000..a328ca5757b1fc0c57a73ff6c7021d49f45242ea
--- /dev/null
+++ b/Sources/AppCore/ToastManager/ToastDismiss.swift
@@ -0,0 +1,19 @@
+import XCTestDynamicOverlay
+
+public struct ToastDismiss {
+  init(run: @escaping () -> Void) {
+    self.run = run
+  }
+
+  public var run: () -> Void
+
+  public func callAsFunction() -> Void {
+    run()
+  }
+}
+
+extension ToastDismiss {
+  public static let unimplemented = ToastDismiss(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/ToastManager/ToastEnqueue.swift b/Sources/AppCore/ToastManager/ToastEnqueue.swift
new file mode 100644
index 0000000000000000000000000000000000000000..ee0145b416e104cf445af6ba29a6216e64b9be36
--- /dev/null
+++ b/Sources/AppCore/ToastManager/ToastEnqueue.swift
@@ -0,0 +1,19 @@
+import XCTestDynamicOverlay
+
+public struct ToastEnqueue {
+  init(run: @escaping (ToastModel) -> Void) {
+    self.run = run
+  }
+
+  public var run: (ToastModel) -> Void
+
+  public func callAsFunction(_ model: ToastModel) -> Void {
+    run(model)
+  }
+}
+
+extension ToastEnqueue {
+  public static let unimplemented = ToastEnqueue(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/AppCore/ToastManager/ToastManager.swift b/Sources/AppCore/ToastManager/ToastManager.swift
new file mode 100644
index 0000000000000000000000000000000000000000..ce14e820840d63894cab76e8b81d5ad4379dcc66
--- /dev/null
+++ b/Sources/AppCore/ToastManager/ToastManager.swift
@@ -0,0 +1,44 @@
+import Combine
+import XCTestDynamicOverlay
+
+public struct ToastManager {
+  public var enqueue: ToastEnqueue
+  public var dismiss: ToastDismiss
+  public var observe: ToastObserve
+}
+
+extension ToastManager {
+  public static func live() -> ToastManager {
+    class Context {
+      let queue = CurrentValueSubject<[ToastModel], Never>([])
+    }
+
+    let context = Context()
+
+    return .init(
+      enqueue: .init {
+        context.queue.value.append($0)
+      },
+      dismiss: .init {
+        guard context.queue.value.isEmpty == false else {
+          return
+        }
+        _ = context.queue.value.removeFirst()
+      },
+      observe: .init {
+        context.queue
+          .compactMap(\.first)
+          .removeDuplicates(by: { $0.id == $1.id })
+          .eraseToAnyPublisher()
+      }
+    )
+  }
+}
+
+extension ToastManager {
+  public static let unimplemented: ToastManager = .init(
+    enqueue: .unimplemented,
+    dismiss: .unimplemented,
+    observe: .unimplemented
+  )
+}
diff --git a/Sources/AppCore/ToastManager/ToastObserve.swift b/Sources/AppCore/ToastManager/ToastObserve.swift
new file mode 100644
index 0000000000000000000000000000000000000000..d1b5fb7d2ce6b4153bbc1f283b4825eb1dfd3214
--- /dev/null
+++ b/Sources/AppCore/ToastManager/ToastObserve.swift
@@ -0,0 +1,16 @@
+import Combine
+import XCTestDynamicOverlay
+
+public struct ToastObserve {
+  public var run: () -> AnyPublisher<ToastModel, Never>
+
+  public func callAsFunction() -> AnyPublisher<ToastModel, Never> {
+    run()
+  }
+}
+
+extension ToastObserve {
+  public static let unimplemented = ToastObserve(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/Shared/Views/HUDView.swift b/Sources/AppCore/UI/HUDView.swift
similarity index 96%
rename from Sources/Shared/Views/HUDView.swift
rename to Sources/AppCore/UI/HUDView.swift
index 328c0b9f92308877cd627995a7289bc7cbc314a1..926e36420b97b084cfa35255c981885cbf240eb4 100644
--- a/Sources/Shared/Views/HUDView.swift
+++ b/Sources/AppCore/UI/HUDView.swift
@@ -1,5 +1,8 @@
 import UIKit
+import Shared
 import Combine
+import SnapKit
+import AppResources
 
 final class HUDView: UIView {
   let titleLabel = UILabel()
@@ -47,7 +50,7 @@ final class HUDView: UIView {
 
   required init?(coder: NSCoder) { nil }
 
-  func setup(model: HUDModel) -> HUDView {
+  func setup(model: HUDModel) -> Self {
     if let title = model.title {
       titleLabel.text = title
       stackView.addArrangedSubview(titleLabel)
diff --git a/Sources/Shared/Views/ToastView.swift b/Sources/AppCore/UI/ToastView.swift
similarity index 96%
rename from Sources/Shared/Views/ToastView.swift
rename to Sources/AppCore/UI/ToastView.swift
index bf1254429a07344f7ba7c20b9dee19e13ebeff03..a5202803704d20d44720f87a78c5149fd49c4291 100644
--- a/Sources/Shared/Views/ToastView.swift
+++ b/Sources/AppCore/UI/ToastView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Combine
+import AppResources
 
 final class ToastView: UIView {
   let titleLabel = UILabel()
@@ -9,69 +10,69 @@ final class ToastView: UIView {
   let verticalStackView = UIStackView()
   let horizontalStackView = UIStackView()
   var cancellables = Set<AnyCancellable>()
-
+  
   init(model: ToastModel) {
     super.init(frame: .zero)
     backgroundColor = model.color
     layer.cornerRadius = 18.0
-
+    
     titleLabel.textColor = .white
     subtitleLabel.textColor = .white
     leftImageView.contentMode = .center
-
+    
     titleLabel.numberOfLines = 0
     subtitleLabel.numberOfLines = 0
     titleLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
     subtitleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
-
+    
     leftImageView.image = Asset.sharedSuccess.image
     leftImageView.setContentHuggingPriority(.required, for: .horizontal)
-
+    
     rightButton.titleLabel?.numberOfLines = 0
     rightButton.titleLabel?.textAlignment = .center
     rightButton.titleLabel?.font = Fonts.Mulish.bold.font(size: 12.0)
-
+    
     verticalStackView.axis = .vertical
     verticalStackView.distribution = .fill
     verticalStackView.addArrangedSubview(titleLabel)
     verticalStackView.addArrangedSubview(subtitleLabel)
-
+    
     horizontalStackView.spacing = 12
     horizontalStackView.addArrangedSubview(leftImageView)
     horizontalStackView.addArrangedSubview(verticalStackView)
     horizontalStackView.addArrangedSubview(rightButton)
-
+    
     addSubview(horizontalStackView)
-
+    
     horizontalStackView.snp.makeConstraints {
       $0.top.equalToSuperview().offset(17)
       $0.left.equalToSuperview().offset(20)
       $0.right.equalToSuperview().offset(-20)
       $0.bottom.equalToSuperview().offset(-17)
     }
-
+    
     titleLabel.text = model.title
     leftImageView.image = model.leftImage
-
+    
     if let subtitle = model.subtitle {
       subtitleLabel.text = subtitle
       subtitleLabel.numberOfLines = 0
     } else {
       subtitleLabel.isHidden = true
     }
-
+    
     if let buttonTitle = model.buttonTitle {
       rightButton.setTitle(buttonTitle, for: .normal)
       rightButton.setContentHuggingPriority(.required, for: .horizontal)
     } else {
       rightButton.isHidden = true
     }
-
+    
     rightButton
       .publisher(for: .touchUpInside)
       .sink { model.onTapClosure?() }
       .store(in: &cancellables)
   }
-
+  
   required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/AppCore/URLDataLoader/URLDataLoader.swift b/Sources/AppCore/URLDataLoader/URLDataLoader.swift
new file mode 100644
index 0000000000000000000000000000000000000000..bca96e58f59d9880aca1f38d100192fdf9c97f47
--- /dev/null
+++ b/Sources/AppCore/URLDataLoader/URLDataLoader.swift
@@ -0,0 +1,22 @@
+import Foundation
+import XCTestDynamicOverlay
+
+public struct URLDataLoader {
+  public var load: (URL) throws -> Data
+
+  public func callAsFunction(_ url: URL) throws -> Data {
+    try load(url)
+  }
+}
+
+extension URLDataLoader {
+  public static let live = URLDataLoader { url in
+    try Data(contentsOf: url)
+  }
+}
+
+extension URLDataLoader {
+  public static let unimplemented = URLDataLoader(
+    load: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/App/AppDelegate.swift b/Sources/AppFeature/AppDelegate.swift
similarity index 99%
rename from Sources/App/AppDelegate.swift
rename to Sources/AppFeature/AppDelegate.swift
index fd23e19c9ad2a4846e099f0c7023c2c1ab236bbf..c4dc80dab5df9e71b580a6e7525fd90858c0d414 100644
--- a/Sources/App/AppDelegate.swift
+++ b/Sources/AppFeature/AppDelegate.swift
@@ -41,7 +41,6 @@ public class AppDelegate: UIResponder, UIApplicationDelegate {
     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
   ) -> Bool {
     UNUserNotificationCenter.current().delegate = self
-    DependencyRegistrator.registerDependencies()
     setupCloudFilesManagers()
     setupCrashReporting()
     setupLogging()
diff --git a/Sources/AppFeature/DependencyRegistrator.swift b/Sources/AppFeature/DependencyRegistrator.swift
new file mode 100644
index 0000000000000000000000000000000000000000..cd4baf2baf6b1af0cb2946df7c72f45a41437c96
--- /dev/null
+++ b/Sources/AppFeature/DependencyRegistrator.swift
@@ -0,0 +1,278 @@
+// MARK: SDK
+
+import UIKit
+import Network
+import QuickLook
+import MobileCoreServices
+
+// MARK: Isolated features
+
+import Bindings
+import XXLogger
+import Keychain
+import Defaults
+import Voxophone
+import Permissions
+import PushFeature
+import CrashService
+import CrashReporting
+import VersionChecking
+import ReportingFeature
+import CountryListFeature
+import DI
+
+// MARK: UI Features
+
+import ScanFeature
+import ChatFeature
+import MenuFeature
+import TermsFeature
+import BackupFeature
+import DrawerFeature
+import SearchFeature
+import LaunchFeature
+import RestoreFeature
+import ContactFeature
+import ProfileFeature
+import ChatListFeature
+import SettingsFeature
+import RequestsFeature
+import OnboardingFeature
+import ContactListFeature
+
+import Shared
+import XXClient
+import Navigation
+import KeychainAccess
+import XXMessengerClient
+
+import ComposableArchitecture
+
+struct DependencyRegistrator {
+  static public func registerNavigators(_ navController: UINavigationController) {
+//    container.register(CombinedNavigator(
+//      PresentModalNavigator(),
+//      DismissModalNavigator(),
+//      PushNavigator(),
+//      PopToRootNavigator(),
+//      PopToNavigator(),
+//      SetStackNavigator(),
+//
+//      OpenUpNavigator(),
+//      OpenLeftNavigator(),
+//
+//      PresentOnboardingStartNavigator(
+//        screen: OnboardingStartController.init,
+//        navigationController: { navController }
+//      ),
+//      PresentChatListNavigator(
+//        screen: ChatListController.init,
+//        navigationController: { navController }
+//      ),
+//      PresentTermsAndConditionsNavigator(
+//        screen: TermsConditionsController.init,
+//        navigationController: { navController }
+//      ),
+//      PresentSearchNavigator(
+//        screen: SearchContainerController.init(_:),
+//        navigationController: { navController }
+//      ),
+//      PresentRequestsNavigator(
+//        screen: RequestsContainerController.init,
+//        navigationController: { navController }
+//      ),
+//      PresentChatNavigator(
+//        screen: SingleChatController.init(_:),
+//        navigationController: { navController }
+//      ),
+//      PresentGroupChatNavigator(
+//        screen: GroupChatController.init(_:),
+//        navigationController: { navController }
+//      ),
+//      PresentOnboardingWelcomeNavigator(
+//        screen: OnboardingWelcomeController.init,
+//        navigationController: { navController }
+//      ),
+//      PresentOnboardingUsernameNavigator(
+//        screen: OnboardingUsernameController.init,
+//        navigationController: { navController }
+//      ),
+//      PresentRestoreListNavigator(
+//        screen: RestoreListController.init,
+//        navigationController: { navController }
+//      ),
+//      PresentOnboardingEmailNavigator(
+//        screen: OnboardingEmailController.init,
+//        navigationController: { navController }
+//      ),
+//      PresentOnboardingPhoneNavigator(
+//        screen: OnboardingPhoneController.init,
+//        navigationController: { navController }
+//      ),
+//      PresentOnboardingCodeNavigator(
+//        screen: OnboardingCodeController.init(_:_:_:),
+//        navigationController: { navController }
+//      ),
+//      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 }
+//      )
+//    ) as Navigator)
+  }
+}
+
+public struct OtherDependencies {
+  public var voxophone: Voxophone
+  public var sendReport: SendReport
+  public var pushHandler: PushHandler
+  public var versionCheck: VersionCheck
+  public var backupService: BackupService
+  public var hudController: HUDController
+  public var crashReporter: CrashReporter
+  public var networkMonitor: NetworkMonitor
+  public var keyObjectStore: KeyObjectStore
+  public var fetchBannedList: FetchBannedList
+  public var toastController: ToastController
+  public var reportingStatus: ReportingStatus
+  public var keychainHandler: KeychainHandler
+  public var makeReportDrawer: MakeReportDrawer
+  public var statusBarStylist: StatusBarStylist
+  public var getIdFromContact: GetIdFromContact
+  public var permissionHandler: PermissionHandler
+  public var processBannedList: ProcessBannedList
+  public var makeAppScreenshot: MakeAppScreenshot
+  public var getFactsFromContact: GetFactsFromContact
+}
+
+extension OtherDependencies {
+  public static func live() -> OtherDependencies {
+    .init(
+      voxophone: .init(),
+      sendReport: .live,
+      pushHandler: .init(),
+      versionCheck: .live,
+      backupService: .init(),
+      hudController: .init(),
+      crashReporter: .live,
+      networkMonitor: .init(),
+      keyObjectStore: .userDefaults,
+      fetchBannedList: .live,
+      toastController: .init(),
+      reportingStatus: .live(),
+      keychainHandler: .init(),
+      makeReportDrawer: .live,
+      statusBarStylist: .init(),
+      getIdFromContact: .live,
+      permissionHandler: .init(),
+      processBannedList: .live,
+      makeAppScreenshot: .live,
+      getFactsFromContact: .live
+    )
+  }
+
+  public static let unimplemented = OtherDependencies(
+    voxophone: .init(),
+    sendReport: .unimplemented,
+    pushHandler: .init(),
+    versionCheck: .unimplemented,
+    backupService: .init(),
+    hudController: .init(),
+    crashReporter: .noop,
+    networkMonitor: .init(),
+    keyObjectStore: .mock(dictionary: [:]),
+    fetchBannedList: .unimplemented,
+    toastController: .init(),
+    reportingStatus: .mock(),
+    keychainHandler: .init(),
+    makeReportDrawer: .unimplemented,
+    statusBarStylist: .init(),
+    getIdFromContact: .live,
+    permissionHandler: .init(),
+    processBannedList: .unimplemented,
+    makeAppScreenshot: .unimplemented,
+    getFactsFromContact: .live
+  )
+}
+
+private enum OtherDependenciesKey: DependencyKey {
+  static let liveValue: OtherDependencies = .live()
+  static let testValue: OtherDependencies = .unimplemented
+}
+
+extension DependencyValues {
+  public var others: OtherDependencies {
+    get { self[OtherDependenciesKey.self] }
+    set { self[OtherDependenciesKey.self] = newValue }
+  }
+}
diff --git a/Sources/AppFeature/PushRouter.swift b/Sources/AppFeature/PushRouter.swift
new file mode 100644
index 0000000000000000000000000000000000000000..dc790bd8d3af5923dd99ea87e3b051adcf840bad
--- /dev/null
+++ b/Sources/AppFeature/PushRouter.swift
@@ -0,0 +1,57 @@
+import DI
+import UIKit
+import XXModels
+import PushFeature
+import ChatFeature
+import SearchFeature
+import LaunchFeature
+import ChatListFeature
+import RequestsFeature
+import XXMessengerClient
+
+extension PushRouter {
+  static func live(navigationController: UINavigationController) -> PushRouter {
+    PushRouter { route, completion in
+      if let launchController = navigationController.viewControllers.last as? LaunchController {
+        launchController.pendingPushRoute = route
+      } else {
+        switch route {
+        case .requests:
+          if !(navigationController.viewControllers.last is RequestsContainerController) {
+            navigationController.setViewControllers([RequestsContainerController()], animated: true)
+          }
+        case .search(username: let username):
+          if let messenger = try? DI.Container.shared.resolve() as Messenger,
+             let _ = try? messenger.ud.get()?.getContact() {
+            if !(navigationController.viewControllers.last is SearchContainerController) {
+              navigationController.setViewControllers([
+                ChatListController(),
+                SearchContainerController(username)
+              ], animated: true)
+            } else {
+              (navigationController.viewControllers.last as? SearchContainerController)?.startSearchingFor(username)
+            }
+          }
+        case .contactChat(id: let id):
+          if let database: Database = try? DI.Container.shared.resolve(),
+             let contact = try? database.fetchContacts(.init(id: [id])).first {
+            navigationController.setViewControllers([
+              ChatListController(),
+              SingleChatController(contact)
+            ], animated: true)
+          }
+        case .groupChat(id: let id):
+          if let database: Database = try? DI.Container.shared.resolve(),
+             let info = try? database.fetchGroupInfos(.init(groupId: id)).first {
+            navigationController.setViewControllers([
+              ChatListController(),
+              GroupChatController(info)
+            ], animated: true)
+          }
+        }
+      }
+
+      completion()
+    }
+  }
+}
diff --git a/Sources/Shared/AutoGenerated/Assets.swift b/Sources/AppResources/Assets.swift
similarity index 100%
rename from Sources/Shared/AutoGenerated/Assets.swift
rename to Sources/AppResources/Assets.swift
diff --git a/Sources/Shared/AutoGenerated/Fonts.swift b/Sources/AppResources/Fonts.swift
similarity index 100%
rename from Sources/Shared/AutoGenerated/Fonts.swift
rename to Sources/AppResources/Fonts.swift
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsBackup/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsBackup/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsBackup/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsBackup/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsBackup/backup_success.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsBackup/backup_success.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsBackup/backup_success.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsBackup/backup_success.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsBackup/backup_success.imageset/Group 512227.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsBackup/backup_success.imageset/Group 512227.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsBackup/backup_success.imageset/Group 512227.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsBackup/backup_success.imageset/Group 512227.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_close_speaker.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_close_speaker.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_close_speaker.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_close_speaker.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_close_speaker.imageset/Icon (9).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_close_speaker.imageset/Icon (9).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_close_speaker.imageset/Icon (9).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_close_speaker.imageset/Icon (9).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_open_speaker.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_open_speaker.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_open_speaker.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_open_speaker.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_open_speaker.imageset/Icon (7).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_open_speaker.imageset/Icon (7).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_open_speaker.imageset/Icon (7).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_open_speaker.imageset/Icon (7).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_pause.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_pause.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_pause.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_pause.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_pause.imageset/Icon (8).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_pause.imageset/Icon (8).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_pause.imageset/Icon (8).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_pause.imageset/Icon (8).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_play.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_play.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_play.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_play.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_play.imageset/Icon (10).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_play.imageset/Icon (10).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_play.imageset/Icon (10).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_play.imageset/Icon (10).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_spectrum.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_spectrum.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_spectrum.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_spectrum.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_spectrum.imageset/sound.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_spectrum.imageset/sound.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_audio_spectrum.imageset/sound.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_audio_spectrum.imageset/sound.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_camera.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_camera.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_camera.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_camera.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_camera.imageset/Icon (2).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_camera.imageset/Icon (2).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_camera.imageset/Icon (2).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_camera.imageset/Icon (2).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_close.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_close.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_close.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_close.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_close.imageset/Icon (5).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_close.imageset/Icon (5).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_close.imageset/Icon (5).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_close.imageset/Icon (5).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_files.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_files.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_files.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_files.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_files.imageset/Icon (4).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_files.imageset/Icon (4).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_files.imageset/Icon (4).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_files.imageset/Icon (4).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_gallery.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_gallery.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_gallery.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_gallery.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_gallery.imageset/Icon (3).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_gallery.imageset/Icon (3).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_gallery.imageset/Icon (3).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_gallery.imageset/Icon (3).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_open.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_open.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_open.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_open.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_open.imageset/Icon-5.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_open.imageset/Icon-5.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_action_open.imageset/Icon-5.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_action_open.imageset/Icon-5.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_pause.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_pause.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_pause.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_pause.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_pause.imageset/pause_brand_light.png b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_pause.imageset/pause_brand_light.png
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_pause.imageset/pause_brand_light.png
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_pause.imageset/pause_brand_light.png
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_play.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_play.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_play.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_play.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_play.imageset/Icon (6).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_play.imageset/Icon (6).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_play.imageset/Icon (6).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_play.imageset/Icon (6).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_start.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_start.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_start.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_start.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_start.imageset/Icon (1).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_start.imageset/Icon (1).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_start.imageset/Icon (1).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_start.imageset/Icon (1).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_stop.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_stop.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_stop.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_stop.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_stop.imageset/Group 2.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_stop.imageset/Group 2.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_input_voice_stop.imageset/Group 2.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_input_voice_stop.imageset/Group 2.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_locker.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_locker.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_locker.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_locker.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_locker.imageset/Vector-26.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_locker.imageset/Vector-26.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_locker.imageset/Vector-26.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_locker.imageset/Vector-26.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_more.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_more.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_more.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_more.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_more.imageset/Icon-6.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_more.imageset/Icon-6.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_more.imageset/Icon-6.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_more.imageset/Icon-6.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_placeholder_image.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_placeholder_image.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_placeholder_image.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_placeholder_image.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_placeholder_image.imageset/Ellipse 1-2.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_placeholder_image.imageset/Ellipse 1-2.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_placeholder_image.imageset/Ellipse 1-2.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_placeholder_image.imageset/Ellipse 1-2.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_send.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_send.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_send.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_send.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_send.imageset/Icon-34.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_send.imageset/Icon-34.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChat/chat_send.imageset/Icon-34.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChat/chat_send.imageset/Icon-34.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_delete_swipe.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_delete_swipe.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_delete_swipe.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_delete_swipe.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_delete_swipe.imageset/Icon-7.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_delete_swipe.imageset/Icon-7.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_delete_swipe.imageset/Icon-7.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_delete_swipe.imageset/Icon-7.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_menu.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_menu.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_menu.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_menu.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_menu.imageset/Vector-19.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_menu.imageset/Vector-19.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_menu.imageset/Vector-19.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_menu.imageset/Vector-19.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_delete.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_delete.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_delete.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_delete.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_delete.imageset/Icon-11.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_delete.imageset/Icon-11.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_delete.imageset/Icon-11.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_delete.imageset/Icon-11.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_pin.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_pin.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_pin.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_pin.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_pin.imageset/Vector-27.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_pin.imageset/Vector-27.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_pin.imageset/Vector-27.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_menu_pin.imageset/Vector-27.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_new.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_new.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_new.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_new.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_new.imageset/Icon-19.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_new.imageset/Icon-19.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_new.imageset/Icon-19.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_new.imageset/Icon-19.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_new_group.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_new_group.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_new_group.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_new_group.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_new_group.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_new_group.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_new_group.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_new_group.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_pin_swipe.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_pin_swipe.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_pin_swipe.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_pin_swipe.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_pin_swipe.imageset/Icon-9.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_pin_swipe.imageset/Icon-9.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_pin_swipe.imageset/Icon-9.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_pin_swipe.imageset/Icon-9.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_placeholder.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_placeholder.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_placeholder.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_placeholder.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_placeholder.imageset/Ellipse 1-3.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_placeholder.imageset/Ellipse 1-3.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_placeholder.imageset/Ellipse 1-3.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_placeholder.imageset/Ellipse 1-3.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_ud.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_ud.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_ud.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_ud.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_ud.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_ud.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsChatList/chat_list_ud.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsChatList/chat_list_ud.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsCode/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsCode/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsCode/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsCode/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsCode/code.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsCode/code.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsCode/code.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsCode/code.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsCode/code.imageset/circle-bg 2-3.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsCode/code.imageset/circle-bg 2-3.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsCode/code.imageset/circle-bg 2-3.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsCode/code.imageset/circle-bg 2-3.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContact/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContact/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContact/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContact/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_add_placeholder.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_add_placeholder.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_add_placeholder.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_add_placeholder.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_add_placeholder.imageset/Group 512213.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_add_placeholder.imageset/Group 512213.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_add_placeholder.imageset/Group 512213.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_add_placeholder.imageset/Group 512213.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_details_padlock.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_details_padlock.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_details_padlock.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_details_padlock.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_details_padlock.imageset/Vector-14.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_details_padlock.imageset/Vector-14.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_details_padlock.imageset/Vector-14.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_details_padlock.imageset/Vector-14.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_nickname_edit.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_nickname_edit.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_nickname_edit.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_nickname_edit.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_nickname_edit.imageset/Group 512219.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_nickname_edit.imageset/Group 512219.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_nickname_edit.imageset/Group 512219.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_nickname_edit.imageset/Group 512219.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_request_exclamation.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_request_exclamation.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_request_exclamation.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_request_exclamation.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_request_exclamation.imageset/Icon-12.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_request_exclamation.imageset/Icon-12.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_request_exclamation.imageset/Icon-12.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_request_exclamation.imageset/Icon-12.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_request_placeholder.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_request_placeholder.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_request_placeholder.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_request_placeholder.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_request_placeholder.imageset/Group 512213.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_request_placeholder.imageset/Group 512213.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_request_placeholder.imageset/Group 512213.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_request_placeholder.imageset/Group 512213.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_send_message.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_send_message.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_send_message.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_send_message.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_send_message.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_send_message.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContact/contact_send_message.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContact/contact_send_message.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContactList/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContactList/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_avatar_remove.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_avatar_remove.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_avatar_remove.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_avatar_remove.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_avatar_remove.imageset/Icon-17.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_avatar_remove.imageset/Icon-17.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_avatar_remove.imageset/Icon-17.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_avatar_remove.imageset/Icon-17.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_new_group.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_new_group.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_new_group.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_new_group.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_new_group.imageset/Icon-23.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_new_group.imageset/Icon-23.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_new_group.imageset/Icon-23.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_new_group.imageset/Icon-23.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_placeholder.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_placeholder.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_placeholder.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_placeholder.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_placeholder.imageset/Ellipse 1-3.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_placeholder.imageset/Ellipse 1-3.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_placeholder.imageset/Ellipse 1-3.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_placeholder.imageset/Ellipse 1-3.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_requests.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_requests.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_requests.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_requests.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_requests.imageset/Icon-24.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_requests.imageset/Icon-24.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_requests.imageset/Icon-24.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_requests.imageset/Icon-24.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_search.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_search.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_search.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_search.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_search.imageset/Union-6.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_search.imageset/Union-6.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_search.imageset/Union-6.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_search.imageset/Union-6.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_user_search.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_user_search.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_user_search.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_user_search.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_user_search.imageset/Icon-16.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_user_search.imageset/Icon-16.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsContactList/contactList_user_search.imageset/Icon-16.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsContactList/contactList_user_search.imageset/Icon-16.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsDrawer/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsDrawer/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsDrawer/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsDrawer/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsDrawer/drawer_negative.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsDrawer/drawer_negative.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsDrawer/drawer_negative.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsDrawer/drawer_negative.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsDrawer/drawer_negative.imageset/circle-bg 2-9.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsDrawer/drawer_negative.imageset/circle-bg 2-9.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsDrawer/drawer_negative.imageset/circle-bg 2-9.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsDrawer/drawer_negative.imageset/circle-bg 2-9.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_chats.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_chats.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_chats.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_chats.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_chats.imageset/Vector-9.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_chats.imageset/Vector-9.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_chats.imageset/Vector-9.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_chats.imageset/Vector-9.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_contacts.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_contacts.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_contacts.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_contacts.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_contacts.imageset/Vector-10.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_contacts.imageset/Vector-10.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_contacts.imageset/Vector-10.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_contacts.imageset/Vector-10.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_dashboard.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_dashboard.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_dashboard.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_dashboard.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_dashboard.imageset/dashboardIconMd.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_dashboard.imageset/dashboardIconMd.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_dashboard.imageset/dashboardIconMd.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_dashboard.imageset/dashboardIconMd.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_profile.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_profile.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_profile.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_profile.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_profile.imageset/Vector-11.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_profile.imageset/Vector-11.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_profile.imageset/Vector-11.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_profile.imageset/Vector-11.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_requests.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_requests.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_requests.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_requests.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_requests.imageset/Icon-33.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_requests.imageset/Icon-33.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_requests.imageset/Icon-33.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_requests.imageset/Icon-33.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_scan.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_scan.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_scan.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_scan.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_scan.imageset/Union-3.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_scan.imageset/Union-3.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_scan.imageset/Union-3.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_scan.imageset/Union-3.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_settings.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_settings.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_settings.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_settings.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_settings.imageset/Vector-12.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_settings.imageset/Vector-12.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_settings.imageset/Vector-12.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_settings.imageset/Vector-12.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_share.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_share.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_share.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_share.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_share.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_share.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsMenu/menu_share.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsMenu/menu_share.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_background.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_background.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_background.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_background.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_background.imageset/photo-1599149535927-36b3fc68a1d6 1-2.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_background.imageset/photo-1599149535927-36b3fc68a1d6 1-2.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_background.imageset/photo-1599149535927-36b3fc68a1d6 1-2.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_background.imageset/photo-1599149535927-36b3fc68a1d6 1-2.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_bottom_logo_start.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_bottom_logo_start.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_bottom_logo_start.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_bottom_logo_start.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_bottom_logo_start.imageset/Powered by xx network.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_bottom_logo_start.imageset/Powered by xx network.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_bottom_logo_start.imageset/Powered by xx network.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_bottom_logo_start.imageset/Powered by xx network.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_email.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_email.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_email.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_email.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_email.imageset/circle-bg 2-6.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_email.imageset/circle-bg 2-6.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_email.imageset/circle-bg 2-6.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_email.imageset/circle-bg 2-6.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo.imageset/Logo.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo.imageset/Logo.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo.imageset/Logo.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo.imageset/Logo.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo_start.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo_start.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo_start.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo_start.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo_start.imageset/Group-2.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo_start.imageset/Group-2.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo_start.imageset/Group-2.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_logo_start.imageset/Group-2.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_phone.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_phone.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_phone.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_phone.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_phone.imageset/circle-bg 2-7.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_phone.imageset/circle-bg 2-7.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_phone.imageset/circle-bg 2-7.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_phone.imageset/circle-bg 2-7.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_success.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_success.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_success.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_success.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_success.imageset/circle-bg 3.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_success.imageset/circle-bg 3.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsOnboarding/onboarding_success.imageset/circle-bg 3.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsOnboarding/onboarding_success.imageset/circle-bg 3.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_camera.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_camera.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_camera.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_camera.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_camera.imageset/circle-bg 2 (2).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_camera.imageset/circle-bg 2 (2).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_camera.imageset/circle-bg 2 (2).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_camera.imageset/circle-bg 2 (2).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_library.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_library.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_library.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_library.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_library.imageset/circle-bg 2 (3).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_library.imageset/circle-bg 2 (3).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_library.imageset/circle-bg 2 (3).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_library.imageset/circle-bg 2 (3).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_logo.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_logo.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_logo.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_logo.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_logo.imageset/Logo (1).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_logo.imageset/Logo (1).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_logo.imageset/Logo (1).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_logo.imageset/Logo (1).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_microphone.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_microphone.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_microphone.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_microphone.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_microphone.imageset/circle-bg 2 (1).pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_microphone.imageset/circle-bg 2 (1).pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsPermissions/permission_microphone.imageset/circle-bg 2 (1).pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsPermissions/permission_microphone.imageset/circle-bg 2 (1).pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsProfile/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsProfile/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_add.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_add.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_add.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_add.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_add.imageset/Icon-21.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_add.imageset/Icon-21.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_add.imageset/Icon-21.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_add.imageset/Icon-21.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_delete.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_delete.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_delete.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_delete.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_delete.imageset/Icon-22.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_delete.imageset/Icon-22.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_delete.imageset/Icon-22.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_delete.imageset/Icon-22.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_email.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_email.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_email.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_email.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_email.imageset/Group 512237.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_email.imageset/Group 512237.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_email.imageset/Group 512237.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_email.imageset/Group 512237.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_image_button.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_image_button.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_image_button.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_image_button.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_image_button.imageset/Group 512242.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_image_button.imageset/Group 512242.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_image_button.imageset/Group 512242.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_image_button.imageset/Group 512242.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_image_placeholder.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_image_placeholder.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_image_placeholder.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_image_placeholder.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_image_placeholder.imageset/Icon-20.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_image_placeholder.imageset/Icon-20.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_image_placeholder.imageset/Icon-20.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_image_placeholder.imageset/Icon-20.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_phone.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_phone.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_phone.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_phone.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_phone.imageset/Group 512237-2.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_phone.imageset/Group 512237-2.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsProfile/profile_phone.imageset/Group 512237-2.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsProfile/profile_phone.imageset/Group 512237-2.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/request_accepted.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/request_accepted.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/request_accepted.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/request_accepted.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/request_accepted.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/request_accepted.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/request_accepted.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/request_accepted.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/request_failed_toaster.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/request_failed_toaster.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/request_failed_toaster.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/request_failed_toaster.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/request_failed_toaster.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/request_failed_toaster.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/request_failed_toaster.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/request_failed_toaster.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/request_sent_toaster.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/request_sent_toaster.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/request_sent_toaster.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/request_sent_toaster.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/request_sent_toaster.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/request_sent_toaster.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/request_sent_toaster.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/request_sent_toaster.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_received_placeholder.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_received_placeholder.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_received_placeholder.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_received_placeholder.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_received_placeholder.imageset/circle-bg 2-11.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_received_placeholder.imageset/circle-bg 2-11.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_received_placeholder.imageset/circle-bg 2-11.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_received_placeholder.imageset/circle-bg 2-11.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_resend.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_resend.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_resend.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_resend.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_resend.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_resend.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_resend.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_resend.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_resent.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_resent.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_resent.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_resent.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_resent.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_resent.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_resent.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_resent.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_tab_failed.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_tab_failed.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_tab_failed.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_tab_failed.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_tab_failed.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_tab_failed.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_tab_failed.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_tab_failed.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_tab_received.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_tab_received.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_tab_received.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_tab_received.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_tab_received.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_tab_received.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_tab_received.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_tab_received.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_tab_sent.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_tab_sent.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_tab_sent.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_tab_sent.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_tab_sent.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_tab_sent.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_tab_sent.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_tab_sent.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_verification_failed.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_verification_failed.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_verification_failed.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_verification_failed.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_verification_failed.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_verification_failed.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRequests/requests_verification_failed.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRequests/requests_verification_failed.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRestore/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRestore/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_SFTP.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_SFTP.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_SFTP.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_SFTP.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_SFTP.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_SFTP.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_SFTP.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_SFTP.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_drive.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_drive.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_drive.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_drive.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_drive.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_drive.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_drive.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_drive.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_dropbox.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_dropbox.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_dropbox.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_dropbox.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_dropbox.imageset/Icon-3.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_dropbox.imageset/Icon-3.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_dropbox.imageset/Icon-3.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_dropbox.imageset/Icon-3.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_icloud.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_icloud.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_icloud.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_icloud.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_icloud.imageset/Icon-2.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_icloud.imageset/Icon-2.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_icloud.imageset/Icon-2.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_icloud.imageset/Icon-2.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_success.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_success.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_success.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_success.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_success.imageset/Group 512227.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_success.imageset/Group 512227.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsRestore/restore_success.imageset/Group 512227.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsRestore/restore_success.imageset/Group 512227.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_add.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_add.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_add.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_add.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_add.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_add.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_add.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_add.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_copy.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_copy.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_copy.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_copy.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_copy.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_copy.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_copy.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_copy.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_dropdown.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_dropdown.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_dropdown.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_dropdown.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_dropdown.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_dropdown.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_dropdown.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_dropdown.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_email.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_email.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_email.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_email.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_email.imageset/Vector-23.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_email.imageset/Vector-23.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_email.imageset/Vector-23.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_email.imageset/Vector-23.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_error.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_error.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_error.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_error.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_error.imageset/Icon-36.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_error.imageset/Icon-36.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_error.imageset/Icon-36.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_error.imageset/Icon-36.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_phone.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_phone.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_phone.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_phone.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_phone.imageset/Vector-24.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_phone.imageset/Vector-24.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_phone.imageset/Vector-24.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_phone.imageset/Vector-24.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_qr.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_qr.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_qr.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_qr.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_qr.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_qr.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_qr.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_qr.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_scan.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_scan.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_scan.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_scan.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_scan.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_scan.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsScan/scan_scan.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsScan/scan_scan.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_email.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_email.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_email.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_email.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_email.imageset/Vector-18.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_email.imageset/Vector-18.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_email.imageset/Vector-18.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_email.imageset/Vector-18.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_lens.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_lens.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_lens.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_lens.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_lens.imageset/Vector-25.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_lens.imageset/Vector-25.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_lens.imageset/Vector-25.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_lens.imageset/Vector-25.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_phone.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_phone.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_phone.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_phone.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_phone.imageset/Vector-17.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_phone.imageset/Vector-17.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_phone.imageset/Vector-17.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_phone.imageset/Vector-17.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_placeholder_image.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_placeholder_image.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_placeholder_image.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_placeholder_image.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_placeholder_image.imageset/Ellipse 1.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_placeholder_image.imageset/Ellipse 1.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_placeholder_image.imageset/Ellipse 1.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_placeholder_image.imageset/Ellipse 1.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_email.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_email.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_email.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_email.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_email.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_email.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_email.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_email.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_phone.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_phone.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_phone.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_phone.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_phone.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_phone.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_phone.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_phone.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_qr.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_qr.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_qr.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_qr.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_qr.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_qr.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_qr.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_qr.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_username.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_username.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_username.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_username.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_username.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_username.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_tab_username.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_tab_username.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_username.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_username.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_username.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_username.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_username.imageset/Vector-16.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_username.imageset/Vector-16.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSearch/search_username.imageset/Vector-16.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSearch/search_username.imageset/Vector-16.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/Icon-32.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/Icon-32.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/Icon-32.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/Icon-32.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/Icon-32.imageset/Icon-32.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/Icon-32.imageset/Icon-32.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/Icon-32.imageset/Icon-32.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/Icon-32.imageset/Icon-32.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_advanced.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_advanced.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_advanced.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_advanced.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_advanced.imageset/Icon-31.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_advanced.imageset/Icon-31.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_advanced.imageset/Icon-31.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_advanced.imageset/Icon-31.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_biometrics.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_biometrics.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_biometrics.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_biometrics.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_biometrics.imageset/Icon-25.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_biometrics.imageset/Icon-25.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_biometrics.imageset/Icon-25.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_biometrics.imageset/Icon-25.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_crash.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_crash.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_crash.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_crash.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_crash.imageset/Group.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_crash.imageset/Group.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_crash.imageset/Group.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_crash.imageset/Group.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_delete.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_delete.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_delete.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_delete.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_delete.imageset/Icon-35.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_delete.imageset/Icon-35.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_delete.imageset/Icon-35.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_delete.imageset/Icon-35.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_delete_large.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_delete_large.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_delete_large.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_delete_large.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_delete_large.imageset/Group 512235.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_delete_large.imageset/Group 512235.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_delete_large.imageset/Group 512235.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_delete_large.imageset/Group 512235.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_disclosure.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_disclosure.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_disclosure.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_disclosure.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_disclosure.imageset/Vector-5.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_disclosure.imageset/Vector-5.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_disclosure.imageset/Vector-5.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_disclosure.imageset/Vector-5.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_download.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_download.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_download.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_download.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_download.imageset/variant=download.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_download.imageset/variant=download.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_download.imageset/variant=download.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_download.imageset/variant=download.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_enter.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_enter.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_enter.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_enter.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_enter.imageset/Icon-27.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_enter.imageset/Icon-27.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_enter.imageset/Icon-27.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_enter.imageset/Icon-27.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_folder.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_folder.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_folder.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_folder.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_folder.imageset/Icon-29.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_folder.imageset/Icon-29.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_folder.imageset/Icon-29.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_folder.imageset/Icon-29.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_hide.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_hide.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_hide.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_hide.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_hide.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_hide.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_hide.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_hide.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_keyboard.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_keyboard.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_keyboard.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_keyboard.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_keyboard.imageset/Icon-26.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_keyboard.imageset/Icon-26.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_keyboard.imageset/Icon-26.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_keyboard.imageset/Icon-26.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_logs.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_logs.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_logs.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_logs.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_logs.imageset/Vector-21.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_logs.imageset/Vector-21.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_logs.imageset/Vector-21.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_logs.imageset/Vector-21.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_notifications.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_notifications.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_notifications.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_notifications.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_notifications.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_notifications.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_notifications.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_notifications.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_privacy.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_privacy.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_privacy.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_privacy.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_privacy.imageset/Icon-28.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_privacy.imageset/Icon-28.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsSettings/settings_privacy.imageset/Icon-28.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsSettings/settings_privacy.imageset/Icon-28.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/balloon.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/balloon.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/balloon.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/balloon.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/balloon.imageset/Icon-18.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/balloon.imageset/Icon-18.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/balloon.imageset/Icon-18.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/balloon.imageset/Icon-18.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/eye_closed.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/eye_closed.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/eye_closed.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/eye_closed.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/eye_closed.imageset/notVisibleIcon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/eye_closed.imageset/notVisibleIcon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/eye_closed.imageset/notVisibleIcon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/eye_closed.imageset/notVisibleIcon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/eye_open.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/eye_open.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/eye_open.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/eye_open.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/eye_open.imageset/visibleIconLg.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/eye_open.imageset/visibleIconLg.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/eye_open.imageset/visibleIconLg.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/eye_open.imageset/visibleIconLg.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/info_icon.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/info_icon.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/info_icon.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/info_icon.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/info_icon.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/info_icon.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/info_icon.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/info_icon.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/info_icon_grey.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/info_icon_grey.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/info_icon_grey.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/info_icon_grey.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/info_icon_grey.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/info_icon_grey.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/info_icon_grey.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/info_icon_grey.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/lens.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/lens.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/lens.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/lens.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/lens.imageset/searchIcon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/lens.imageset/searchIcon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/lens.imageset/searchIcon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/lens.imageset/searchIcon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/navigation_bar_back.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/navigation_bar_back.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/navigation_bar_back.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/navigation_bar_back.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/navigation_bar_back.imageset/Vector.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/navigation_bar_back.imageset/Vector.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/navigation_bar_back.imageset/Vector.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/navigation_bar_back.imageset/Vector.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/person_gray.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/person_gray.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/person_gray.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/person_gray.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/person_gray.imageset/Icon-13.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/person_gray.imageset/Icon-13.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/person_gray.imageset/Icon-13.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/person_gray.imageset/Icon-13.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/person_placeholder.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/person_placeholder.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/person_placeholder.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/person_placeholder.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/person_placeholder.imageset/circle-bg 2-11.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/person_placeholder.imageset/circle-bg 2-11.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/person_placeholder.imageset/circle-bg 2-11.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/person_placeholder.imageset/circle-bg 2-11.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/closeIconDark512.png b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/closeIconDark512.png
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/closeIconDark512.png
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/closeIconDark512.png
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/closeIconDark512@2x.png b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/closeIconDark512@2x.png
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/closeIconDark512@2x.png
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/closeIconDark512@2x.png
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/closeIconDark512@3x.png b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/closeIconDark512@3x.png
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/closeIconDark512@3x.png
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/reply_abort.imageset/closeIconDark512@3x.png
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_cross.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_cross.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_cross.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_cross.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_cross.imageset/Icon-8.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_cross.imageset/Icon-8.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_cross.imageset/Icon-8.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_cross.imageset/Icon-8.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_error.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_error.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_error.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_error.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_error.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_error.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_error.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_error.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_group.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_group.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_group.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_group.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_group.imageset/Icon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_group.imageset/Icon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_group.imageset/Icon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_group.imageset/Icon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_scan.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_scan.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_scan.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_scan.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_scan.imageset/Union-7.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_scan.imageset/Union-7.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_scan.imageset/Union-7.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_scan.imageset/Union-7.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_success.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_success.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_success.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_success.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_success.imageset/Icon-2.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_success.imageset/Icon-2.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_success.imageset/Icon-2.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_success.imageset/Icon-2.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_white_exclamation.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_white_exclamation.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_white_exclamation.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_white_exclamation.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_white_exclamation.imageset/alertDidntsendIcon.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_white_exclamation.imageset/alertDidntsendIcon.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/shared_white_exclamation.imageset/alertDidntsendIcon.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/shared_white_exclamation.imageset/alertDidntsendIcon.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/splash.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/splash.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/splash.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/splash.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/AssetsShared/splash.imageset/group.pdf b/Sources/AppResources/Resources/Assets.xcassets/AssetsShared/splash.imageset/group.pdf
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/AssetsShared/splash.imageset/group.pdf
rename to Sources/AppResources/Resources/Assets.xcassets/AssetsShared/splash.imageset/group.pdf
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsAccent/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsAccent/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsAccent/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsAccent/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsAccent/accent_danger.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsAccent/accent_danger.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsAccent/accent_danger.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsAccent/accent_danger.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsAccent/accent_safe.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsAccent/accent_safe.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsAccent/accent_safe.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsAccent/accent_safe.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsAccent/accent_success.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsAccent/accent_success.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsAccent/accent_success.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsAccent/accent_success.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsAccent/accent_warning.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsAccent/accent_warning.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsAccent/accent_warning.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsAccent/accent_warning.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsBrand/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsBrand/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsBrand/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsBrand/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsBrand/brand_background.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsBrand/brand_background.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsBrand/brand_background.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsBrand/brand_background.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsBrand/brand_bubble.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsBrand/brand_bubble.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsBrand/brand_bubble.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsBrand/brand_bubble.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsBrand/brand_default.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsBrand/brand_default.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsBrand/brand_default.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsBrand/brand_default.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsBrand/brand_light.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsBrand/brand_light.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsBrand/brand_light.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsBrand/brand_light.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsBrand/brand_primary.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsBrand/brand_primary.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsBrand/brand_primary.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsBrand/brand_primary.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_active.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_active.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_active.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_active.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_body.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_body.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_body.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_body.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_dark.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_dark.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_dark.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_dark.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_disabled.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_disabled.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_disabled.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_disabled.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_line.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_line.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_line.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_line.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_overlay.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_overlay.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_overlay.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_overlay.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_secondary.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_secondary.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_secondary.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_secondary.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_secondary_alternative.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_secondary_alternative.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_secondary_alternative.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_secondary_alternative.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_weak.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_weak.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_weak.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_weak.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_white.colorset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_white.colorset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/ColorsNeutral/neutral_white.colorset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/ColorsNeutral/neutral_white.colorset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/transfer_image_placeholder.imageset/Contents.json b/Sources/AppResources/Resources/Assets.xcassets/transfer_image_placeholder.imageset/Contents.json
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/transfer_image_placeholder.imageset/Contents.json
rename to Sources/AppResources/Resources/Assets.xcassets/transfer_image_placeholder.imageset/Contents.json
diff --git a/Sources/Shared/Resources/Assets.xcassets/transfer_image_placeholder.imageset/placeholder-images-image_large.png b/Sources/AppResources/Resources/Assets.xcassets/transfer_image_placeholder.imageset/placeholder-images-image_large.png
similarity index 100%
rename from Sources/Shared/Resources/Assets.xcassets/transfer_image_placeholder.imageset/placeholder-images-image_large.png
rename to Sources/AppResources/Resources/Assets.xcassets/transfer_image_placeholder.imageset/placeholder-images-image_large.png
diff --git a/Sources/Shared/Resources/Fonts/Mulish-Black.ttf b/Sources/AppResources/Resources/Fonts/Mulish-Black.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-Black.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-Black.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-BlackItalic.ttf b/Sources/AppResources/Resources/Fonts/Mulish-BlackItalic.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-BlackItalic.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-BlackItalic.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-Bold.ttf b/Sources/AppResources/Resources/Fonts/Mulish-Bold.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-Bold.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-Bold.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-BoldItalic.ttf b/Sources/AppResources/Resources/Fonts/Mulish-BoldItalic.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-BoldItalic.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-BoldItalic.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-ExtraBold.ttf b/Sources/AppResources/Resources/Fonts/Mulish-ExtraBold.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-ExtraBold.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-ExtraBold.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-ExtraBoldItalic.ttf b/Sources/AppResources/Resources/Fonts/Mulish-ExtraBoldItalic.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-ExtraBoldItalic.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-ExtraBoldItalic.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-ExtraLight.ttf b/Sources/AppResources/Resources/Fonts/Mulish-ExtraLight.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-ExtraLight.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-ExtraLight.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-ExtraLightItalic.ttf b/Sources/AppResources/Resources/Fonts/Mulish-ExtraLightItalic.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-ExtraLightItalic.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-ExtraLightItalic.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-Italic.ttf b/Sources/AppResources/Resources/Fonts/Mulish-Italic.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-Italic.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-Italic.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-Light.ttf b/Sources/AppResources/Resources/Fonts/Mulish-Light.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-Light.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-Light.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-LightItalic.ttf b/Sources/AppResources/Resources/Fonts/Mulish-LightItalic.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-LightItalic.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-LightItalic.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-Medium.ttf b/Sources/AppResources/Resources/Fonts/Mulish-Medium.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-Medium.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-Medium.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-MediumItalic.ttf b/Sources/AppResources/Resources/Fonts/Mulish-MediumItalic.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-MediumItalic.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-MediumItalic.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-Regular.ttf b/Sources/AppResources/Resources/Fonts/Mulish-Regular.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-Regular.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-Regular.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-SemiBold.ttf b/Sources/AppResources/Resources/Fonts/Mulish-SemiBold.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-SemiBold.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-SemiBold.ttf
diff --git a/Sources/Shared/Resources/Fonts/Mulish-SemiBoldItalic.ttf b/Sources/AppResources/Resources/Fonts/Mulish-SemiBoldItalic.ttf
similarity index 100%
rename from Sources/Shared/Resources/Fonts/Mulish-SemiBoldItalic.ttf
rename to Sources/AppResources/Resources/Fonts/Mulish-SemiBoldItalic.ttf
diff --git a/Sources/Shared/Resources/en.lproj/Localizable.strings b/Sources/AppResources/Resources/en.lproj/Localizable.strings
similarity index 100%
rename from Sources/Shared/Resources/en.lproj/Localizable.strings
rename to Sources/AppResources/Resources/en.lproj/Localizable.strings
diff --git a/Sources/Shared/AutoGenerated/Strings.swift b/Sources/AppResources/Strings.swift
similarity index 100%
rename from Sources/Shared/AutoGenerated/Strings.swift
rename to Sources/AppResources/Strings.swift
diff --git a/Sources/BackupFeature/Controllers/BackupConfigController.swift b/Sources/BackupFeature/Controllers/BackupConfigController.swift
index 5c75751ef6bbe2a7c8149d1f36cc65407d83ee57..25772de76f0a5a0bc13a45ddc2789088b3307982 100644
--- a/Sources/BackupFeature/Controllers/BackupConfigController.swift
+++ b/Sources/BackupFeature/Controllers/BackupConfigController.swift
@@ -1,10 +1,11 @@
+import DI
 import UIKit
 import Shared
 import Combine
 import CloudFiles
 import Navigation
 import DrawerFeature
-import DI
+import AppResources
 
 final class BackupConfigController: UIViewController {
   @Dependency var navigator: Navigator
@@ -271,7 +272,7 @@ final class BackupConfigController: UIViewController {
       wifiOnlyButton,
       wifiAndCellularButton,
       cancelButton
-    ]))
+    ], isDismissable: true, from: self))
   }
 
   private func presentFrequencyDrawer(manual: Bool) {
@@ -329,6 +330,6 @@ final class BackupConfigController: UIViewController {
       manualButton,
       automaticButton,
       cancelButton
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/BackupFeature/Controllers/BackupController.swift b/Sources/BackupFeature/Controllers/BackupController.swift
index aa5b7e8db6f20d08baebc313b4ea459fc093532c..b01e3865f6aee5765f0cdb18423b553c266de428 100644
--- a/Sources/BackupFeature/Controllers/BackupController.swift
+++ b/Sources/BackupFeature/Controllers/BackupController.swift
@@ -1,65 +1,66 @@
+import DI
 import UIKit
 import Shared
 import Combine
-import DI
+import AppResources
 
 public final class BackupController: UIViewController {
-    private let viewModel = BackupViewModel.live()
-    private var cancellables = Set<AnyCancellable>()
+  private let viewModel = BackupViewModel.live()
+  private var cancellables = Set<AnyCancellable>()
 
-    public override func viewWillAppear(_ animated: Bool) {
-        super.viewWillAppear(animated)
-        navigationItem.backButtonTitle = ""
-        navigationController?.navigationBar
-            .customize(backgroundColor: Asset.neutralWhite.color)
-    }
+  public override func viewWillAppear(_ animated: Bool) {
+    super.viewWillAppear(animated)
+    navigationItem.backButtonTitle = ""
+    navigationController?.navigationBar
+      .customize(backgroundColor: Asset.neutralWhite.color)
+  }
 
-    public override func viewDidLoad() {
-        super.viewDidLoad()
-        view.backgroundColor = Asset.neutralWhite.color
-        setupNavigationBar()
-        setupBindings()
-    }
+  public override func viewDidLoad() {
+    super.viewDidLoad()
+    view.backgroundColor = Asset.neutralWhite.color
+    setupNavigationBar()
+    setupBindings()
+  }
 
-    private func setupNavigationBar() {
-        let title = UILabel()
-        title.text = Localized.Backup.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 setupNavigationBar() {
+    let title = UILabel()
+    title.text = Localized.Backup.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.state()
-            .receive(on: DispatchQueue.main)
-            .removeDuplicates()
-            .sink { [unowned self] in
-                switch $0 {
-                case .setup:
-                    contentViewController = BackupSetupController(viewModel.setupViewModel())
-                case .config:
-                    contentViewController = BackupConfigController(viewModel.configViewModel())
-                }
-            }.store(in: &cancellables)
-    }
+  private func setupBindings() {
+    viewModel.state()
+      .receive(on: DispatchQueue.main)
+      .removeDuplicates()
+      .sink { [unowned self] in
+        switch $0 {
+        case .setup:
+          contentViewController = BackupSetupController(viewModel.setupViewModel())
+        case .config:
+          contentViewController = BackupConfigController(viewModel.configViewModel())
+        }
+      }.store(in: &cancellables)
+  }
 
-    private var contentViewController: UIViewController? {
-        didSet {
-            guard contentViewController != oldValue else { return }
+  private var contentViewController: UIViewController? {
+    didSet {
+      guard contentViewController != oldValue else { return }
 
-            if let oldValue = oldValue {
-                oldValue.willMove(toParent: nil)
-                oldValue.view.removeFromSuperview()
-                oldValue.removeFromParent()
-            }
+      if let oldValue = oldValue {
+        oldValue.willMove(toParent: nil)
+        oldValue.view.removeFromSuperview()
+        oldValue.removeFromParent()
+      }
 
-            if let newValue = contentViewController {
-                addChild(newValue)
-                view.addSubview(newValue.view)
-                newValue.view.snp.makeConstraints { $0.edges.equalToSuperview() }
-                newValue.didMove(toParent: self)
-            }
-        }
+      if let newValue = contentViewController {
+        addChild(newValue)
+        view.addSubview(newValue.view)
+        newValue.view.snp.makeConstraints { $0.edges.equalToSuperview() }
+        newValue.didMove(toParent: self)
+      }
     }
+  }
 }
diff --git a/Sources/BackupFeature/Service/BackupService.swift b/Sources/BackupFeature/Service/BackupService.swift
index 2d5e9989434f1f46a380597bfcc51e1716a29369..c471287bad37f16d3cda7d81dfb7ff4f1fcc0f07 100644
--- a/Sources/BackupFeature/Service/BackupService.swift
+++ b/Sources/BackupFeature/Service/BackupService.swift
@@ -1,17 +1,17 @@
+import AppCore
 import UIKit
 import Combine
 import XXClient
 import Defaults
 import CloudFiles
 import CloudFilesSFTP
-import NetworkMonitor
 import KeychainAccess
 import XXMessengerClient
-import DI
+import ComposableArchitecture
 
 public final class BackupService {
-  @Dependency var messenger: Messenger
-  @Dependency var networkManager: NetworkMonitoring
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.networkMonitor) var networkMonitor: NetworkMonitorManager
 
   @KeyObject(.email, defaultValue: nil) var email: String?
   @KeyObject(.phone, defaultValue: nil) var phone: String?
@@ -34,7 +34,6 @@ public final class BackupService {
     }).eraseToAnyPublisher()
   }
 
-  private var connType: ConnectionType = .wifi
   private var cancellables = Set<AnyCancellable>()
   private let connectedServicesSubject = CurrentValueSubject<Set<CloudService>, Never>([])
   private let backupSubject = CurrentValueSubject<[CloudService: Fetch.Metadata], Never>([:])
@@ -44,13 +43,9 @@ public final class BackupService {
     settings
       .dropFirst()
       .removeDuplicates()
-      .sink { [unowned self] in storedSettings = $0.toData() }
-      .store(in: &cancellables)
-
-    networkManager.connType
-      .receive(on: DispatchQueue.main)
-      .sink { [unowned self] in connType = $0 }
-      .store(in: &cancellables)
+      .sink { [unowned self] in
+        storedSettings = $0.toData()
+      }.store(in: &cancellables)
   }
 
   func didSetWiFiOnly(enabled: Bool) {
@@ -87,26 +82,21 @@ public final class BackupService {
 
   private func shouldBackupIfSetAutomatic() {
     guard let lastBackup = try? Data(contentsOf: getBackupURL()) else {
-      print(">>> No stored backup so won't upload anything.")
-      return
+      return // No stored backup so won't upload anything
     }
     guard settings.value.automaticBackups else {
-      print(">>> Backups are not set to automatic")
-      return
+      return // Backups are not set to automatic
     }
     guard settings.value.enabledService != nil else {
-      print(">>> No service enabled to upload")
-      return
+      return // No service enabled to upload
     }
     if settings.value.wifiOnlyBackup {
-      guard connType == .wifi else {
-        print(">>> WiFi only backups, and connType != Wifi")
-        return
+      guard networkMonitor.connType() == .wifi else {
+        return // WiFi only backups, and connType != Wifi
       }
     } else {
-      guard connType != .unknown else {
-        print(">>> Connectivity is unknown")
-        return
+      guard networkMonitor.connType() != .unknown else {
+        return // Connectivity is unknown
       }
     }
     performUpload(of: lastBackup)
@@ -155,8 +145,6 @@ public final class BackupService {
     backupManager.addJSON(string)
   }
 
-  // MARK: - CloudProviders
-
   func setupSFTP(host: String, username: String, password: String) {
     let sftpManager = CloudFilesManager.sftp(
       host: host,
@@ -233,8 +221,7 @@ public final class BackupService {
       )
     }
     guard let manager = CloudFilesManager.all[enabledService] else {
-      print(">>> Tried to upload but the enabled service is not set")
-      return
+      return // Tried to upload but the enabled service is not set
     }
     do {
       try manager.upload(data) { [weak self] in
diff --git a/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift b/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift
index 4ae6414e89a48f752080c7775fb33d4376265519..5318952dcadddd6a33bf7c257a4d51ae96851523 100644
--- a/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift
+++ b/Sources/BackupFeature/ViewModels/BackupConfigViewModel.swift
@@ -1,14 +1,12 @@
 import UIKit
 import Shared
+import AppCore
 import Combine
 import XXClient
 import Defaults
-import Foundation
-
-import DI
-
 import CloudFiles
 import Navigation
+import ComposableArchitecture
 
 enum BackupActionState {
   case backupFinished
@@ -34,9 +32,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 service: BackupService
+      @Dependency(\.navigator) var navigator: Navigator
+      @Dependency(\.app.hudManager) var hudManager: HUDManager
     }
 
     let context = Context()
@@ -70,9 +68,9 @@ extension BackupConfigViewModel {
       },
       didTapService: { service, controller in
         if service == .sftp {
-          context.navigator.perform(PresentSFTP { host, username, password in
+          context.navigator.perform(PresentSFTP(completion: { host, username, password in
             context.service.setupSFTP(host: host, username: username, password: password)
-          })
+          }, on: controller.navigationController!))
           return
         }
 
diff --git a/Sources/BackupFeature/ViewModels/BackupViewModel.swift b/Sources/BackupFeature/ViewModels/BackupViewModel.swift
index 17fca00a15143c3fd16752e780bb49ce15a48bc8..d25ddc5ebfbd3778131f15b111ad57e89f4c6733 100644
--- a/Sources/BackupFeature/ViewModels/BackupViewModel.swift
+++ b/Sources/BackupFeature/ViewModels/BackupViewModel.swift
@@ -1,34 +1,34 @@
-import Combine
 import DI
+import Combine
 
 enum BackupViewState: Equatable {
-    case setup
-    case config
+  case setup
+  case config
 }
 
 struct BackupViewModel {
-    var setupViewModel: () -> BackupSetupViewModel
-    var configViewModel: () -> BackupConfigViewModel
+  var setupViewModel: () -> BackupSetupViewModel
+  var configViewModel: () -> BackupConfigViewModel
 
-    var state: () -> AnyPublisher<BackupViewState, Never>
+  var state: () -> AnyPublisher<BackupViewState, Never>
 }
 
 extension BackupViewModel {
-    static func live() -> Self {
-        class Context {
-            @Dependency var service: BackupService
-        }
+  static func live() -> Self {
+    class Context {
+      @Dependency var service: BackupService
+    }
 
-        let context = Context()
+    let context = Context()
 
-        return .init(
-            setupViewModel: { BackupSetupViewModel.live() },
-            configViewModel: { BackupConfigViewModel.live() },
-            state: {
-                context.service.connectedServicesPublisher
-                    .map { $0.isEmpty ? BackupViewState.setup : .config }
-                    .eraseToAnyPublisher()
-            }
-        )
-    }
+    return .init(
+      setupViewModel: { BackupSetupViewModel.live() },
+      configViewModel: { BackupConfigViewModel.live() },
+      state: {
+        context.service.connectedServicesPublisher
+          .map { $0.isEmpty ? BackupViewState.setup : .config }
+          .eraseToAnyPublisher()
+      }
+    )
+  }
 }
diff --git a/Sources/BackupFeature/Views/BackupActionView.swift b/Sources/BackupFeature/Views/BackupActionView.swift
index 705263e0ef815ae9fab0ff5657cc536f02c98101..ae30fe5575fef2d271afb848c3720af29cd6b75b 100644
--- a/Sources/BackupFeature/Views/BackupActionView.swift
+++ b/Sources/BackupFeature/Views/BackupActionView.swift
@@ -1,125 +1,126 @@
 import UIKit
 import Shared
+import AppResources
 
 final class BackupActionView: UIView {
-    let stackView = UIStackView()
-    let backupNowButton = CapsuleButton()
+  let stackView = UIStackView()
+  let backupNowButton = CapsuleButton()
 
-    let progressView = UIView()
-    let progressLabel = UILabel()
-    let progressBarPartial = UIView()
-    let progressBarFull = UIView()
+  let progressView = UIView()
+  let progressLabel = UILabel()
+  let progressBarPartial = UIView()
+  let progressBarFull = UIView()
 
-    let finishedView = UIView()
-    let finishedLabel = UILabel()
-    let finishedImage = UIImageView()
+  let finishedView = UIView()
+  let finishedLabel = UILabel()
+  let finishedImage = UIImageView()
 
-    init() {
-        super.init(frame: .zero)
+  init() {
+    super.init(frame: .zero)
 
-        setupProgressView()
-        setupFinishedView()
+    setupProgressView()
+    setupFinishedView()
 
-        backupNowButton.set(style: .brandColored, title: Localized.Backup.Config.backupNow)
+    backupNowButton.set(style: .brandColored, title: Localized.Backup.Config.backupNow)
 
-        stackView.spacing = 15
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(backupNowButton)
-        stackView.addArrangedSubview(progressView)
-        stackView.addArrangedSubview(finishedView)
+    stackView.spacing = 15
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(backupNowButton)
+    stackView.addArrangedSubview(progressView)
+    stackView.addArrangedSubview(finishedView)
 
-        addSubview(stackView)
+    addSubview(stackView)
 
-        stackView.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.equalToSuperview()
-        }
+    stackView.snp.makeConstraints { make in
+      make.top.equalToSuperview()
+      make.left.equalToSuperview()
+      make.right.equalToSuperview()
+      make.bottom.equalToSuperview()
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 
-    private func setupFinishedView() {
-        finishedImage.contentMode = .center
-        finishedImage.image = Asset.restoreSuccess.image
+  private func setupFinishedView() {
+    finishedImage.contentMode = .center
+    finishedImage.image = Asset.restoreSuccess.image
 
-        finishedLabel.text = "Backup completed!"
-        finishedLabel.textColor = Asset.neutralBody.color
-        finishedLabel.font = Fonts.Mulish.regular.font(size: 16.0)
+    finishedLabel.text = "Backup completed!"
+    finishedLabel.textColor = Asset.neutralBody.color
+    finishedLabel.font = Fonts.Mulish.regular.font(size: 16.0)
 
-        finishedView.addSubview(finishedImage)
-        finishedView.addSubview(finishedLabel)
+    finishedView.addSubview(finishedImage)
+    finishedView.addSubview(finishedLabel)
 
-        finishedImage.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview()
-            make.bottom.equalToSuperview()
-        }
+    finishedImage.snp.makeConstraints { make in
+      make.top.equalToSuperview()
+      make.left.equalToSuperview()
+      make.bottom.equalToSuperview()
+    }
 
-        finishedLabel.snp.makeConstraints { make in
-            make.left.equalTo(finishedImage.snp.right).offset(10)
-            make.centerY.equalTo(finishedImage)
-            make.right.lessThanOrEqualToSuperview()
-        }
+    finishedLabel.snp.makeConstraints { make in
+      make.left.equalTo(finishedImage.snp.right).offset(10)
+      make.centerY.equalTo(finishedImage)
+      make.right.lessThanOrEqualToSuperview()
+    }
+  }
+
+  private func setupProgressView() {
+    progressLabel.textColor = Asset.neutralDisabled.color
+    progressLabel.font = Fonts.Mulish.regular.font(size: 14.0)
+
+    progressBarFull.backgroundColor = Asset.neutralLine.color
+    progressBarPartial.backgroundColor = Asset.brandPrimary.color
+    progressBarFull.layer.masksToBounds = true
+    progressBarFull.layer.cornerRadius = 4
+
+    progressBarFull.addSubview(progressBarPartial)
+    progressView.addSubview(progressLabel)
+    progressView.addSubview(progressBarFull)
+
+    progressBarFull.snp.makeConstraints { make in
+      make.top.equalToSuperview()
+      make.left.equalToSuperview()
+      make.right.equalToSuperview()
+      make.height.equalTo(8)
     }
 
-    private func setupProgressView() {
-        progressLabel.textColor = Asset.neutralDisabled.color
-        progressLabel.font = Fonts.Mulish.regular.font(size: 14.0)
-
-        progressBarFull.backgroundColor = Asset.neutralLine.color
-        progressBarPartial.backgroundColor = Asset.brandPrimary.color
-        progressBarFull.layer.masksToBounds = true
-        progressBarFull.layer.cornerRadius = 4
-
-        progressBarFull.addSubview(progressBarPartial)
-        progressView.addSubview(progressLabel)
-        progressView.addSubview(progressBarFull)
-
-        progressBarFull.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.height.equalTo(8)
-        }
-
-        progressLabel.snp.makeConstraints { make in
-            make.top.equalTo(progressBarFull.snp.bottom).offset(10)
-            make.left.equalToSuperview()
-            make.bottom.equalToSuperview()
-        }
-
-        progressBarPartial.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview()
-            make.width.equalToSuperview().multipliedBy(0.5)
-            make.bottom.equalToSuperview()
-        }
+    progressLabel.snp.makeConstraints { make in
+      make.top.equalTo(progressBarFull.snp.bottom).offset(10)
+      make.left.equalToSuperview()
+      make.bottom.equalToSuperview()
     }
 
-    func setState(_ state: BackupActionState) {
-        switch state {
-        case .backupFinished:
-            backupNowButton.isHidden = true
-            progressView.isHidden = true
-            finishedView.isHidden = false
-
-        case .backupAllowed(let bool):
-            backupNowButton.isHidden = false
-            progressView.isHidden = true
-            finishedView.isHidden = true
-            backupNowButton.isEnabled = bool
-
-        case .backupInProgress(let uploaded, let total):
-            backupNowButton.isHidden = true
-            progressView.isHidden = false
-            finishedView.isHidden = true
-
-            let uploadedKb = String(format: "%.1f kb", uploaded/1000)
-            let totalkb = String(format: "%.1f kb", total/1000)
-
-            progressLabel.text = "Uploaded \(uploadedKb) of \(totalkb) (\(total/uploaded)%)"
-        }
+    progressBarPartial.snp.makeConstraints { make in
+      make.top.equalToSuperview()
+      make.left.equalToSuperview()
+      make.width.equalToSuperview().multipliedBy(0.5)
+      make.bottom.equalToSuperview()
+    }
+  }
+
+  func setState(_ state: BackupActionState) {
+    switch state {
+    case .backupFinished:
+      backupNowButton.isHidden = true
+      progressView.isHidden = true
+      finishedView.isHidden = false
+
+    case .backupAllowed(let bool):
+      backupNowButton.isHidden = false
+      progressView.isHidden = true
+      finishedView.isHidden = true
+      backupNowButton.isEnabled = bool
+
+    case .backupInProgress(let uploaded, let total):
+      backupNowButton.isHidden = true
+      progressView.isHidden = false
+      finishedView.isHidden = true
+
+      let uploadedKb = String(format: "%.1f kb", uploaded/1000)
+      let totalkb = String(format: "%.1f kb", total/1000)
+
+      progressLabel.text = "Uploaded \(uploadedKb) of \(totalkb) (\(total/uploaded)%)"
     }
+  }
 }
diff --git a/Sources/BackupFeature/Views/BackupConfigView.swift b/Sources/BackupFeature/Views/BackupConfigView.swift
index 1c65f58f7222f1c069284c717518904dc2e596ca..60555ce672c01384fd2037af58a3803b465560ef 100644
--- a/Sources/BackupFeature/Views/BackupConfigView.swift
+++ b/Sources/BackupFeature/Views/BackupConfigView.swift
@@ -1,117 +1,118 @@
 import UIKit
 import Shared
+import AppResources
 
 final class BackupConfigView: UIView {
-    let titleLabel = UILabel()
-    let subtitleLabel = UILabel()
-    let actionView = BackupActionView()
-
-    let stackView = UIStackView()
-    let sftpButton = BackupSwitcherButton()
-    let iCloudButton = BackupSwitcherButton()
-    let dropboxButton = BackupSwitcherButton()
-    let googleDriveButton = BackupSwitcherButton()
-
-    let enabledSubtitleView = UIView()
-    let enabledSubtitleLabel = UILabel()
-    let frequencyDetailView = BackupDetailView()
-    let latestBackupDetailView = BackupDetailView()
-    let infrastructureDetailView = BackupDetailView()
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        titleLabel.textColor = Asset.neutralDark.color
-        titleLabel.text = Localized.Backup.Config.title
-        titleLabel.font = Fonts.Mulish.bold.font(size: 24.0)
-
-        enabledSubtitleLabel.numberOfLines = 0
-        enabledSubtitleLabel.textColor = Asset.neutralWeak.color
-        enabledSubtitleLabel.font = Fonts.Mulish.regular.font(size: 14.0)
-
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.alignment = .left
-        paragraph.lineHeightMultiple = 1.15
-
-        let attString = NSAttributedString(
-            string: Localized.Backup.subtitle,
-            attributes: [
-                .foregroundColor: Asset.neutralBody.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
-                .paragraphStyle: paragraph
-            ])
-
-        subtitleLabel.numberOfLines = 0
-        subtitleLabel.attributedText = attString
-
-        sftpButton.titleLabel.text = Localized.Backup.sftp
-        sftpButton.logoImageView.image = Asset.restoreSFTP.image
-
-        iCloudButton.titleLabel.text = Localized.Backup.iCloud
-        iCloudButton.logoImageView.image = Asset.restoreIcloud.image
-
-        dropboxButton.titleLabel.text = Localized.Backup.dropbox
-        dropboxButton.logoImageView.image = Asset.restoreDropbox.image
-
-        googleDriveButton.titleLabel.text = Localized.Backup.googleDrive
-        googleDriveButton.logoImageView.image = Asset.restoreDrive.image
-
-        latestBackupDetailView.titleLabel.text = Localized.Backup.Config.latestBackup
-        frequencyDetailView.accessoryImageView.image = Asset.settingsDisclosure.image
-
-        infrastructureDetailView.titleLabel.text = Localized.Backup.Config.infrastructure.uppercased()
-        infrastructureDetailView.accessoryImageView.image = Asset.settingsDisclosure.image
-
-        enabledSubtitleView.addSubview(enabledSubtitleLabel)
-
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(googleDriveButton)
-        stackView.addArrangedSubview(iCloudButton)
-        stackView.addArrangedSubview(dropboxButton)
-        stackView.addArrangedSubview(sftpButton)
-        stackView.addArrangedSubview(enabledSubtitleView)
-        stackView.addArrangedSubview(latestBackupDetailView)
-        stackView.addArrangedSubview(frequencyDetailView)
-        stackView.addArrangedSubview(infrastructureDetailView)
-
-        addSubview(titleLabel)
-        addSubview(subtitleLabel)
-        addSubview(actionView)
-        addSubview(stackView)
-
-        titleLabel.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(15)
-            $0.left.equalToSuperview().offset(38)
-            $0.right.equalToSuperview().offset(-41)
-        }
-
-        enabledSubtitleLabel.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(-10)
-            $0.left.equalToSuperview().offset(92)
-            $0.right.equalToSuperview().offset(-48)
-            $0.bottom.equalToSuperview()
-        }
-
-        subtitleLabel.snp.makeConstraints {
-            $0.top.equalTo(titleLabel.snp.bottom).offset(8)
-            $0.left.equalToSuperview().offset(38)
-            $0.right.equalToSuperview().offset(-41)
-        }
-
-        actionView.snp.makeConstraints {
-            $0.top.equalTo(subtitleLabel.snp.bottom).offset(15)
-            $0.left.equalToSuperview().offset(38)
-            $0.right.equalToSuperview().offset(-38)
-        }
-
-        stackView.snp.makeConstraints {
-            $0.top.equalTo(actionView.snp.bottom).offset(28)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.lessThanOrEqualToSuperview()
-        }
+  let titleLabel = UILabel()
+  let subtitleLabel = UILabel()
+  let actionView = BackupActionView()
+
+  let stackView = UIStackView()
+  let sftpButton = BackupSwitcherButton()
+  let iCloudButton = BackupSwitcherButton()
+  let dropboxButton = BackupSwitcherButton()
+  let googleDriveButton = BackupSwitcherButton()
+
+  let enabledSubtitleView = UIView()
+  let enabledSubtitleLabel = UILabel()
+  let frequencyDetailView = BackupDetailView()
+  let latestBackupDetailView = BackupDetailView()
+  let infrastructureDetailView = BackupDetailView()
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+
+    titleLabel.textColor = Asset.neutralDark.color
+    titleLabel.text = Localized.Backup.Config.title
+    titleLabel.font = Fonts.Mulish.bold.font(size: 24.0)
+
+    enabledSubtitleLabel.numberOfLines = 0
+    enabledSubtitleLabel.textColor = Asset.neutralWeak.color
+    enabledSubtitleLabel.font = Fonts.Mulish.regular.font(size: 14.0)
+
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.alignment = .left
+    paragraph.lineHeightMultiple = 1.15
+
+    let attString = NSAttributedString(
+      string: Localized.Backup.subtitle,
+      attributes: [
+        .foregroundColor: Asset.neutralBody.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
+        .paragraphStyle: paragraph
+      ])
+
+    subtitleLabel.numberOfLines = 0
+    subtitleLabel.attributedText = attString
+
+    sftpButton.titleLabel.text = Localized.Backup.sftp
+    sftpButton.logoImageView.image = Asset.restoreSFTP.image
+
+    iCloudButton.titleLabel.text = Localized.Backup.iCloud
+    iCloudButton.logoImageView.image = Asset.restoreIcloud.image
+
+    dropboxButton.titleLabel.text = Localized.Backup.dropbox
+    dropboxButton.logoImageView.image = Asset.restoreDropbox.image
+
+    googleDriveButton.titleLabel.text = Localized.Backup.googleDrive
+    googleDriveButton.logoImageView.image = Asset.restoreDrive.image
+
+    latestBackupDetailView.titleLabel.text = Localized.Backup.Config.latestBackup
+    frequencyDetailView.accessoryImageView.image = Asset.settingsDisclosure.image
+
+    infrastructureDetailView.titleLabel.text = Localized.Backup.Config.infrastructure.uppercased()
+    infrastructureDetailView.accessoryImageView.image = Asset.settingsDisclosure.image
+
+    enabledSubtitleView.addSubview(enabledSubtitleLabel)
+
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(googleDriveButton)
+    stackView.addArrangedSubview(iCloudButton)
+    stackView.addArrangedSubview(dropboxButton)
+    stackView.addArrangedSubview(sftpButton)
+    stackView.addArrangedSubview(enabledSubtitleView)
+    stackView.addArrangedSubview(latestBackupDetailView)
+    stackView.addArrangedSubview(frequencyDetailView)
+    stackView.addArrangedSubview(infrastructureDetailView)
+
+    addSubview(titleLabel)
+    addSubview(subtitleLabel)
+    addSubview(actionView)
+    addSubview(stackView)
+
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(15)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
     }
 
-    required init?(coder: NSCoder) { nil }
+    enabledSubtitleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(-10)
+      $0.left.equalToSuperview().offset(92)
+      $0.right.equalToSuperview().offset(-48)
+      $0.bottom.equalToSuperview()
+    }
+
+    subtitleLabel.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(8)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
+    }
+
+    actionView.snp.makeConstraints {
+      $0.top.equalTo(subtitleLabel.snp.bottom).offset(15)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-38)
+    }
+
+    stackView.snp.makeConstraints {
+      $0.top.equalTo(actionView.snp.bottom).offset(28)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.lessThanOrEqualToSuperview()
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/BackupFeature/Views/BackupDetailView.swift b/Sources/BackupFeature/Views/BackupDetailView.swift
index d28647330d7cd7b81d516ad7d4b506f712d94d0c..28b75bb1418c0a2e7ae4d9f16920cdea019db646 100644
--- a/Sources/BackupFeature/Views/BackupDetailView.swift
+++ b/Sources/BackupFeature/Views/BackupDetailView.swift
@@ -1,40 +1,41 @@
 import UIKit
 import Shared
+import AppResources
 
 final class BackupDetailView: UIControl {
-    let titleLabel = UILabel()
-    let subtitleLabel = UILabel()
-    let accessoryImageView = UIImageView()
-
-    init() {
-        super.init(frame: .zero)
-
-        titleLabel.font = Fonts.Mulish.bold.font(size: 12.0)
-        subtitleLabel.font = Fonts.Mulish.regular.font(size: 16.0)
-
-        titleLabel.textColor = Asset.neutralWeak.color
-        subtitleLabel.textColor = Asset.neutralActive.color
-
-        addSubview(titleLabel)
-        addSubview(subtitleLabel)
-        addSubview(accessoryImageView)
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(20)
-            make.left.equalToSuperview().offset(92)
-        }
-
-        subtitleLabel.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(4)
-            make.left.equalTo(titleLabel)
-            make.bottom.equalToSuperview().offset(-2)
-        }
-
-        accessoryImageView.snp.makeConstraints { make in
-            make.right.equalToSuperview().offset(-48)
-            make.centerY.equalTo(titleLabel.snp.bottom)
-        }
+  let titleLabel = UILabel()
+  let subtitleLabel = UILabel()
+  let accessoryImageView = UIImageView()
+
+  init() {
+    super.init(frame: .zero)
+
+    titleLabel.font = Fonts.Mulish.bold.font(size: 12.0)
+    subtitleLabel.font = Fonts.Mulish.regular.font(size: 16.0)
+
+    titleLabel.textColor = Asset.neutralWeak.color
+    subtitleLabel.textColor = Asset.neutralActive.color
+
+    addSubview(titleLabel)
+    addSubview(subtitleLabel)
+    addSubview(accessoryImageView)
+
+    titleLabel.snp.makeConstraints { make in
+      make.top.equalToSuperview().offset(20)
+      make.left.equalToSuperview().offset(92)
+    }
+
+    subtitleLabel.snp.makeConstraints { make in
+      make.top.equalTo(titleLabel.snp.bottom).offset(4)
+      make.left.equalTo(titleLabel)
+      make.bottom.equalToSuperview().offset(-2)
+    }
+
+    accessoryImageView.snp.makeConstraints { make in
+      make.right.equalToSuperview().offset(-48)
+      make.centerY.equalTo(titleLabel.snp.bottom)
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/BackupFeature/Views/BackupPassphraseView.swift b/Sources/BackupFeature/Views/BackupPassphraseView.swift
index f2ff27b4d01652f72abab2482a70db9f031d5e55..ea0630520b803a717c5b8d8ed949867b74a52279 100644
--- a/Sources/BackupFeature/Views/BackupPassphraseView.swift
+++ b/Sources/BackupFeature/Views/BackupPassphraseView.swift
@@ -1,80 +1,81 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
 final class BackupPassphraseView: UIView {
-    let titleLabel = UILabel()
-    let stackView = UIStackView()
-    let inputField = InputField()
-    let subtitleLabel = UILabel()
-    let cancelButton = CapsuleButton()
-    let continueButton = CapsuleButton()
+  let titleLabel = UILabel()
+  let stackView = UIStackView()
+  let inputField = InputField()
+  let subtitleLabel = UILabel()
+  let cancelButton = CapsuleButton()
+  let continueButton = CapsuleButton()
 
-    init() {
-        super.init(frame: .zero)
-        layer.cornerRadius = 40
-        backgroundColor = Asset.neutralWhite.color
-        layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
+  init() {
+    super.init(frame: .zero)
+    layer.cornerRadius = 40
+    backgroundColor = Asset.neutralWhite.color
+    layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
 
-        setupInput()
-        setupLabels()
-        setupButtons()
-        setupStackView()
-    }
+    setupInput()
+    setupLabels()
+    setupButtons()
+    setupStackView()
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 
-    private func setupInput() {
-        inputField.setup(
-            style: .regular,
-            title: Localized.Backup.Passphrase.Input.title,
-            placeholder: Localized.Backup.Passphrase.Input.placeholder,
-            rightView: .toggleSecureEntry,
-            subtitleColor: Asset.neutralDisabled.color,
-            allowsEmptySpace: false,
-            autocapitalization: .none,
-            contentType: .newPassword
-        )
-    }
+  private func setupInput() {
+    inputField.setup(
+      style: .regular,
+      title: Localized.Backup.Passphrase.Input.title,
+      placeholder: Localized.Backup.Passphrase.Input.placeholder,
+      rightView: .toggleSecureEntry,
+      subtitleColor: Asset.neutralDisabled.color,
+      allowsEmptySpace: false,
+      autocapitalization: .none,
+      contentType: .newPassword
+    )
+  }
 
-    private func setupLabels() {
-        titleLabel.textAlignment = .left
-        titleLabel.text = Localized.Backup.Passphrase.title
-        titleLabel.textColor = Asset.neutralActive.color
-        titleLabel.font = Fonts.Mulish.bold.font(size: 26.0)
+  private func setupLabels() {
+    titleLabel.textAlignment = .left
+    titleLabel.text = Localized.Backup.Passphrase.title
+    titleLabel.textColor = Asset.neutralActive.color
+    titleLabel.font = Fonts.Mulish.bold.font(size: 26.0)
 
-        subtitleLabel.numberOfLines = 0
-        subtitleLabel.textAlignment = .left
-        subtitleLabel.textColor = Asset.neutralActive.color
-        subtitleLabel.text = Localized.Backup.Passphrase.subtitle
-        subtitleLabel.font = Fonts.Mulish.regular.font(size: 16.0)
-    }
+    subtitleLabel.numberOfLines = 0
+    subtitleLabel.textAlignment = .left
+    subtitleLabel.textColor = Asset.neutralActive.color
+    subtitleLabel.text = Localized.Backup.Passphrase.subtitle
+    subtitleLabel.font = Fonts.Mulish.regular.font(size: 16.0)
+  }
 
-    private func setupButtons() {
-        cancelButton.setStyle(.seeThrough)
-        cancelButton.setTitle(Localized.Backup.Passphrase.cancel, for: .normal)
+  private func setupButtons() {
+    cancelButton.setStyle(.seeThrough)
+    cancelButton.setTitle(Localized.Backup.Passphrase.cancel, for: .normal)
 
-        continueButton.isEnabled = false
-        continueButton.setStyle(.brandColored)
-        continueButton.setTitle(Localized.Backup.Passphrase.continue, for: .normal)
-    }
+    continueButton.isEnabled = false
+    continueButton.setStyle(.brandColored)
+    continueButton.setTitle(Localized.Backup.Passphrase.continue, for: .normal)
+  }
 
-    private func setupStackView() {
-        stackView.spacing = 20
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(titleLabel)
-        stackView.addArrangedSubview(subtitleLabel)
-        stackView.addArrangedSubview(inputField)
-        stackView.addArrangedSubview(continueButton)
-        stackView.addArrangedSubview(cancelButton)
+  private func setupStackView() {
+    stackView.spacing = 20
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(titleLabel)
+    stackView.addArrangedSubview(subtitleLabel)
+    stackView.addArrangedSubview(inputField)
+    stackView.addArrangedSubview(continueButton)
+    stackView.addArrangedSubview(cancelButton)
 
-        addSubview(stackView)
+    addSubview(stackView)
 
-        stackView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(60)
-            $0.left.equalToSuperview().offset(50)
-            $0.right.equalToSuperview().offset(-50)
-            $0.bottom.equalToSuperview().offset(-70)
-        }
+    stackView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(60)
+      $0.left.equalToSuperview().offset(50)
+      $0.right.equalToSuperview().offset(-50)
+      $0.bottom.equalToSuperview().offset(-70)
     }
+  }
 }
diff --git a/Sources/BackupFeature/Views/BackupSetupView.swift b/Sources/BackupFeature/Views/BackupSetupView.swift
index 3e19d50034f4d03ba62d3e4d038d82d24196af89..30ae722dd7b2c630a861cc50dd9f808311446f43 100644
--- a/Sources/BackupFeature/Views/BackupSetupView.swift
+++ b/Sources/BackupFeature/Views/BackupSetupView.swift
@@ -1,99 +1,100 @@
 import UIKit
 import Shared
+import AppResources
 
 final class BackupSetupView: UIView {
-    let titleLabel = UILabel()
-    let subtitleLabel = UILabel()
-
-    let stackView = UIStackView()
-    let sftpButton = BackupSwitcherButton()
-    let iCloudButton = BackupSwitcherButton()
-    let dropboxButton = BackupSwitcherButton()
-    let googleDriveButton = BackupSwitcherButton()
-
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
-
-        let title = Localized.Backup.Setup.title
-
-        let attString = NSMutableAttributedString(string: title)
-        let firstParagraph = NSMutableParagraphStyle()
-        firstParagraph.alignment = .left
-        firstParagraph.lineHeightMultiple = 1
-
-        attString.addAttribute(.paragraphStyle, value: firstParagraph)
-        attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
-        attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
-
-        attString.addAttributes(attributes: [
-            .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
-            .foregroundColor: Asset.brandPrimary.color
-        ], betweenCharacters: "#")
-
-        titleLabel.numberOfLines = 0
-        titleLabel.attributedText = attString
-
-        let secondParagraph = NSMutableParagraphStyle()
-        secondParagraph.alignment = .left
-        secondParagraph.lineHeightMultiple = 1.15
-
-        let secondAttString = NSAttributedString(
-            string: Localized.Backup.subtitle,
-            attributes: [
-                .foregroundColor: Asset.neutralBody.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
-                .paragraphStyle: secondParagraph
-            ])
-
-        subtitleLabel.numberOfLines = 0
-        subtitleLabel.attributedText = secondAttString
-
-        iCloudButton.titleLabel.text = Localized.Backup.iCloud
-        iCloudButton.logoImageView.image = Asset.restoreIcloud.image
-        iCloudButton.showChevron()
-
-        dropboxButton.titleLabel.text = Localized.Backup.dropbox
-        dropboxButton.logoImageView.image = Asset.restoreDropbox.image
-        dropboxButton.showChevron()
-
-        googleDriveButton.titleLabel.text = Localized.Backup.googleDrive
-        googleDriveButton.logoImageView.image = Asset.restoreDrive.image
-        googleDriveButton.showChevron()
-
-        sftpButton.titleLabel.text = Localized.Backup.sftp
-        sftpButton.logoImageView.image = Asset.restoreSFTP.image
-        sftpButton.showChevron()
-
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(googleDriveButton)
-        stackView.addArrangedSubview(iCloudButton)
-        stackView.addArrangedSubview(dropboxButton)
-        stackView.addArrangedSubview(sftpButton)
-
-        addSubview(titleLabel)
-        addSubview(subtitleLabel)
-        addSubview(stackView)
-
-        titleLabel.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(15)
-            $0.left.equalToSuperview().offset(38)
-            $0.right.equalToSuperview().offset(-41)
-        }
-
-        subtitleLabel.snp.makeConstraints {
-            $0.top.equalTo(titleLabel.snp.bottom).offset(8)
-            $0.left.equalToSuperview().offset(38)
-            $0.right.equalToSuperview().offset(-41)
-        }
-
-        stackView.snp.makeConstraints {
-            $0.top.equalTo(subtitleLabel.snp.bottom).offset(28)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.lessThanOrEqualToSuperview()
-        }
+  let titleLabel = UILabel()
+  let subtitleLabel = UILabel()
+
+  let stackView = UIStackView()
+  let sftpButton = BackupSwitcherButton()
+  let iCloudButton = BackupSwitcherButton()
+  let dropboxButton = BackupSwitcherButton()
+  let googleDriveButton = BackupSwitcherButton()
+
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
+
+    let title = Localized.Backup.Setup.title
+
+    let attString = NSMutableAttributedString(string: title)
+    let firstParagraph = NSMutableParagraphStyle()
+    firstParagraph.alignment = .left
+    firstParagraph.lineHeightMultiple = 1
+
+    attString.addAttribute(.paragraphStyle, value: firstParagraph)
+    attString.addAttribute(.foregroundColor, value: Asset.neutralActive.color)
+    attString.addAttribute(.font, value: Fonts.Mulish.bold.font(size: 34.0) as Any)
+
+    attString.addAttributes(attributes: [
+      .font: Fonts.Mulish.bold.font(size: 34.0) as Any,
+      .foregroundColor: Asset.brandPrimary.color
+    ], betweenCharacters: "#")
+
+    titleLabel.numberOfLines = 0
+    titleLabel.attributedText = attString
+
+    let secondParagraph = NSMutableParagraphStyle()
+    secondParagraph.alignment = .left
+    secondParagraph.lineHeightMultiple = 1.15
+
+    let secondAttString = NSAttributedString(
+      string: Localized.Backup.subtitle,
+      attributes: [
+        .foregroundColor: Asset.neutralBody.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0) as Any,
+        .paragraphStyle: secondParagraph
+      ])
+
+    subtitleLabel.numberOfLines = 0
+    subtitleLabel.attributedText = secondAttString
+
+    iCloudButton.titleLabel.text = Localized.Backup.iCloud
+    iCloudButton.logoImageView.image = Asset.restoreIcloud.image
+    iCloudButton.showChevron()
+
+    dropboxButton.titleLabel.text = Localized.Backup.dropbox
+    dropboxButton.logoImageView.image = Asset.restoreDropbox.image
+    dropboxButton.showChevron()
+
+    googleDriveButton.titleLabel.text = Localized.Backup.googleDrive
+    googleDriveButton.logoImageView.image = Asset.restoreDrive.image
+    googleDriveButton.showChevron()
+
+    sftpButton.titleLabel.text = Localized.Backup.sftp
+    sftpButton.logoImageView.image = Asset.restoreSFTP.image
+    sftpButton.showChevron()
+
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(googleDriveButton)
+    stackView.addArrangedSubview(iCloudButton)
+    stackView.addArrangedSubview(dropboxButton)
+    stackView.addArrangedSubview(sftpButton)
+
+    addSubview(titleLabel)
+    addSubview(subtitleLabel)
+    addSubview(stackView)
+
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(15)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
     }
 
-    required init?(coder: NSCoder) { nil }
+    subtitleLabel.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(8)
+      $0.left.equalToSuperview().offset(38)
+      $0.right.equalToSuperview().offset(-41)
+    }
+
+    stackView.snp.makeConstraints {
+      $0.top.equalTo(subtitleLabel.snp.bottom).offset(28)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.lessThanOrEqualToSuperview()
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/BackupFeature/Views/BackupSwitcherButton.swift b/Sources/BackupFeature/Views/BackupSwitcherButton.swift
index 2c115cdc9b723cc7c2ece188e17ef5e3a7ea7533..dfd3a32ea1b66967f9df5da2ae4b62553beab12b 100644
--- a/Sources/BackupFeature/Views/BackupSwitcherButton.swift
+++ b/Sources/BackupFeature/Views/BackupSwitcherButton.swift
@@ -1,69 +1,70 @@
 import UIKit
 import Shared
+import AppResources
 
 final class BackupSwitcherButton: UIControl {
-    let titleLabel = UILabel()
-    let separatorView = UIView()
-    let switcherView = UISwitch()
-    let logoImageView = UIImageView()
-    let chevronImageView = UIImageView()
+  let titleLabel = UILabel()
+  let separatorView = UIView()
+  let switcherView = UISwitch()
+  let logoImageView = UIImageView()
+  let chevronImageView = UIImageView()
 
-    init() {
-        super.init(frame: .zero)
+  init() {
+    super.init(frame: .zero)
 
-        titleLabel.textColor = Asset.neutralActive.color
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
+    titleLabel.textColor = Asset.neutralActive.color
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
 
-        switcherView.onTintColor = Asset.brandLight.color
-        chevronImageView.image = Asset.settingsDisclosure.image
-        separatorView.backgroundColor = Asset.neutralLine.color
+    switcherView.onTintColor = Asset.brandLight.color
+    chevronImageView.image = Asset.settingsDisclosure.image
+    separatorView.backgroundColor = Asset.neutralLine.color
 
-        addSubview(separatorView)
-        addSubview(logoImageView)
-        addSubview(titleLabel)
-        addSubview(switcherView)
-        addSubview(chevronImageView)
+    addSubview(separatorView)
+    addSubview(logoImageView)
+    addSubview(titleLabel)
+    addSubview(switcherView)
+    addSubview(chevronImageView)
 
-        logoImageView.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(20)
-            make.left.equalToSuperview().offset(36)
-            make.bottom.equalToSuperview().offset(-20)
-        }
+    logoImageView.snp.makeConstraints { make in
+      make.top.equalToSuperview().offset(20)
+      make.left.equalToSuperview().offset(36)
+      make.bottom.equalToSuperview().offset(-20)
+    }
 
-        titleLabel.snp.makeConstraints { make in
-            make.left.equalTo(logoImageView.snp.right).offset(15)
-            make.centerY.equalTo(logoImageView)
-        }
+    titleLabel.snp.makeConstraints { make in
+      make.left.equalTo(logoImageView.snp.right).offset(15)
+      make.centerY.equalTo(logoImageView)
+    }
 
-        chevronImageView.snp.makeConstraints { make in
-            make.centerY.equalTo(logoImageView)
-            make.right.equalToSuperview().offset(-48)
-        }
+    chevronImageView.snp.makeConstraints { make in
+      make.centerY.equalTo(logoImageView)
+      make.right.equalToSuperview().offset(-48)
+    }
 
-        switcherView.snp.makeConstraints { make in
-            make.right.equalToSuperview().offset(-25)
-            make.centerY.equalTo(logoImageView)
-        }
+    switcherView.snp.makeConstraints { make in
+      make.right.equalToSuperview().offset(-25)
+      make.centerY.equalTo(logoImageView)
+    }
 
-        separatorView.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.height.equalTo(1)
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-        }
+    separatorView.snp.makeConstraints { make in
+      make.top.equalToSuperview()
+      make.height.equalTo(1)
+      make.left.equalToSuperview().offset(24)
+      make.right.equalToSuperview().offset(-24)
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 
-    func showSwitcher(enabled: Bool) {
-        switcherView.isOn = enabled
-        switcherView.isHidden = false
-        chevronImageView.isHidden = true
-    }
+  func showSwitcher(enabled: Bool) {
+    switcherView.isOn = enabled
+    switcherView.isHidden = false
+    chevronImageView.isHidden = true
+  }
 
-    func showChevron() {
-        switcherView.isOn = false
-        switcherView.isHidden = true
-        chevronImageView.isHidden = false
-    }
+  func showChevron() {
+    switcherView.isOn = false
+    switcherView.isHidden = true
+    chevronImageView.isHidden = false
+  }
 }
diff --git a/Sources/BackupFeature/Views/RestoreSFTPView.swift b/Sources/BackupFeature/Views/RestoreSFTPView.swift
index dfb4d73a12c784ac51c25b27702ac2d592744f01..3d12ccbcf180961a0bdc989404b2571aa944b841 100644
--- a/Sources/BackupFeature/Views/RestoreSFTPView.swift
+++ b/Sources/BackupFeature/Views/RestoreSFTPView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
 final class BackupSFTPView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/CollectionView/CellFactory.swift b/Sources/ChatFeature/CellFactory.swift
similarity index 100%
rename from Sources/CollectionView/CellFactory.swift
rename to Sources/ChatFeature/CellFactory.swift
diff --git a/Sources/ChatFeature/Controllers/GroupChatController.swift b/Sources/ChatFeature/Controllers/GroupChatController.swift
index 97a65ca8cdfb906866a0bd90d8ffff7c3c66bdd4..7a5090ef483860e517d5f128dfcc8e758d86d4b8 100644
--- a/Sources/ChatFeature/Controllers/GroupChatController.swift
+++ b/Sources/ChatFeature/Controllers/GroupChatController.swift
@@ -196,7 +196,7 @@ public final class GroupChatController: UIViewController {
               lineHeightMultiple: 1.35,
               spacingAfter: 25
             ), button
-          ]))
+          ], isDismissable: false, from: self))
 
         case .webview(let urlString):
           navigator.perform(PresentWebsite(url: URL(string: urlString)!))
@@ -260,7 +260,7 @@ public final class GroupChatController: UIViewController {
             spacing: 20.0,
             views: [reportButton, cancelButton]
           )
-        ]))
+        ], isDismissable: true, from: self))
       }.store(in: &cancellables)
 
     viewModel
diff --git a/Sources/ChatFeature/Controllers/SingleChatController.swift b/Sources/ChatFeature/Controllers/SingleChatController.swift
index c4a890898d8ffe657812c7af427ceaf3708df6a2..a8052cb16ae611a98ff44c37c29102e1fc442701 100644
--- a/Sources/ChatFeature/Controllers/SingleChatController.swift
+++ b/Sources/ChatFeature/Controllers/SingleChatController.swift
@@ -213,49 +213,49 @@ public final class SingleChatController: UIViewController {
     viewModel.navigation
       .receive(on: DispatchQueue.main)
       .removeDuplicates()
-      .sink { [unowned self] in
-        switch $0 {
-        case .library:
-          navigator.perform(PresentPhotoLibrary())
-        case .camera:
-          navigator.perform(PresentCamera())
-        case .cameraPermission:
-          navigator.perform(PresentPermissionRequest(type: .camera))
-        case .microphonePermission:
-          navigator.perform(PresentPermissionRequest(type: .microphone))
-        case .libraryPermission:
-          navigator.perform(PresentPermissionRequest(type: .library))
-        case .webview(let urlString):
-          navigator.perform(PresentWebsite(url: URL(string: urlString)!))
-        case .waitingRound:
-          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
-        }
+      .sink { [unowned self] _ in
+//        switch $0 {
+//        case .library:
+//          navigator.perform(PresentPhotoLibrary())
+//        case .camera:
+//          navigator.perform(PresentCamera())
+//        case .cameraPermission:
+//          navigator.perform(PresentPermissionRequest(type: .camera))
+//        case .microphonePermission:
+//          navigator.perform(PresentPermissionRequest(type: .microphone))
+//        case .libraryPermission:
+//          navigator.perform(PresentPermissionRequest(type: .library))
+//        case .webview(let urlString):
+//          navigator.perform(PresentWebsite(url: URL(string: urlString)!))
+//        case .waitingRound:
+//          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
+//        }
 
         viewModel.didNavigateSomewhere()
       }.store(in: &cancellables)
@@ -270,7 +270,10 @@ public final class SingleChatController: UIViewController {
         case .clear:
           presentDeleteAllDrawer()
         case .details:
-          navigator.perform(PresentContact(contact: viewModel.contact))
+          navigator.perform(PresentContact(
+            contact: viewModel.contact,
+            on: navigationController!
+          ))
         case .report:
           presentReportDrawer()
         }
@@ -444,7 +447,7 @@ public final class SingleChatController: UIViewController {
         spacing: 20.0,
         views: [reportButton, cancelButton]
       )
-    ]))
+    ], isDismissable: true, from: self))
   }
 
   private func presentDeleteAllDrawer() {
@@ -497,7 +500,7 @@ public final class SingleChatController: UIViewController {
         spacing: 20.0,
         views: [clearButton, cancelButton]
       )
-    ]))
+    ], isDismissable: true, from: self))
   }
 
   private func previewItemAt(_ indexPath: IndexPath) {
@@ -516,7 +519,10 @@ public final class SingleChatController: UIViewController {
   }
 
   @objc private func didTapInfo() {
-    navigator.perform(PresentContact(contact: viewModel.contact))
+    navigator.perform(PresentContact(
+      contact: viewModel.contact,
+      on: navigationController!
+    ))
   }
 }
 
diff --git a/Sources/CollectionView/ViewConfigurator.swift b/Sources/ChatFeature/ViewConfigurator.swift
similarity index 100%
rename from Sources/CollectionView/ViewConfigurator.swift
rename to Sources/ChatFeature/ViewConfigurator.swift
diff --git a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
index 6f0b3f96767fe92d97cca76bc472ffafb4f665f7..adc8743e058ea95d384a5a60bb522f2312f139c2 100644
--- a/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
+++ b/Sources/ChatFeature/ViewModels/SingleChatViewModel.swift
@@ -15,7 +15,6 @@ import XXMessengerClient
 
 import struct XXModels.Message
 import struct XXModels.FileTransfer
-import NetworkMonitor
 
 enum SingleChatNavigationRoutes: Equatable {
   case none
diff --git a/Sources/ChatInputFeature/ActionButton.swift b/Sources/ChatInputFeature/ActionButton.swift
index 492ba1657c56ffb68bafb5c85b4f0cc94d87c4e3..8ffd5b84b508afe79f71203de25bef1bb9ce8e61 100644
--- a/Sources/ChatInputFeature/ActionButton.swift
+++ b/Sources/ChatInputFeature/ActionButton.swift
@@ -1,51 +1,48 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ActionButton: UIControl {
+  let titleLabel = UILabel()
+  let imageView = UIImageView()
+  let imageBackgroundView = UIView()
 
-    let titleLabel = UILabel()
-    let imageView = UIImageView()
-    let imageBackgroundView = UIView()
+  init() {
+    super.init(frame: .zero)
 
-    init() {
-        super.init(frame: .zero)
-        setup()
-    }
+    imageBackgroundView.layer.cornerRadius = 4
+    titleLabel.textColor = Asset.neutralDark.color
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 10.0)
+    imageBackgroundView.backgroundColor = Asset.neutralSecondary.color
+
+    addSubview(titleLabel)
+    addSubview(imageBackgroundView)
+    imageBackgroundView.addSubview(imageView)
+
+    imageView.isUserInteractionEnabled = false
+    imageBackgroundView.isUserInteractionEnabled = false
 
-    required init?(coder: NSCoder) { nil }
+    imageView.snp.makeConstraints { $0.center.equalToSuperview() }
 
-    func setup(title: String, image: UIImage) {
-        titleLabel.text = title
-        imageView.image = image
+    imageBackgroundView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.width.equalTo(imageBackgroundView.snp.height)
     }
 
-    private func setup() {
-        imageBackgroundView.layer.cornerRadius = 4
-        titleLabel.textColor = Asset.neutralDark.color
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 10.0)
-        imageBackgroundView.backgroundColor = Asset.neutralSecondary.color
-
-        addSubview(titleLabel)
-        addSubview(imageBackgroundView)
-        imageBackgroundView.addSubview(imageView)
-
-        imageView.isUserInteractionEnabled = false
-        imageBackgroundView.isUserInteractionEnabled = false
-
-        imageView.snp.makeConstraints { $0.center.equalToSuperview() }
-
-        imageBackgroundView.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.width.equalTo(imageBackgroundView.snp.height)
-        }
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalTo(imageBackgroundView.snp.bottom).offset(4)
-            make.centerX.equalToSuperview()
-            make.left.greaterThanOrEqualToSuperview()
-            make.bottom.equalToSuperview()
-        }
+    titleLabel.snp.makeConstraints {
+      $0.top.equalTo(imageBackgroundView.snp.bottom).offset(4)
+      $0.centerX.equalToSuperview()
+      $0.left.greaterThanOrEqualToSuperview()
+      $0.bottom.equalToSuperview()
     }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  func setup(title: String, image: UIImage) {
+    titleLabel.text = title
+    imageView.image = image
+  }
 }
diff --git a/Sources/ChatInputFeature/ActionsView.swift b/Sources/ChatInputFeature/ActionsView.swift
index f6cd9123754a31e7f70512a507cb31a965fe10bd..0668f7b94162a9d31c2dd818c892886a186ef79a 100644
--- a/Sources/ChatInputFeature/ActionsView.swift
+++ b/Sources/ChatInputFeature/ActionsView.swift
@@ -1,43 +1,39 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ActionsView: UIView {
-
-    let stack = UIStackView()
-    let cameraButton = ActionButton()
-    let libraryButton = ActionButton()
-
-    init() {
-        super.init(frame: .zero)
-        setup()
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    private func setup() {
-        cameraButton.setup(
-            title: Localized.Chat.Actions.camera,
-            image: Asset.chatInputActionCamera.image
-        )
-
-        libraryButton.setup(
-            title: Localized.Chat.Actions.gallery,
-            image: Asset.chatInputActionGallery.image
-        )
-
-        stack.spacing = 33
-        stack.axis = .horizontal
-        stack.distribution = .fillEqually
-        stack.addArrangedSubview(cameraButton)
-        stack.addArrangedSubview(libraryButton)
-
-        addSubview(stack)
-        stack.translatesAutoresizingMaskIntoConstraints = false
-        NSLayoutConstraint.activate([
-            stack.topAnchor.constraint(equalTo: topAnchor),
-            stack.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20),
-            stack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20),
-            stack.bottomAnchor.constraint(equalTo: bottomAnchor),
-        ])
-    }
+  let stack = UIStackView()
+  let cameraButton = ActionButton()
+  let libraryButton = ActionButton()
+
+  init() {
+    super.init(frame: .zero)
+    cameraButton.setup(
+      title: Localized.Chat.Actions.camera,
+      image: Asset.chatInputActionCamera.image
+    )
+    
+    libraryButton.setup(
+      title: Localized.Chat.Actions.gallery,
+      image: Asset.chatInputActionGallery.image
+    )
+
+    stack.spacing = 33
+    stack.axis = .horizontal
+    stack.distribution = .fillEqually
+    stack.addArrangedSubview(cameraButton)
+    stack.addArrangedSubview(libraryButton)
+
+    addSubview(stack)
+    stack.translatesAutoresizingMaskIntoConstraints = false
+    NSLayoutConstraint.activate([
+      stack.topAnchor.constraint(equalTo: topAnchor),
+      stack.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 20),
+      stack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -20),
+      stack.bottomAnchor.constraint(equalTo: bottomAnchor),
+    ])
+  }
+
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/ChatInputFeature/AudioView.swift b/Sources/ChatInputFeature/AudioView.swift
index cd43082ac940a9038edd6e8506237b5be141715a..b7fb0d354800cfd719d28df6db56e2ad0cc7b0b4 100644
--- a/Sources/ChatInputFeature/AudioView.swift
+++ b/Sources/ChatInputFeature/AudioView.swift
@@ -1,56 +1,53 @@
 import UIKit
 import Shared
+import AppResources
 
 final class AudioView: UIView {
-
-    let stack = UIStackView()
-    let timeLabel = UILabel()
-    let playButton = UIButton()
-    let sendButton = UIButton()
-    let cancelButton = UIButton()
-    let stopPlaybackButton = UIButton()
-    let stopRecordingButton = UIButton()
-
-    init() {
-        super.init(frame: .zero)
-        setup()
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    private func setup() {
-        timeLabel.textAlignment = .center
-        timeLabel.textColor = Asset.neutralDark.color
-        timeLabel.font = Fonts.Mulish.semiBold.font(size: 13)
-
-        sendButton.setImage(Asset.chatSend.image, for: .normal)
-        playButton.setImage(Asset.chatInputVoicePlay.image, for: .normal)
-        cancelButton.setImage(Asset.chatInputActionClose.image, for: .normal)
-        stopPlaybackButton.setImage(Asset.chatInputVoicePause.image, for: .normal)
-        stopRecordingButton.setImage(Asset.chatInputVoiceStop.image, for: .normal)
-
-        stack.spacing = 8
-        stack.axis = .horizontal
-        stack.addArrangedSubview(cancelButton)
-        stack.addArrangedSubview(playButton)
-        stack.addArrangedSubview(stopPlaybackButton)
-        stack.addArrangedSubview(timeLabel)
-        stack.addArrangedSubview(stopRecordingButton)
-        stack.addArrangedSubview(sendButton)
-
-        cancelButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
-        playButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
-        stopPlaybackButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
-        sendButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
-        timeLabel.setContentHuggingPriority(.defaultLow, for: .horizontal)
-
-        addSubview(stack)
-        stack.translatesAutoresizingMaskIntoConstraints = false
-        NSLayoutConstraint.activate([
-            stack.topAnchor.constraint(equalTo: topAnchor),
-            stack.leadingAnchor.constraint(equalTo: leadingAnchor),
-            stack.trailingAnchor.constraint(equalTo: trailingAnchor),
-            stack.bottomAnchor.constraint(equalTo: bottomAnchor),
-        ])
-    }
+  let stack = UIStackView()
+  let timeLabel = UILabel()
+  let playButton = UIButton()
+  let sendButton = UIButton()
+  let cancelButton = UIButton()
+  let stopPlaybackButton = UIButton()
+  let stopRecordingButton = UIButton()
+
+  init() {
+    super.init(frame: .zero)
+
+    timeLabel.textAlignment = .center
+    timeLabel.textColor = Asset.neutralDark.color
+    timeLabel.font = Fonts.Mulish.semiBold.font(size: 13)
+
+    sendButton.setImage(Asset.chatSend.image, for: .normal)
+    playButton.setImage(Asset.chatInputVoicePlay.image, for: .normal)
+    cancelButton.setImage(Asset.chatInputActionClose.image, for: .normal)
+    stopPlaybackButton.setImage(Asset.chatInputVoicePause.image, for: .normal)
+    stopRecordingButton.setImage(Asset.chatInputVoiceStop.image, for: .normal)
+
+    stack.spacing = 8
+    stack.axis = .horizontal
+    stack.addArrangedSubview(cancelButton)
+    stack.addArrangedSubview(playButton)
+    stack.addArrangedSubview(stopPlaybackButton)
+    stack.addArrangedSubview(timeLabel)
+    stack.addArrangedSubview(stopRecordingButton)
+    stack.addArrangedSubview(sendButton)
+
+    cancelButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
+    playButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
+    stopPlaybackButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
+    sendButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
+    timeLabel.setContentHuggingPriority(.defaultLow, for: .horizontal)
+
+    addSubview(stack)
+    stack.translatesAutoresizingMaskIntoConstraints = false
+    NSLayoutConstraint.activate([
+      stack.topAnchor.constraint(equalTo: topAnchor),
+      stack.leadingAnchor.constraint(equalTo: leadingAnchor),
+      stack.trailingAnchor.constraint(equalTo: trailingAnchor),
+      stack.bottomAnchor.constraint(equalTo: bottomAnchor),
+    ])
+  }
+
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/ChatInputFeature/ChatInputReply.swift b/Sources/ChatInputFeature/ChatInputReply.swift
index d5353e34ab95481fc899189efa84c6e7ad4ca86f..ff3d9f958cc5f133d4d5189c9d57305b16ecb7fd 100644
--- a/Sources/ChatInputFeature/ChatInputReply.swift
+++ b/Sources/ChatInputFeature/ChatInputReply.swift
@@ -1,78 +1,71 @@
 import UIKit
 import Shared
+import AppResources
 
 final class ChatInputReply: UIView {
+  let nameLabel = UILabel()
+  let titleLabel = UILabel()
+  let abortButton = UIButton()
+  let messageLabel = UILabel()
 
-    let nameLabel = UILabel()
-    let titleLabel = UILabel()
-    let abortButton = UIButton()
-    let messageLabel = UILabel()
+  init() {
+    super.init(frame: .zero)
 
-    init() {
-        super.init(frame: .zero)
-        setup()
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    func setup(message: String?, sender: String?) {
-        guard let message = message else {
-            isHidden = true
-            return
-        }
-
-        isHidden = false
-        messageLabel.text = message
-        nameLabel.text = sender ?? "You"
-    }
+    titleLabel.text = "Replying to"
+    messageLabel.numberOfLines = 2
+    abortButton.setImage(Asset.replyAbort.image, for: .normal)
 
-    private func setup() {
-        titleLabel.text = "Replying to"
-        messageLabel.numberOfLines = 2
-        abortButton.setImage(Asset.replyAbort.image, for: .normal)
+    nameLabel.font = Fonts.Mulish.bold.font(size: 11.0)
+    titleLabel.font = Fonts.Mulish.regular.font(size: 12.0)
+    messageLabel.font = Fonts.Mulish.regular.font(size: 11.0)
 
-        nameLabel.font = Fonts.Mulish.bold.font(size: 11.0)
-        titleLabel.font = Fonts.Mulish.regular.font(size: 12.0)
-        messageLabel.font = Fonts.Mulish.regular.font(size: 11.0)
+    nameLabel.textColor = Asset.neutralBody.color
+    titleLabel.textColor = Asset.neutralBody.color
+    messageLabel.textColor = Asset.neutralBody.color
 
-        nameLabel.textColor = Asset.neutralBody.color
-        titleLabel.textColor = Asset.neutralBody.color
-        messageLabel.textColor = Asset.neutralBody.color
+    addSubview(nameLabel)
+    addSubview(titleLabel)
+    addSubview(abortButton)
+    addSubview(messageLabel)
 
-        addSubview(nameLabel)
-        addSubview(titleLabel)
-        addSubview(abortButton)
-        addSubview(messageLabel)
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(10)
+      $0.left.equalToSuperview().offset(19)
+      $0.right.lessThanOrEqualToSuperview()
+      $0.height.equalTo(15)
+    }
 
-        setupConstraints()
+    nameLabel.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(11)
+      $0.left.equalTo(titleLabel)
+      $0.right.lessThanOrEqualToSuperview().offset(-30)
+      $0.height.equalTo(10)
     }
 
-    private func setupConstraints() {
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(10)
-            make.left.equalToSuperview().offset(19)
-            make.right.lessThanOrEqualToSuperview()
-            make.height.equalTo(15)
-        }
+    messageLabel.snp.makeConstraints {
+      $0.left.equalToSuperview().offset(28)
+      $0.top.equalTo(nameLabel.snp.bottom).offset(4)
+      $0.right.equalToSuperview().offset(-41)
+      $0.bottom.equalToSuperview().offset(-10)
+      $0.height.equalTo(30)
+    }
 
-        nameLabel.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(11)
-            make.left.equalTo(titleLabel)
-            make.right.lessThanOrEqualToSuperview().offset(-30)
-            make.height.equalTo(10)
-        }
+    abortButton.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(12)
+      $0.right.equalToSuperview().offset(-12)
+    }
+  }
 
-        messageLabel.snp.makeConstraints { make in
-            make.left.equalToSuperview().offset(28)
-            make.top.equalTo(nameLabel.snp.bottom).offset(4)
-            make.right.equalToSuperview().offset(-41)
-            make.bottom.equalToSuperview().offset(-10)
-            make.height.equalTo(30)
-        }
+  required init?(coder: NSCoder) { nil }
 
-        abortButton.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(12)
-            make.right.equalToSuperview().offset(-12)
-        }
+  func setup(message: String?, sender: String?) {
+    guard let message = message else {
+      isHidden = true
+      return
     }
+
+    isHidden = false
+    messageLabel.text = message
+    nameLabel.text = sender ?? "You"
+  }
 }
diff --git a/Sources/ChatInputFeature/ChatInputView.swift b/Sources/ChatInputFeature/ChatInputView.swift
index 31e5a8ae93cb5f49b64765280130dd89efe87bd1..eef904e58e8f57277a57a3789bd3db15f7ac7adc 100644
--- a/Sources/ChatInputFeature/ChatInputView.swift
+++ b/Sources/ChatInputFeature/ChatInputView.swift
@@ -3,228 +3,228 @@ import Shared
 import Combine
 import CasePaths
 import Voxophone
+import AppResources
 import ComposableArchitecture
 
 public final class ChatInputView: UIToolbar {
-
-    public init(store: Store<ChatInputState, ChatInputAction>) {
-        self.store = store
-        self.viewStore = ViewStore(store)
-        super.init(frame: .zero)
-
-        setup()
-        observeStore()
-        setupUIActions()
-        viewStore.send(.setup)
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    deinit {
-        viewStore.send(.destroy)
-    }
-
-    public func setMaxHeight(_ function: @escaping () -> CGFloat) {
-        text.maxHeight = function
-    }
-
-    public func setupReply(message: String, sender: String) {
-        viewStore.send(.text(.didTriggerReply(message, sender)))
-    }
-
-    let store: Store<ChatInputState, ChatInputAction>
-    let viewStore: ViewStore<ChatInputState, ChatInputAction>
-    private var cancellables: Set<AnyCancellable> = []
-
-    let stack = UIStackView()
-    let text = TextInputView()
-    let audio = AudioView()
-    let actions = ActionsView()
-
-    private func setup() {
-        isTranslucent = false
-        translatesAutoresizingMaskIntoConstraints = false
-        barTintColor = Asset.neutralWhite.color
-
-        stack.axis = .vertical
-        stack.spacing = 8
-        stack.addArrangedSubview(text)
-        stack.addArrangedSubview(audio)
-        stack.addArrangedSubview(actions)
-
-        addSubview(stack)
-        stack.translatesAutoresizingMaskIntoConstraints = false
-        NSLayoutConstraint.activate([
-            stack.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 8),
-            stack.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor, constant: 8),
-            stack.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -8),
-            stack.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -8),
-        ])
-    }
-
-    private func observeStore() {
-        viewStore.publisher
-            .map(\.isPresentingActions)
-            .combineLatest(viewStore.publisher.map(\.canAddAttachments))
-            .sink { [unowned self] isPresentingActions, canAddAttachments in
-                if canAddAttachments {
-                    text.showActionsButton.isHidden = isPresentingActions
-                    text.hideActionsButton.isHidden = !isPresentingActions
-                    actions.isHidden = !isPresentingActions
-                } else {
-                    text.showActionsButton.isHidden = true
-                    text.hideActionsButton.isHidden = true
-                    actions.isHidden = true
-                }
-            }
-            .store(in: &cancellables)
-
-        viewStore.publisher
-            .map(\.reply)
-            .sink { [unowned self] reply in
-                guard let reply = reply else {
-                    text.replyView.isHidden = true
-                    return
-                }
-
-                text.replyView.isHidden = false
-                text.replyView.messageLabel.text = reply.text
-                text.replyView.nameLabel.text = reply.name
-            }.store(in: &cancellables)
-
-        viewStore.publisher
-            .map(\.audio)
-            .map { $0 != nil }
-            .sink { [unowned self] in
-                text.isHidden = $0
-                audio.isHidden = !$0
-            }
-            .store(in: &cancellables)
-
-        viewStore.publisher
-            .map(\.text.isEmpty)
-            .combineLatest(viewStore.publisher.map(\.canAddAttachments))
-            .sink { [unowned self] textIsEmpty, canAddAttachments in
-                if canAddAttachments {
-                    text.sendButton.isHidden = textIsEmpty
-                    text.audioButton.isHidden = !textIsEmpty
-                } else {
-                    text.sendButton.isHidden = false
-                    text.audioButton.isHidden = true
-                }
-
-                text.sendButton.isEnabled = !textIsEmpty
-                text.placeholderView.isHidden = !textIsEmpty
-            }
-            .store(in: &cancellables)
-
-        viewStore.publisher
-            .map(\.text)
-            .sink { [unowned self] in
-                if text.textView.markedTextRange == nil {
-                    let range = text.textView.selectedTextRange
-                    text.textView.text = $0
-
-                    if let range = range {
-                        text.textView.selectedTextRange = range
-                    }
-                } else if $0 == "" {
-                    text.textView.text = $0
-                }
-
-                text.updateHeight()
-            }.store(in: &cancellables)
-
-        let timeFormatter = DateComponentsFormatter()
-        timeFormatter.unitsStyle = .positional
-        timeFormatter.allowedUnits = [.minute, .second]
-        timeFormatter.zeroFormattingBehavior = .pad
-
-        viewStore.publisher
-            .map(\.audio)
-            .sink { [unowned self] in
-                switch $0 {
-                case let .idle(_, duration):
-                    audio.playButton.isHidden = false
-                    audio.stopPlaybackButton.isHidden = true
-                    audio.stopRecordingButton.isHidden = true
-                    audio.sendButton.isHidden = false
-                    audio.timeLabel.text = timeFormatter.string(from: duration)
-
-                case let .recording(_, time):
-                    audio.playButton.isHidden = true
-                    audio.stopPlaybackButton.isHidden = true
-                    audio.stopRecordingButton.isHidden = false
-                    audio.sendButton.isHidden = true
-                    audio.timeLabel.text = timeFormatter.string(from: time)
-
-                case let .playing(_, _, time):
-                    audio.playButton.isHidden = true
-                    audio.stopPlaybackButton.isHidden = false
-                    audio.stopRecordingButton.isHidden = true
-                    audio.sendButton.isHidden = false
-                    audio.timeLabel.text = timeFormatter.string(from: time)
-
-                case .none:
-                    audio.playButton.isHidden = true
-                    audio.stopPlaybackButton.isHidden = true
-                    audio.stopRecordingButton.isHidden = true
-                    audio.sendButton.isHidden = true
-                    audio.timeLabel.text = ""
-                }
-            }
-            .store(in: &cancellables)
-    }
-
-    private func setupUIActions() {
-        text.textDidChange = { [unowned self] text in viewStore.send(.text(.didUpdate(text))) }
-
-        text.replyView.abortButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewStore.send(.text(.didTapAbortReply)) }
-            .store(in: &cancellables)
-
-        text.showActionsButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewStore.send(.text(.didTapShowActions)) }
-            .store(in: &cancellables)
-
-        text.hideActionsButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewStore.send(.text(.didTapHideActions)) }
-            .store(in: &cancellables)
-
-        text.sendButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewStore.send(.text(.didTapSend)) }
-            .store(in: &cancellables)
-
-        text.audioButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewStore.send(.text(.didTapAudio)) }
-            .store(in: &cancellables)
-
-        audio.cancelButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewStore.send(.audio(.didTapCancel)) }
-            .store(in: &cancellables)
-
-        audio.playButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewStore.send(.audio(.didTapPlay)) }
-            .store(in: &cancellables)
-
-        audio.stopPlaybackButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewStore.send(.audio(.didTapStopPlayback)) }
-            .store(in: &cancellables)
-
-        audio.stopRecordingButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewStore.send(.audio(.didTapStopRecording)) }
-            .store(in: &cancellables)
-
-        audio.sendButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewStore.send(.audio(.didTapSend)) }
-            .store(in: &cancellables)
-
-        actions.libraryButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewStore.send(.actions(.didTapLibrary)) }
-            .store(in: &cancellables)
-
-        actions.cameraButton.publisher(for: .touchUpInside)
-            .sink { [unowned self] in viewStore.send(.actions(.didTapCamera)) }
-            .store(in: &cancellables)
-    }
+  public init(store: Store<ChatInputState, ChatInputAction>) {
+    self.store = store
+    self.viewStore = ViewStore(store)
+    super.init(frame: .zero)
+
+    setup()
+    observeStore()
+    setupUIActions()
+    viewStore.send(.setup)
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  deinit {
+    viewStore.send(.destroy)
+  }
+
+  public func setMaxHeight(_ function: @escaping () -> CGFloat) {
+    text.maxHeight = function
+  }
+
+  public func setupReply(message: String, sender: String) {
+    viewStore.send(.text(.didTriggerReply(message, sender)))
+  }
+
+  let store: Store<ChatInputState, ChatInputAction>
+  let viewStore: ViewStore<ChatInputState, ChatInputAction>
+  private var cancellables: Set<AnyCancellable> = []
+
+  let stack = UIStackView()
+  let text = TextInputView()
+  let audio = AudioView()
+  let actions = ActionsView()
+
+  private func setup() {
+    isTranslucent = false
+    translatesAutoresizingMaskIntoConstraints = false
+    barTintColor = Asset.neutralWhite.color
+
+    stack.axis = .vertical
+    stack.spacing = 8
+    stack.addArrangedSubview(text)
+    stack.addArrangedSubview(audio)
+    stack.addArrangedSubview(actions)
+
+    addSubview(stack)
+    stack.translatesAutoresizingMaskIntoConstraints = false
+    NSLayoutConstraint.activate([
+      stack.topAnchor.constraint(equalTo: safeAreaLayoutGuide.topAnchor, constant: 8),
+      stack.leadingAnchor.constraint(equalTo: safeAreaLayoutGuide.leadingAnchor, constant: 8),
+      stack.trailingAnchor.constraint(equalTo: safeAreaLayoutGuide.trailingAnchor, constant: -8),
+      stack.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor, constant: -8),
+    ])
+  }
+
+  private func observeStore() {
+    viewStore.publisher
+      .map(\.isPresentingActions)
+      .combineLatest(viewStore.publisher.map(\.canAddAttachments))
+      .sink { [unowned self] isPresentingActions, canAddAttachments in
+        if canAddAttachments {
+          text.showActionsButton.isHidden = isPresentingActions
+          text.hideActionsButton.isHidden = !isPresentingActions
+          actions.isHidden = !isPresentingActions
+        } else {
+          text.showActionsButton.isHidden = true
+          text.hideActionsButton.isHidden = true
+          actions.isHidden = true
+        }
+      }
+      .store(in: &cancellables)
+
+    viewStore.publisher
+      .map(\.reply)
+      .sink { [unowned self] reply in
+        guard let reply = reply else {
+          text.replyView.isHidden = true
+          return
+        }
+
+        text.replyView.isHidden = false
+        text.replyView.messageLabel.text = reply.text
+        text.replyView.nameLabel.text = reply.name
+      }.store(in: &cancellables)
+
+    viewStore.publisher
+      .map(\.audio)
+      .map { $0 != nil }
+      .sink { [unowned self] in
+        text.isHidden = $0
+        audio.isHidden = !$0
+      }
+      .store(in: &cancellables)
+
+    viewStore.publisher
+      .map(\.text.isEmpty)
+      .combineLatest(viewStore.publisher.map(\.canAddAttachments))
+      .sink { [unowned self] textIsEmpty, canAddAttachments in
+        if canAddAttachments {
+          text.sendButton.isHidden = textIsEmpty
+          text.audioButton.isHidden = !textIsEmpty
+        } else {
+          text.sendButton.isHidden = false
+          text.audioButton.isHidden = true
+        }
+
+        text.sendButton.isEnabled = !textIsEmpty
+        text.placeholderView.isHidden = !textIsEmpty
+      }
+      .store(in: &cancellables)
+
+    viewStore.publisher
+      .map(\.text)
+      .sink { [unowned self] in
+        if text.textView.markedTextRange == nil {
+          let range = text.textView.selectedTextRange
+          text.textView.text = $0
+
+          if let range = range {
+            text.textView.selectedTextRange = range
+          }
+        } else if $0 == "" {
+          text.textView.text = $0
+        }
+
+        text.updateHeight()
+      }.store(in: &cancellables)
+
+    let timeFormatter = DateComponentsFormatter()
+    timeFormatter.unitsStyle = .positional
+    timeFormatter.allowedUnits = [.minute, .second]
+    timeFormatter.zeroFormattingBehavior = .pad
+
+    viewStore.publisher
+      .map(\.audio)
+      .sink { [unowned self] in
+        switch $0 {
+        case let .idle(_, duration):
+          audio.playButton.isHidden = false
+          audio.stopPlaybackButton.isHidden = true
+          audio.stopRecordingButton.isHidden = true
+          audio.sendButton.isHidden = false
+          audio.timeLabel.text = timeFormatter.string(from: duration)
+
+        case let .recording(_, time):
+          audio.playButton.isHidden = true
+          audio.stopPlaybackButton.isHidden = true
+          audio.stopRecordingButton.isHidden = false
+          audio.sendButton.isHidden = true
+          audio.timeLabel.text = timeFormatter.string(from: time)
+
+        case let .playing(_, _, time):
+          audio.playButton.isHidden = true
+          audio.stopPlaybackButton.isHidden = false
+          audio.stopRecordingButton.isHidden = true
+          audio.sendButton.isHidden = false
+          audio.timeLabel.text = timeFormatter.string(from: time)
+
+        case .none:
+          audio.playButton.isHidden = true
+          audio.stopPlaybackButton.isHidden = true
+          audio.stopRecordingButton.isHidden = true
+          audio.sendButton.isHidden = true
+          audio.timeLabel.text = ""
+        }
+      }
+      .store(in: &cancellables)
+  }
+
+  private func setupUIActions() {
+    text.textDidChange = { [unowned self] text in viewStore.send(.text(.didUpdate(text))) }
+
+    text.replyView.abortButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewStore.send(.text(.didTapAbortReply)) }
+      .store(in: &cancellables)
+
+    text.showActionsButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewStore.send(.text(.didTapShowActions)) }
+      .store(in: &cancellables)
+
+    text.hideActionsButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewStore.send(.text(.didTapHideActions)) }
+      .store(in: &cancellables)
+
+    text.sendButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewStore.send(.text(.didTapSend)) }
+      .store(in: &cancellables)
+
+    text.audioButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewStore.send(.text(.didTapAudio)) }
+      .store(in: &cancellables)
+
+    audio.cancelButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewStore.send(.audio(.didTapCancel)) }
+      .store(in: &cancellables)
+
+    audio.playButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewStore.send(.audio(.didTapPlay)) }
+      .store(in: &cancellables)
+
+    audio.stopPlaybackButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewStore.send(.audio(.didTapStopPlayback)) }
+      .store(in: &cancellables)
+
+    audio.stopRecordingButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewStore.send(.audio(.didTapStopRecording)) }
+      .store(in: &cancellables)
+
+    audio.sendButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewStore.send(.audio(.didTapSend)) }
+      .store(in: &cancellables)
+
+    actions.libraryButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewStore.send(.actions(.didTapLibrary)) }
+      .store(in: &cancellables)
+
+    actions.cameraButton.publisher(for: .touchUpInside)
+      .sink { [unowned self] in viewStore.send(.actions(.didTapCamera)) }
+      .store(in: &cancellables)
+  }
 }
diff --git a/Sources/ChatInputFeature/TextInputView.swift b/Sources/ChatInputFeature/TextInputView.swift
index 960d534fe9757710edb7cb157dd6fe6852f77d00..9a074c8cf78f058a97ff59e5f49475f5da85c1dd 100644
--- a/Sources/ChatInputFeature/TextInputView.swift
+++ b/Sources/ChatInputFeature/TextInputView.swift
@@ -1,121 +1,122 @@
 import UIKit
 import Shared
+import AppResources
 
 final class TextInputView: UIView, UITextViewDelegate {
-    let internalStack = UIStackView()
-    var replyView = ChatInputReply()
-    var placeholderView = UITextView()
-    lazy var bubble = BubbleView(internalStack, padding: 4)
-
-    let stack = UIStackView()
-    let textView = UITextView()
-    let showActionsButton = UIButton()
-    let hideActionsButton = UIButton()
-    let sendButton = UIButton()
-    let audioButton = UIButton()
-
-    var maxHeight: () -> CGFloat = { 150 }
-    var textDidChange: (String) -> Void = { _ in }
-
-    private var computedTextHeight: CGFloat {
-        let textWidth = textView.frame.size.width
-        let size = CGSize(width: textWidth, height: .greatestFiniteMagnitude)
-        return textView.sizeThatFits(size).height
+  let internalStack = UIStackView()
+  var replyView = ChatInputReply()
+  var placeholderView = UITextView()
+  lazy var bubble = BubbleView(internalStack, padding: 4)
+
+  let stack = UIStackView()
+  let textView = UITextView()
+  let showActionsButton = UIButton()
+  let hideActionsButton = UIButton()
+  let sendButton = UIButton()
+  let audioButton = UIButton()
+
+  var maxHeight: () -> CGFloat = { 150 }
+  var textDidChange: (String) -> Void = { _ in }
+
+  private var computedTextHeight: CGFloat {
+    let textWidth = textView.frame.size.width
+    let size = CGSize(width: textWidth, height: .greatestFiniteMagnitude)
+    return textView.sizeThatFits(size).height
+  }
+
+  init() {
+    super.init(frame: .zero)
+    setup()
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  override func layoutSubviews() {
+    super.layoutSubviews()
+    updateHeight()
+  }
+
+  func updateHeight() {
+    let replyHeight = replyView.isHidden ? 0 : replyView.bounds.height
+    let computedTextHeight = self.computedTextHeight
+    let computedHeight = computedTextHeight + replyHeight
+    let maxHeight = self.maxHeight()
+
+    if computedHeight < maxHeight {
+      textView.snp.updateConstraints { $0.height.equalTo(computedTextHeight) }
+      textView.isScrollEnabled = false
+    } else {
+      textView.snp.updateConstraints { $0.height.equalTo(maxHeight - replyHeight) }
+      textView.isScrollEnabled = true
     }
-
-    init() {
-        super.init(frame: .zero)
-        setup()
+  }
+
+  private func setup() {
+    replyView.isHidden = true
+    textView.autocorrectionType = .default
+    placeholderView.isUserInteractionEnabled = false
+    textView.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    placeholderView.text = Localized.Chat.placeholder
+    placeholderView.font = Fonts.Mulish.semiBold.font(size: 14.0)
+
+    textView.backgroundColor = .clear
+    placeholderView.backgroundColor = .clear
+    textView.textColor = Asset.neutralActive.color
+    bubble.backgroundColor = Asset.neutralSecondary.color
+    placeholderView.textColor = Asset.neutralDisabled.color
+
+    showActionsButton.setImage(Asset.chatInputActionOpen.image, for: .normal)
+    hideActionsButton.setImage(Asset.chatInputActionClose.image, for: .normal)
+    audioButton.setImage(Asset.chatInputVoiceStart.image, for: .normal)
+    sendButton.setImage(Asset.chatSend.image, for: .normal)
+
+    showActionsButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
+    showActionsButton.setContentCompressionResistancePriority(.required, for: .horizontal)
+
+    hideActionsButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
+    hideActionsButton.setContentCompressionResistancePriority(.required, for: .horizontal)
+
+    sendButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
+    sendButton.setContentCompressionResistancePriority(.required, for: .horizontal)
+
+    audioButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
+    audioButton.setContentCompressionResistancePriority(.required, for: .horizontal)
+
+    internalStack.axis = .vertical
+    internalStack.addArrangedSubview(replyView)
+    internalStack.addArrangedSubview(textView)
+
+    textView.addSubview(placeholderView)
+    textView.setContentHuggingPriority(.defaultLow, for: .horizontal)
+
+    placeholderView.snp.makeConstraints { make in
+      make.top.equalToSuperview()
+      make.left.equalToSuperview()
+      make.height.equalToSuperview()
+      make.width.equalToSuperview()
     }
 
-    required init?(coder: NSCoder) { nil }
-
-    override func layoutSubviews() {
-        super.layoutSubviews()
-        updateHeight()
-    }
-
-    func updateHeight() {
-        let replyHeight = replyView.isHidden ? 0 : replyView.bounds.height
-        let computedTextHeight = self.computedTextHeight
-        let computedHeight = computedTextHeight + replyHeight
-        let maxHeight = self.maxHeight()
-
-        if computedHeight < maxHeight {
-            textView.snp.updateConstraints { $0.height.equalTo(computedTextHeight) }
-            textView.isScrollEnabled = false
-        } else {
-            textView.snp.updateConstraints { $0.height.equalTo(maxHeight - replyHeight) }
-            textView.isScrollEnabled = true
-        }
-    }
-
-    private func setup() {
-        replyView.isHidden = true
-        textView.autocorrectionType = .default
-        placeholderView.isUserInteractionEnabled = false
-        textView.font = Fonts.Mulish.semiBold.font(size: 14.0)
-        placeholderView.text = Localized.Chat.placeholder
-        placeholderView.font = Fonts.Mulish.semiBold.font(size: 14.0)
-
-        textView.backgroundColor = .clear
-        placeholderView.backgroundColor = .clear
-        textView.textColor = Asset.neutralActive.color
-        bubble.backgroundColor = Asset.neutralSecondary.color
-        placeholderView.textColor = Asset.neutralDisabled.color
-
-        showActionsButton.setImage(Asset.chatInputActionOpen.image, for: .normal)
-        hideActionsButton.setImage(Asset.chatInputActionClose.image, for: .normal)
-        audioButton.setImage(Asset.chatInputVoiceStart.image, for: .normal)
-        sendButton.setImage(Asset.chatSend.image, for: .normal)
-
-        showActionsButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
-        showActionsButton.setContentCompressionResistancePriority(.required, for: .horizontal)
-
-        hideActionsButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
-        hideActionsButton.setContentCompressionResistancePriority(.required, for: .horizontal)
-
-        sendButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
-        sendButton.setContentCompressionResistancePriority(.required, for: .horizontal)
-
-        audioButton.setContentHuggingPriority(.defaultHigh, for: .horizontal)
-        audioButton.setContentCompressionResistancePriority(.required, for: .horizontal)
-
-        internalStack.axis = .vertical
-        internalStack.addArrangedSubview(replyView)
-        internalStack.addArrangedSubview(textView)
-
-        textView.addSubview(placeholderView)
-        textView.setContentHuggingPriority(.defaultLow, for: .horizontal)
-
-        placeholderView.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview()
-            make.height.equalToSuperview()
-            make.width.equalToSuperview()
-        }
-
-        stack.axis = .horizontal
-        stack.spacing = 8
-        stack.addArrangedSubview(showActionsButton)
-        stack.addArrangedSubview(hideActionsButton)
-        stack.addArrangedSubview(bubble)
-        stack.addArrangedSubview(sendButton)
-        stack.addArrangedSubview(audioButton)
-
-        addSubview(stack)
-        stack.translatesAutoresizingMaskIntoConstraints = false
-        NSLayoutConstraint.activate([
-            stack.topAnchor.constraint(equalTo: topAnchor),
-            stack.leadingAnchor.constraint(equalTo: leadingAnchor),
-            stack.trailingAnchor.constraint(equalTo: trailingAnchor),
-            stack.bottomAnchor.constraint(equalTo: bottomAnchor),
-        ])
-
-        textView.delegate = self
-    }
-
-    func textViewDidChange(_ textView: UITextView) {
-        textDidChange(textView.text)
-    }
+    stack.axis = .horizontal
+    stack.spacing = 8
+    stack.addArrangedSubview(showActionsButton)
+    stack.addArrangedSubview(hideActionsButton)
+    stack.addArrangedSubview(bubble)
+    stack.addArrangedSubview(sendButton)
+    stack.addArrangedSubview(audioButton)
+
+    addSubview(stack)
+    stack.translatesAutoresizingMaskIntoConstraints = false
+    NSLayoutConstraint.activate([
+      stack.topAnchor.constraint(equalTo: topAnchor),
+      stack.leadingAnchor.constraint(equalTo: leadingAnchor),
+      stack.trailingAnchor.constraint(equalTo: trailingAnchor),
+      stack.bottomAnchor.constraint(equalTo: bottomAnchor),
+    ])
+
+    textView.delegate = self
+  }
+
+  func textViewDidChange(_ textView: UITextView) {
+    textDidChange(textView.text)
+  }
 }
diff --git a/Sources/ChatInputFeature/Voxophone.swift b/Sources/ChatInputFeature/Voxophone.swift
new file mode 100644
index 0000000000000000000000000000000000000000..61141ffd36ff068e3eb0a8385dd38d76699c9aa1
--- /dev/null
+++ b/Sources/ChatInputFeature/Voxophone.swift
@@ -0,0 +1,227 @@
+import Shared
+import Combine
+import AVFoundation
+
+public final class Voxophone: NSObject, AVAudioRecorderDelegate, AVAudioPlayerDelegate {
+  public enum State: Equatable {
+    case empty(isLoudspeaker: Bool)
+    case idle(URL, duration: TimeInterval, isLoudspeaker: Bool)
+    case recording(URL, time: TimeInterval, isLoudspeaker: Bool)
+    case playing(URL, duration: TimeInterval, time: TimeInterval, isLoudspeaker: Bool)
+  }
+
+  public override init() {
+    super.init()
+  }
+
+  deinit {
+    destroyPlayer()
+    destroyRecorder()
+    stopTimer()
+  }
+
+  @Published public private(set) var state: State = .empty(isLoudspeaker: false)
+
+  private let session: AVAudioSession = .sharedInstance()
+  private var recorder: AVAudioRecorder?
+  private var player: AVAudioPlayer?
+  private var timer: Timer?
+
+  public func reset() {
+    destroyPlayer()
+    destroyRecorder()
+    state = .empty(isLoudspeaker: false)
+  }
+
+  public func toggleLoudspeaker() {
+    state.isLoudspeaker.toggle()
+    setupSessionCategory()
+  }
+
+  public func load(_ url: URL) {
+    destroyPlayer()
+    destroyRecorder()
+    let player = setupPlayer(url: url)
+    state = .idle(url, duration: player.duration, isLoudspeaker: state.isLoudspeaker)
+  }
+
+  public func play() {
+    guard let player = player, let url = player.url else { return }
+    destroyRecorder()
+    state = .playing(url, duration: player.duration, time: player.currentTime, isLoudspeaker: state.isLoudspeaker)
+    startPlayback()
+  }
+
+  public func record() {
+    let url = URL(fileURLWithPath: FileManager.xxPath + "/recording_\(Date.asTimestamp).m4a")
+
+    destroyPlayer()
+    destroyRecorder()
+    let recorder = setupRecorder(url: url)
+    state = .recording(url, time: recorder.currentTime, isLoudspeaker: state.isLoudspeaker)
+    startRecording()
+  }
+
+  public func stop() {
+    switch state {
+    case .empty, .idle:
+      return
+
+    case .recording:
+      finishRecording()
+
+    case .playing(let url, let duration, _, let isLoudspeaker):
+      stopPlayback()
+      state = .idle(url, duration: duration, isLoudspeaker: isLoudspeaker)
+    }
+  }
+
+  private func setupPlayer(url: URL) -> AVAudioPlayer {
+    let player = try! AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.m4a.rawValue)
+    self.player = player
+    return player
+  }
+
+  private func setupSessionCategory() {
+    switch state {
+    case .playing(_, _, _, let isLoud):
+      if isLoud, session.category != .playback {
+        try! session.setCategory(.playback, options: .duckOthers)
+      }
+
+      if !isLoud, session.category != .playAndRecord {
+        try! session.setCategory(.playAndRecord, options: .duckOthers)
+      }
+    case .recording(_, _, _):
+      if session.category != .playAndRecord {
+        try! session.setCategory(.playAndRecord, options: .duckOthers)
+      }
+    default:
+      break
+    }
+  }
+
+  private func startPlayback() {
+    guard let player = player else { return }
+    try! session.setActive(true)
+    setupSessionCategory()
+    player.delegate = self
+    player.prepareToPlay()
+    player.play()
+    startTimer()
+  }
+
+  private func stopPlayback() {
+    guard let player = player else { return }
+    player.stop()
+  }
+
+  private func destroyPlayer() {
+    player?.delegate = nil
+    player?.stop()
+    player = nil
+  }
+
+  // MARK: - Recorder
+
+  private func setupRecorder(url: URL) -> AVAudioRecorder {
+    let recorder = try! AVAudioRecorder(url: url, settings: [
+      AVFormatIDKey: kAudioFormatMPEG4AAC,
+      AVSampleRateKey: 12000,
+      AVNumberOfChannelsKey: 1
+    ])
+    self.recorder = recorder
+    return recorder
+  }
+
+  private func startRecording() {
+    guard let recorder = recorder else { return }
+    try! session.setActive(true)
+    setupSessionCategory()
+    recorder.delegate = self
+    recorder.record()
+    startTimer()
+  }
+
+  private func finishRecording() {
+    guard let recorder = recorder else { return }
+    recorder.stop()
+  }
+
+  private func destroyRecorder() {
+    recorder?.delegate = nil
+    recorder?.stop()
+    recorder = nil
+  }
+
+  // MARK: - Timer
+
+  private func startTimer() {
+    stopTimer()
+    timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { _ in
+      self.timerTick()
+    }
+  }
+
+  private func timerTick() {
+    switch state {
+    case .empty, .idle:
+      stopTimer()
+
+    case .recording(_, _, let isLoud):
+      guard let recorder = recorder else { return }
+      state = .recording(recorder.url, time: recorder.currentTime, isLoudspeaker: isLoud)
+
+    case .playing(_, _, _, let isLoud):
+      guard let player = player, let url = player.url else { return }
+      state = .playing(url, duration: player.duration, time: player.currentTime, isLoudspeaker: isLoud)
+    }
+  }
+
+  private func stopTimer() {
+    timer?.invalidate()
+    timer = nil
+  }
+
+  // MARK: - AVAudioRecorderDelegate
+
+  public func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
+    guard flag else {
+      state = .empty(isLoudspeaker: state.isLoudspeaker)
+      return
+    }
+    load(recorder.url)
+  }
+
+  // MARK: - AVAudioPlayerDelegate
+
+  public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
+    guard flag, let url = player.url else {
+      state = .empty(isLoudspeaker: state.isLoudspeaker)
+      return
+    }
+    load(url)
+  }
+}
+
+public extension Voxophone.State {
+  var isLoudspeaker: Bool {
+    get {
+      switch self {
+      case .playing(_, _, _, let isLoud), .idle(_, _, let isLoud), .empty(let isLoud), .recording(_, _, let isLoud):
+        return isLoud
+      }
+    } set {
+      switch self {
+      case .empty(_):
+        self = .empty(isLoudspeaker: newValue)
+      case let .idle(url, duration, _):
+        self = .idle(url, duration: duration, isLoudspeaker: newValue)
+      case let .playing(url, duration, time, _):
+        self = .playing(url, duration: duration, time: time, isLoudspeaker: newValue)
+      case let .recording(url, time, _):
+        self = .recording(url, time: time, isLoudspeaker: newValue)
+      }
+    }
+  }
+}
diff --git a/Sources/ChatListFeature/Controller/ChatListController.swift b/Sources/ChatListFeature/Controller/ChatListController.swift
index dfa484b08116958931d12a93f98a54f53a7db096..c141c1ae99af73758f9acb538e98b4e4d7ae94f2 100644
--- a/Sources/ChatListFeature/Controller/ChatListController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListController.swift
@@ -2,7 +2,6 @@ import UIKit
 import Shared
 import Combine
 import XXModels
-import MenuFeature
 import Navigation
 import DI
 
@@ -70,9 +69,9 @@ public final class ChatListController: UIViewController {
       .sink { [unowned self] in
         switch $0 {
         case .didTapSearch:
-          navigator.perform(PresentSearch(replacing: false))
+          navigator.perform(PresentSearch(searching: nil, replacing: false, on: navigationController!))
         case .didTapNewGroup:
-          navigator.perform(PresentNewGroup())
+          navigator.perform(PresentNewGroup(on: navigationController!))
         }
       }.store(in: &cancellables)
     
@@ -87,7 +86,7 @@ public final class ChatListController: UIViewController {
       .actionPublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentMenu(currentItem: .chats))
+        navigator.perform(PresentMenu(currentItem: .chats, from: self))
       }.store(in: &cancellables)
   }
   
@@ -146,7 +145,7 @@ public final class ChatListController: UIViewController {
       .rightPublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentScan())
+        navigator.perform(PresentScan(on: navigationController!))
       }.store(in: &cancellables)
     
     screenView
@@ -211,7 +210,11 @@ public final class ChatListController: UIViewController {
       .searchButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
-        navigator.perform(PresentSearch(replacing: false))
+        navigator.perform(PresentSearch(
+          searching: nil,
+          replacing: false,
+          on: navigationController!
+        ))
       }.store(in: &cancellables)
     
     screenView
@@ -221,7 +224,7 @@ public final class ChatListController: UIViewController {
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentContactList())
+        navigator.perform(PresentContactList(on: navigationController!))
       }.store(in: &cancellables)
     
     viewModel
@@ -240,7 +243,7 @@ extension ChatListController: UICollectionViewDelegate {
     didSelectItemAt indexPath: IndexPath
   ) {
     if let contact = collectionDataSource.itemIdentifier(for: indexPath) {
-      navigator.perform(PresentChat(contact: contact))
+      navigator.perform(PresentChat(contact: contact, on: navigationController!))
     }
   }
 }
diff --git a/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift b/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift
index d2949c9c73eb457990b5caf69563e809585d8626..b9a877cbf6f4942ba12d547a1fdef94aa8cf502d 100644
--- a/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListSearchTableController.swift
@@ -108,18 +108,18 @@ extension ChatSearchTableController {
         switch chatInfo {
         case .group(let group):
           if let groupInfo = viewModel.groupInfo(from: group) {
-            navigator.perform(PresentGroupChat(model: groupInfo))
+            navigator.perform(PresentGroupChat(groupInfo: groupInfo, on: navigationController!))
           }
         case .groupChat(let info):
           if let groupInfo = viewModel.groupInfo(from: info.group) {
-            navigator.perform(PresentGroupChat(model: groupInfo))
+            navigator.perform(PresentGroupChat(groupInfo: groupInfo, on: navigationController!))
           }
         case .contactChat(let info):
           guard info.contact.authStatus == .friend else { return }
-          navigator.perform(PresentChat(contact: info.contact))
+          navigator.perform(PresentChat(contact: info.contact, on: navigationController!))
         }
       case .connection(let contact):
-        navigator.perform(PresentContact(contact: contact))
+        navigator.perform(PresentContact(contact: contact, on: navigationController!))
       }
     }
   }
diff --git a/Sources/ChatListFeature/Controller/ChatListTableController.swift b/Sources/ChatListFeature/Controller/ChatListTableController.swift
index 7129b97c4318bfb0f9569e9bc7f0b57f36ac0822..8db077fa8c454239b6d1b5553c9c25632ed7e38d 100644
--- a/Sources/ChatListFeature/Controller/ChatListTableController.swift
+++ b/Sources/ChatListFeature/Controller/ChatListTableController.swift
@@ -96,15 +96,21 @@ extension ChatListTableController {
     switch rows[indexPath.row] {
     case .group(let group):
       if let groupInfo = viewModel.groupInfo(from: group) {
-        navigator.perform(PresentGroupChat(model: groupInfo))
+        navigator.perform(PresentGroupChat(
+          groupInfo: groupInfo,
+          on: navigationController!
+        ))
       }
     case .groupChat(let info):
       if let groupInfo = viewModel.groupInfo(from: info.group) {
-        navigator.perform(PresentGroupChat(model: groupInfo))
+        navigator.perform(PresentGroupChat(
+          groupInfo: groupInfo,
+          on: navigationController!
+        ))
       }
     case .contactChat(let info):
       guard info.contact.authStatus == .friend else { return }
-      navigator.perform(PresentChat(contact: info.contact))
+      navigator.perform(PresentChat(contact: info.contact, on: navigationController!))
     }
   }
   
@@ -202,6 +208,6 @@ extension ChatListTableController {
         spacingAfter: 39
       ),
       actionButton
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/ContactFeature/Controllers/ContactController.swift b/Sources/ContactFeature/Controllers/ContactController.swift
index 145318147b35a7d79992bfca2e4e93e9c3643eb1..b1e667cecb38dc02c386fcc875317c961674f786 100644
--- a/Sources/ContactFeature/Controllers/ContactController.swift
+++ b/Sources/ContactFeature/Controllers/ContactController.swift
@@ -50,7 +50,8 @@ public final class ContactController: UIViewController {
     screenView.didTapSend = { [weak self] in
       guard let self else { return }
       self.navigator.perform(PresentChat(
-        contact: self.viewModel.contact
+        contact: self.viewModel.contact,
+        on: self.navigationController!
       ))
     }
     screenView.didTapInfo = { [weak self] in
@@ -83,7 +84,9 @@ public final class ContactController: UIViewController {
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentPhotoLibrary())
+        navigator.perform(
+          PresentPhotoLibrary(from: self)
+        )
       }.store(in: &cancellables)
 
     viewModel
@@ -146,7 +149,7 @@ public final class ContactController: UIViewController {
       .sentRequests
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
-        navigator.perform(PresentRequests())
+        navigator.perform(PresentRequests(on: navigationController!))
       }.store(in: &cancellables)
 
     viewModel
@@ -178,10 +181,10 @@ public final class ContactController: UIViewController {
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
         let nickname = (viewModel.contact.nickname ?? viewModel.contact.username) ?? ""
-        navigator.perform(PresentNickname(prefilled: nickname) { [weak self] in
+        navigator.perform(PresentNickname(prefilled: nickname, completion: { [weak self] in
           guard let self else { return }
           self.viewModel.didTapRequest(with: $0)
-        })
+        }, from: self))
       }.store(in: &cancellables)
   }
 
@@ -191,10 +194,10 @@ public final class ContactController: UIViewController {
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
         let nickname = (viewModel.contact.nickname ?? viewModel.contact.username) ?? ""
-        navigator.perform(PresentNickname(prefilled: nickname) { [weak self] in
+        navigator.perform(PresentNickname(prefilled: nickname, completion: { [weak self] in
           guard let self else { return }
           self.viewModel.didTapAccept($0)
-        })
+        }, from: self))
       }.store(in: &cancellables)
 
     screenView
@@ -263,7 +266,7 @@ public final class ContactController: UIViewController {
             navigator.perform(PresentNickname(prefilled: nickname, completion: { [weak self] in
               guard let self else { return }
               self.viewModel.didUpdateNickname($0)
-            }))
+            }, from: self))
           }.store(in: &cancellables)
 
         let usernameAttribute = AttributeComponent()
@@ -352,7 +355,7 @@ public final class ContactController: UIViewController {
         spacing: 20.0,
         views: [clearButton, cancelButton]
       )
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
 
@@ -422,7 +425,7 @@ extension ContactController {
         actionButton,
         FlexibleSpace()
       ])
-    ]))
+    ], isDismissable: true, from: self))
   }
 
   private func presentDeleteInfo() {
@@ -456,6 +459,6 @@ extension ContactController {
         customAttributes: [.font:  Fonts.Mulish.bold.font(size: 16.0)]
       ),
       actionButton
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/ContactListFeature/Controllers/ContactListController.swift b/Sources/ContactListFeature/Controllers/ContactListController.swift
index 2c45e7d914ac37c39257f6cf9c606e92b91f046b..c5a2dbb059953c0a8ed6c5b680ec98a6851261ee 100644
--- a/Sources/ContactListFeature/Controllers/ContactListController.swift
+++ b/Sources/ContactListFeature/Controllers/ContactListController.swift
@@ -86,7 +86,10 @@ public final class ContactListController: UIViewController {
       .didTap
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentChat(contact: $0))
+        navigator.perform(PresentChat(
+          contact: $0,
+          on: navigationController!
+        ))
       }.store(in: &cancellables)
 
     screenView
@@ -94,7 +97,7 @@ public final class ContactListController: UIViewController {
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentRequests())
+        navigator.perform(PresentRequests(on: navigationController!))
       }.store(in: &cancellables)
 
     screenView
@@ -102,7 +105,7 @@ public final class ContactListController: UIViewController {
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentNewGroup())
+        navigator.perform(PresentNewGroup(on: navigationController!))
       }.store(in: &cancellables)
 
     screenView
@@ -110,7 +113,11 @@ public final class ContactListController: UIViewController {
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentSearch(replacing: false))
+        navigator.perform(PresentSearch(
+          searching: nil,
+          replacing: false,
+          on: navigationController!
+        ))
       }.store(in: &cancellables)
 
     viewModel
@@ -132,14 +139,18 @@ public final class ContactListController: UIViewController {
   }
 
   @objc private func didTapSearch() {
-    navigator.perform(PresentSearch(replacing: false))
+    navigator.perform(PresentSearch(
+      searching: nil,
+      replacing: false,
+      on: navigationController!
+    ))
   }
 
   @objc private func didTapScan() {
-    navigator.perform(PresentScan())
+    navigator.perform(PresentScan(on: navigationController!))
   }
 
   @objc private func didTapMenu() {
-    navigator.perform(PresentMenu(currentItem: .contacts))
+    navigator.perform(PresentMenu(currentItem: .contacts, from: self))
   }
 }
diff --git a/Sources/ContactListFeature/Controllers/CreateGroupController.swift b/Sources/ContactListFeature/Controllers/CreateGroupController.swift
index 4397c8cd53a8f58d94df05348ea2149e1be6cd6e..34539b857c33cec6bbf1ba0a074db9f228493e48 100644
--- a/Sources/ContactListFeature/Controllers/CreateGroupController.swift
+++ b/Sources/ContactListFeature/Controllers/CreateGroupController.swift
@@ -157,7 +157,10 @@ public final class CreateGroupController: UIViewController {
       .info
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentGroupChat(model: $0))
+        navigator.perform(PresentGroupChat(
+          groupInfo: $0,
+          on: navigationController!
+        ))
       }.store(in: &cancellables)
 
     createButton
diff --git a/Sources/Countries/CountryListCell.swift b/Sources/Countries/CountryListCell.swift
deleted file mode 100644
index b3b650e5ae8daae80cc8b026fc3d242bac1b9920..0000000000000000000000000000000000000000
--- a/Sources/Countries/CountryListCell.swift
+++ /dev/null
@@ -1,62 +0,0 @@
-import UIKit
-import Shared
-
-final class CountryListCell: UITableViewCell {
-    let nameLabel = UILabel()
-    let flagLabel = UILabel()
-    let prefixLabel = UILabel()
-    let separatorView = UIView()
-
-    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
-        super.init(style: style, reuseIdentifier: reuseIdentifier)
-
-        selectionStyle = .none
-        backgroundColor = Asset.neutralWhite.color
-
-        nameLabel.textColor = Asset.neutralDark.color
-        prefixLabel.textColor = Asset.neutralWeak.color
-        nameLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
-        prefixLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
-
-        separatorView.backgroundColor = Asset.brandBackground.color
-        prefixLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
-
-        contentView.addSubview(nameLabel)
-        contentView.addSubview(flagLabel)
-        contentView.addSubview(prefixLabel)
-        contentView.addSubview(separatorView)
-
-        flagLabel.snp.makeConstraints {
-            $0.left.top.equalToSuperview().inset(18)
-            $0.bottom.equalToSuperview().offset(-16)
-        }
-
-        nameLabel.snp.makeConstraints {
-            $0.left.equalToSuperview().offset(55)
-            $0.centerY.equalToSuperview()
-            $0.right.lessThanOrEqualTo(prefixLabel.snp.left).offset(-10)
-        }
-
-        prefixLabel.snp.makeConstraints {
-            $0.right.equalToSuperview().offset(-18)
-            $0.centerY.equalToSuperview()
-        }
-
-        separatorView.snp.makeConstraints {
-            $0.bottom.equalToSuperview()
-            $0.left.equalToSuperview().offset(20)
-            $0.right.equalToSuperview().offset(-20)
-            $0.height.equalTo(1)
-        }
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    override func prepareForReuse() {
-        super.prepareForReuse()
-
-        nameLabel.text = nil
-        flagLabel.text = nil
-        prefixLabel.text = nil
-    }
-}
diff --git a/Sources/Countries/CountryListView.swift b/Sources/Countries/CountryListView.swift
deleted file mode 100644
index cf743823ace4b8b1d45fefeb1dedc0360374799a..0000000000000000000000000000000000000000
--- a/Sources/Countries/CountryListView.swift
+++ /dev/null
@@ -1,42 +0,0 @@
-import UIKit
-import Shared
-
-final class CountryListView: UIView {
-    let tableView = UITableView()
-    let searchComponent = SearchComponent()
-
-    init() {
-        super.init(frame: .zero)
-        setup()
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    private func setup() {
-        tableView.separatorStyle = .none
-        tableView.backgroundColor = .clear
-        backgroundColor = Asset.neutralWhite.color
-
-        searchComponent.set(
-            imageAtRight: UIImage.color(.clear),
-            inputAccessibility: Localized.Accessibility.Countries.Search.field,
-            rightAccessibility: Localized.Accessibility.Countries.Search.right
-        )
-
-        addSubview(tableView)
-        addSubview(searchComponent)
-
-        searchComponent.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(20)
-            make.left.equalToSuperview().offset(20)
-            make.right.equalToSuperview().offset(-20)
-        }
-
-        tableView.snp.makeConstraints { make in
-            make.top.equalTo(searchComponent.snp.bottom).offset(20)
-            make.left.equalToSuperview()
-            make.bottom.equalToSuperview()
-            make.right.equalToSuperview()
-        }
-    }
-}
diff --git a/Sources/Countries/CountryListViewModel.swift b/Sources/Countries/CountryListViewModel.swift
deleted file mode 100644
index e4157a16e1938cc506f0549113d393eb6f5b6202..0000000000000000000000000000000000000000
--- a/Sources/Countries/CountryListViewModel.swift
+++ /dev/null
@@ -1,49 +0,0 @@
-import os
-import UIKit
-import Shared
-import Combine
-import Foundation
-
-private let logger = Logger(subsystem: "logs_xxmessenger", category: "Countries.CountryListViewModel.swift")
-
-final class CountryListViewModel {
-    var countries: AnyPublisher<NSDiffableDataSourceSnapshot<SectionId, Country>, Never> {
-        countriesRelay.eraseToAnyPublisher()
-    }
-
-    private var cancellables = Set<AnyCancellable>()
-    private let searchQueryRelay = CurrentValueSubject<String, Never>("")
-    private let countriesRelay = CurrentValueSubject<NSDiffableDataSourceSnapshot<SectionId, Country>, Never>(.init())
-
-    func fetchCountryList() {
-        logger.log("fetchCountryList()")
-
-        Publishers.CombineLatest(Just(Country.all()), searchQueryRelay)
-            .map { countryList, query -> NSDiffableDataSourceSnapshot<SectionId, Country> in
-                var snapshot = NSDiffableDataSourceSnapshot<SectionId, Country>()
-                let section = SectionId()
-                snapshot.appendSections([section])
-
-                guard !query.isEmpty else {
-                    logger.log("query.isEmpty, returning all countries")
-                    snapshot.appendItems(countryList, toSection: section)
-                    return snapshot
-                }
-
-                let filtered = countryList.filter {
-                    $0.name.lowercased().contains(query.lowercased()) ||
-                    $0.prefix.lowercased().contains(query.lowercased())
-                }
-
-                snapshot.appendItems(filtered, toSection: section)
-                return snapshot
-
-            }.sink { [weak countriesRelay] in countriesRelay?.send($0) }
-            .store(in: &cancellables)
-    }
-
-    func didSearchFor(_ string: String) {
-        logger.log("didSearchFor \(string, privacy: .public)()")
-        searchQueryRelay.send(string)
-    }
-}
diff --git a/Sources/CountryListFeature/CountryListCell.swift b/Sources/CountryListFeature/CountryListCell.swift
new file mode 100644
index 0000000000000000000000000000000000000000..61dc02fcab863e5a965f6c5e589e880d3617ba12
--- /dev/null
+++ b/Sources/CountryListFeature/CountryListCell.swift
@@ -0,0 +1,63 @@
+import UIKit
+import Shared
+import AppResources
+
+final class CountryListCell: UITableViewCell {
+  let nameLabel = UILabel()
+  let flagLabel = UILabel()
+  let prefixLabel = UILabel()
+  let separatorView = UIView()
+
+  override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+    super.init(style: style, reuseIdentifier: reuseIdentifier)
+
+    selectionStyle = .none
+    backgroundColor = Asset.neutralWhite.color
+
+    nameLabel.textColor = Asset.neutralDark.color
+    prefixLabel.textColor = Asset.neutralWeak.color
+    nameLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    prefixLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
+
+    separatorView.backgroundColor = Asset.brandBackground.color
+    prefixLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
+
+    contentView.addSubview(nameLabel)
+    contentView.addSubview(flagLabel)
+    contentView.addSubview(prefixLabel)
+    contentView.addSubview(separatorView)
+
+    flagLabel.snp.makeConstraints {
+      $0.left.top.equalToSuperview().inset(18)
+      $0.bottom.equalToSuperview().offset(-16)
+    }
+
+    nameLabel.snp.makeConstraints {
+      $0.left.equalToSuperview().offset(55)
+      $0.centerY.equalToSuperview()
+      $0.right.lessThanOrEqualTo(prefixLabel.snp.left).offset(-10)
+    }
+
+    prefixLabel.snp.makeConstraints {
+      $0.right.equalToSuperview().offset(-18)
+      $0.centerY.equalToSuperview()
+    }
+
+    separatorView.snp.makeConstraints {
+      $0.bottom.equalToSuperview()
+      $0.left.equalToSuperview().offset(20)
+      $0.right.equalToSuperview().offset(-20)
+      $0.height.equalTo(1)
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  override func prepareForReuse() {
+    super.prepareForReuse()
+
+    nameLabel.text = nil
+    flagLabel.text = nil
+    prefixLabel.text = nil
+  }
+}
diff --git a/Sources/Countries/CountryListController.swift b/Sources/CountryListFeature/CountryListController.swift
similarity index 82%
rename from Sources/Countries/CountryListController.swift
rename to Sources/CountryListFeature/CountryListController.swift
index 5a6181315eb8446afbac9a82beee507244cd9d9a..f7c11b93853371b1ccf191b32abfe367ca59b237 100644
--- a/Sources/Countries/CountryListController.swift
+++ b/Sources/CountryListFeature/CountryListController.swift
@@ -1,12 +1,12 @@
 import UIKit
 import Shared
 import Combine
-import Navigation
-import DI
+import AppResources
+import StatusBarFeature
+import ComposableArchitecture
 
 public final class CountryListController: UIViewController, UITableViewDelegate {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
 
   private lazy var screenView = CountryListView()
 
@@ -24,12 +24,7 @@ public final class CountryListController: UIViewController, UITableViewDelegate
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    navigationItem.backButtonTitle = ""
-    barStylist.styleSubject.send(.darkContent)
-    navigationController?.navigationBar.customize(
-      backgroundColor: Asset.neutralWhite.color,
-      shadowColor: Asset.neutralDisabled.color
-    )
+    statusBar.update(.darkContent)
   }
 
   public override func loadView() {
@@ -75,7 +70,7 @@ public final class CountryListController: UIViewController, UITableViewDelegate
   public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
     if let country = dataSource.itemIdentifier(for: indexPath) {
       completion(country)
-      navigator.perform(DismissModal(from: self))
+      dismiss(animated: true)
     }
   }
 }
diff --git a/Sources/CountryListFeature/CountryListView.swift b/Sources/CountryListFeature/CountryListView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..9d5f65f297a66aa47c3db75cc97782845600a3f4
--- /dev/null
+++ b/Sources/CountryListFeature/CountryListView.swift
@@ -0,0 +1,39 @@
+import UIKit
+import Shared
+import AppResources
+
+final class CountryListView: UIView {
+  let tableView = UITableView()
+  let searchComponent = SearchComponent()
+
+  init() {
+    super.init(frame: .zero)
+
+    tableView.separatorStyle = .none
+    tableView.backgroundColor = .clear
+    backgroundColor = Asset.neutralWhite.color
+
+    searchComponent.set(
+      imageAtRight: UIImage.color(.clear),
+      inputAccessibility: Localized.Accessibility.Countries.Search.field,
+      rightAccessibility: Localized.Accessibility.Countries.Search.right
+    )
+
+    addSubview(tableView)
+    addSubview(searchComponent)
+
+    searchComponent.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(20)
+      $0.left.equalToSuperview().offset(20)
+      $0.right.equalToSuperview().offset(-20)
+    }
+    tableView.snp.makeConstraints {
+      $0.top.equalTo(searchComponent.snp.bottom).offset(20)
+      $0.left.equalToSuperview()
+      $0.bottom.equalToSuperview()
+      $0.right.equalToSuperview()
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
+}
diff --git a/Sources/CountryListFeature/CountryListViewModel.swift b/Sources/CountryListFeature/CountryListViewModel.swift
new file mode 100644
index 0000000000000000000000000000000000000000..4144345c6118e05b0f2743abe8b4a92c68d53527
--- /dev/null
+++ b/Sources/CountryListFeature/CountryListViewModel.swift
@@ -0,0 +1,43 @@
+import UIKit
+import Shared
+import Combine
+
+final class CountryListViewModel {
+  var countries: AnyPublisher<NSDiffableDataSourceSnapshot<SectionId, Country>, Never> {
+    countriesRelay.eraseToAnyPublisher()
+  }
+
+  private var cancellables = Set<AnyCancellable>()
+  private let searchQueryRelay = CurrentValueSubject<String, Never>("")
+  private let countriesRelay = CurrentValueSubject<NSDiffableDataSourceSnapshot<SectionId, Country>, Never>(.init())
+
+  func fetchCountryList() {
+    Publishers
+      .CombineLatest(Just(Country.all()), searchQueryRelay)
+      .map { countryList, query -> NSDiffableDataSourceSnapshot<SectionId, Country> in
+        var snapshot = NSDiffableDataSourceSnapshot<SectionId, Country>()
+        let section = SectionId()
+        snapshot.appendSections([section])
+
+        guard !query.isEmpty else {
+          snapshot.appendItems(countryList, toSection: section)
+          return snapshot
+        }
+
+        let filtered = countryList.filter {
+          $0.name.lowercased().contains(query.lowercased()) ||
+          $0.prefix.lowercased().contains(query.lowercased())
+        }
+
+        snapshot.appendItems(filtered, toSection: section)
+        return snapshot
+
+      }.sink { [weak countriesRelay] in
+        countriesRelay?.send($0)
+      }.store(in: &cancellables)
+  }
+
+  func didSearchFor(_ string: String) {
+    searchQueryRelay.send(string)
+  }
+}
diff --git a/Sources/CrashReporting/CrashReporter.swift b/Sources/CrashReporting/CrashReporter.swift
index f249d741c7baa42218d77487a26e717866ea2f9a..e83c1c54b0f765442b9f31c5c779c86096a92db7 100644
--- a/Sources/CrashReporting/CrashReporter.swift
+++ b/Sources/CrashReporting/CrashReporter.swift
@@ -1,25 +1,25 @@
 import Foundation
 
 public struct CrashReporter {
-    public var configure: () -> Void
-    public var sendError: (NSError) -> Void
-    public var setEnabled: (Bool) -> Void
+  public var configure: () -> Void
+  public var sendError: (NSError) -> Void
+  public var setEnabled: (Bool) -> Void
 
-    public init(
-        configure: @escaping () -> Void,
-        sendError: @escaping (NSError) -> Void,
-        setEnabled: @escaping (Bool) -> Void
-    ) {
-        self.configure = configure
-        self.sendError = sendError
-        self.setEnabled = setEnabled
-    }
+  public init(
+    configure: @escaping () -> Void,
+    sendError: @escaping (NSError) -> Void,
+    setEnabled: @escaping (Bool) -> Void
+  ) {
+    self.configure = configure
+    self.sendError = sendError
+    self.setEnabled = setEnabled
+  }
 }
 
 public extension CrashReporter {
-    static let noop = Self(
-        configure: {},
-        sendError: { _ in },
-        setEnabled: { _ in }
-    )
+  static let noop = Self(
+    configure: {},
+    sendError: { _ in },
+    setEnabled: { _ in }
+  )
 }
diff --git a/Sources/CrashService/CrashService.swift b/Sources/CrashService/CrashService.swift
index 4815ed483b3177262b90089ecc2af62973208a5d..4226369deeb3db598fee81058dbd139ff0dc1c2b 100644
--- a/Sources/CrashService/CrashService.swift
+++ b/Sources/CrashService/CrashService.swift
@@ -3,9 +3,9 @@ import CrashReporting
 import FirebaseCrashlytics
 
 public extension CrashReporter {
-    static let live = Self(
-        configure: { FirebaseApp.configure() },
-        sendError: { Crashlytics.crashlytics().record(error: $0) },
-        setEnabled: { Crashlytics.crashlytics().setCrashlyticsCollectionEnabled($0) }
-    )
+  static let live = Self(
+    configure: { FirebaseApp.configure() },
+    sendError: { Crashlytics.crashlytics().record(error: $0) },
+    setEnabled: { Crashlytics.crashlytics().setCrashlyticsCollectionEnabled($0) }
+  )
 }
diff --git a/Sources/Defaults/KeyObject.swift b/Sources/Defaults/KeyObject.swift
index fc350c6090a25ec3eda750b1c3db128b1e27fb86..1072e3c1cca9e9e195e99f892f489d52b4d6150f 100644
--- a/Sources/Defaults/KeyObject.swift
+++ b/Sources/Defaults/KeyObject.swift
@@ -1,109 +1,90 @@
-import Foundation
 import DI
+import Foundation
 
 public enum Key: String {
-    // MARK: Profile
-
-    case email
-    case phone
-    case avatar
-    case username
-
-    case sharingEmail
-    case sharingPhone
-
-    // MARK: Notifications
-
-    case requestCounter
-    case pushNotifications
-    case inappnotifications
-
-    // MARK: General
-
-    case acceptedTerms
-
-    // MARK: Requests
-
-    case isShowingHiddenRequests
-
-    // MARK: Backup
-
-    case backupSettings
-
-    // MARK: Settings
-
-    case biometrics
-    case hideAppList
-    case recordingLogs
-    case crashReporting
-    case icognitoKeyboard
-
-    case dummyTrafficOn
-    case askedDummyTrafficOnce
+  case email
+  case phone
+  case avatar
+  case username
+  case sharingEmail
+  case sharingPhone
+  case requestCounter
+  case pushNotifications
+  case inappnotifications
+  case acceptedTerms
+  case isShowingHiddenRequests
+  case backupSettings
+  case biometrics
+  case hideAppList
+  case recordingLogs
+  case crashReporting
+  case icognitoKeyboard
+  case dummyTrafficOn
+  case askedDummyTrafficOnce
 }
 
 public struct KeyObjectStore {
-    var objectForKey: (String) -> Any?
-    var setObjectForKey: (Any?, String) -> Void
-    var removeObjectForKey: (String) -> Void
-
-    public init(
-        objectForKey: @escaping (String) -> Any?,
-        setObjectForKey: @escaping (Any?, String) -> Void,
-        removeObjectForKey: @escaping (String) -> Void
-    ) {
-        self.objectForKey = objectForKey
-        self.setObjectForKey = setObjectForKey
-        self.removeObjectForKey = removeObjectForKey
-    }
+  var objectForKey: (String) -> Any?
+  var setObjectForKey: (Any?, String) -> Void
+  var removeObjectForKey: (String) -> Void
+
+  public init(
+    objectForKey: @escaping (String) -> Any?,
+    setObjectForKey: @escaping (Any?, String) -> Void,
+    removeObjectForKey: @escaping (String) -> Void
+  ) {
+    self.objectForKey = objectForKey
+    self.setObjectForKey = setObjectForKey
+    self.removeObjectForKey = removeObjectForKey
+  }
 }
 
 public extension KeyObjectStore {
-    static func mock(dictionary: NSMutableDictionary) -> Self {
-        Self(objectForKey: { dictionary[$0] },
-             setObjectForKey: { dictionary[$1] = $0 },
-             removeObjectForKey: { dictionary[$0] = nil })
-    }
-
-    static let userDefaults = Self(
-        objectForKey: UserDefaults.standard.object(forKey:),
-        setObjectForKey: UserDefaults.standard.set(_:forKey:),
-        removeObjectForKey: UserDefaults.standard.removeObject(forKey:)
-    )
+  static func mock(dictionary: NSMutableDictionary) -> Self {
+    Self(objectForKey: { dictionary[$0] },
+         setObjectForKey: { dictionary[$1] = $0 },
+         removeObjectForKey: { dictionary[$0] = nil })
+  }
+
+  static let userDefaults = Self(
+    objectForKey: UserDefaults.standard.object(forKey:),
+    setObjectForKey: UserDefaults.standard.set(_:forKey:),
+    removeObjectForKey: UserDefaults.standard.removeObject(forKey:)
+  )
 }
 
 @propertyWrapper
 public struct KeyObject<T> {
-    let key: String
-    let defaultValue: T
+  let key: String
+  let defaultValue: T
 
-    @Dependency var store: KeyObjectStore
+  @Dependency var store: KeyObjectStore
 
-    public init(_ key: Key, defaultValue: T) {
-        self.key = key.rawValue
-        self.defaultValue = defaultValue
-    }
+  public init(_ key: Key, defaultValue: T) {
+    self.key = key.rawValue
+    self.defaultValue = defaultValue
+  }
 
-    public var wrappedValue: T {
-        get {
-            store.objectForKey(key) as? T ?? defaultValue
-        }
-        set {
-            if let value = newValue as? OptionalProtocol, value.isNil() {
-                store.removeObjectForKey(key)
-            } else {
-                store.setObjectForKey(newValue, key)
-            }
-        }
+  public var wrappedValue: T {
+    get {
+      store.objectForKey(key) as? T ?? defaultValue
     }
+    set {
+      if let value = newValue as? OptionalProtocol, value.isNil() {
+        store.removeObjectForKey(key)
+      } else {
+        store.setObjectForKey(newValue, key)
+      }
+    }
+  }
 }
 
 fileprivate protocol OptionalProtocol {
-    func isNil() -> Bool
+  func isNil() -> Bool
 }
 
 extension Optional : OptionalProtocol {
-    func isNil() -> Bool {
-        return self == nil
-    }
+  func isNil() -> Bool {
+    return self == nil
+  }
 }
diff --git a/Sources/DrawerFeature/DrawerView.swift b/Sources/DrawerFeature/DrawerView.swift
index 4c157e0df68dd9b5eade8cbb1569d7018499f354..95b711c3280ccdd40502d6cc4421eb98f058c672 100644
--- a/Sources/DrawerFeature/DrawerView.swift
+++ b/Sources/DrawerFeature/DrawerView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class DrawerView: UIView {
   let stackView = UIStackView()
diff --git a/Sources/DrawerFeature/Items/DrawerLinkText.swift b/Sources/DrawerFeature/Items/DrawerLinkText.swift
index 428acbaa89e295fb8f95f4bc3a131f0955e571fc..313e98d08ae67f511bc0d6c9ae34d527a2a12f8a 100644
--- a/Sources/DrawerFeature/Items/DrawerLinkText.swift
+++ b/Sources/DrawerFeature/Items/DrawerLinkText.swift
@@ -1,63 +1,64 @@
 import UIKit
 import Shared
+import AppResources
 
 public final class DrawerLinkText: NSObject, DrawerItem {
-    let text: String
-    let urlString: String
-
-    public var spacingAfter: CGFloat? = 0
-
-    public init(
-        text: String,
-        urlString: String,
-        spacingAfter: CGFloat = 10
-    ) {
-        self.text = text
-        self.urlString = urlString
-        self.spacingAfter = spacingAfter
-    }
+  let text: String
+  let urlString: String
+
+  public var spacingAfter: CGFloat? = 0
+
+  public init(
+    text: String,
+    urlString: String,
+    spacingAfter: CGFloat = 10
+  ) {
+    self.text = text
+    self.urlString = urlString
+    self.spacingAfter = spacingAfter
+  }
+
+  public func makeView() -> UIView {
+    let textView = UnselectableTextView()
+    textView.delegate = self
+    textView.isEditable = false
+    textView.isSelectable = true
+    textView.isScrollEnabled = false
+    textView.backgroundColor = .clear
+    textView.isUserInteractionEnabled = true
+
+    let paragraphStyle = NSMutableParagraphStyle()
+    paragraphStyle.alignment = .left
+    paragraphStyle.lineHeightMultiple = 1.1
 
-    public func makeView() -> UIView {
-        let textView = UnselectableTextView()
-        textView.delegate = self
-        textView.isEditable = false
-        textView.isSelectable = true
-        textView.isScrollEnabled = false
-        textView.backgroundColor = .clear
-        textView.isUserInteractionEnabled = true
-
-        let paragraphStyle = NSMutableParagraphStyle()
-        paragraphStyle.alignment = .left
-        paragraphStyle.lineHeightMultiple = 1.1
-
-        let attrString = NSMutableAttributedString(string: text)
-        attrString.addAttributes([
-            .paragraphStyle: paragraphStyle,
-            .foregroundColor: Asset.neutralDark.color,
-            .font: Fonts.Mulish.regular.font(size: 16.0) as Any
-        ])
-
-        if let url = URL(string: urlString) {
-            attrString.addAttribute(name: .link, value: url, betweenCharacters: "#")
-
-            textView.linkTextAttributes = [
-                .paragraphStyle: paragraphStyle,
-                .foregroundColor: Asset.brandPrimary.color,
-                .font: Fonts.Mulish.regular.font(size: 16.0) as Any
-            ]
-        }
-
-        textView.attributedText = attrString
-
-        return textView
+    let attrString = NSMutableAttributedString(string: text)
+    attrString.addAttributes([
+      .paragraphStyle: paragraphStyle,
+      .foregroundColor: Asset.neutralDark.color,
+      .font: Fonts.Mulish.regular.font(size: 16.0) as Any
+    ])
+
+    if let url = URL(string: urlString) {
+      attrString.addAttribute(name: .link, value: url, betweenCharacters: "#")
+
+      textView.linkTextAttributes = [
+        .paragraphStyle: paragraphStyle,
+        .foregroundColor: Asset.brandPrimary.color,
+        .font: Fonts.Mulish.regular.font(size: 16.0) as Any
+      ]
     }
 
-    public func textView(
-        _: UITextView,
-        shouldInteractWith: URL,
-        in: NSRange,
-        interaction: UITextItemInteraction
-    ) -> Bool { true }
+    textView.attributedText = attrString
+
+    return textView
+  }
+
+  public func textView(
+    _: UITextView,
+    shouldInteractWith: URL,
+    in: NSRange,
+    interaction: UITextItemInteraction
+  ) -> Bool { true }
 }
 
 extension DrawerLinkText: UITextViewDelegate {}
diff --git a/Sources/DrawerFeature/Items/DrawerLoadingRetry.swift b/Sources/DrawerFeature/Items/DrawerLoadingRetry.swift
index dcf46a4c812ef1698972c1f5337c1963279a7122..552cb10f94f06161c7a6a6eb6f84aef0c1cb88d0 100644
--- a/Sources/DrawerFeature/Items/DrawerLoadingRetry.swift
+++ b/Sources/DrawerFeature/Items/DrawerLoadingRetry.swift
@@ -1,57 +1,58 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 
 public final class DrawerLoadingRetry: DrawerItem {
-    public var retryPublisher: AnyPublisher<Void, Never> {
-        retrySubject.eraseToAnyPublisher()
-    }
-
-    private let view = UIView()
-    private let retryButton = UIButton()
-    private let stackView = UIStackView()
-    private var cancellables = Set<AnyCancellable>()
-    private let activityIndicator = UIActivityIndicatorView()
-    private let retrySubject = PassthroughSubject<Void, Never>()
-
-    public var spacingAfter: CGFloat? = 0
-
-    public init(spacingAfter: CGFloat? = 10) {
-        self.spacingAfter = spacingAfter
-        self.activityIndicator.style = .large
-        self.activityIndicator.hidesWhenStopped = true
-    }
-
-    public func startSpinning() {
-        activityIndicator.startAnimating()
-        retryButton.isHidden = true
-    }
-
-    public func stopSpinning(withRetry retry: Bool) {
-        guard retry else { view.isHidden = true; return }
-
-        retryButton.isHidden = false
-        activityIndicator.stopAnimating()
-        retryButton.setTitle("Retry", for: .normal)
-        retryButton.setTitleColor(.red, for: .normal)
-
-        retryButton.titleLabel?.numberOfLines = 0
-        retryButton.titleLabel?.textAlignment = .center
-        retryButton.titleLabel?.font = Fonts.Mulish.bold.font(size: 16.0)
-    }
-
-    public func makeView() -> UIView {
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(activityIndicator)
-        stackView.addArrangedSubview(retryButton)
-
-        retryButton
-            .publisher(for: .touchUpInside)
-            .sink { [weak retrySubject] in retrySubject?.send() }
-            .store(in: &cancellables)
-
-        view.addSubview(stackView)
-        stackView.snp.makeConstraints { $0.edges.equalToSuperview() }
-        return view
-    }
+  public var retryPublisher: AnyPublisher<Void, Never> {
+    retrySubject.eraseToAnyPublisher()
+  }
+
+  private let view = UIView()
+  private let retryButton = UIButton()
+  private let stackView = UIStackView()
+  private var cancellables = Set<AnyCancellable>()
+  private let activityIndicator = UIActivityIndicatorView()
+  private let retrySubject = PassthroughSubject<Void, Never>()
+
+  public var spacingAfter: CGFloat? = 0
+
+  public init(spacingAfter: CGFloat? = 10) {
+    self.spacingAfter = spacingAfter
+    self.activityIndicator.style = .large
+    self.activityIndicator.hidesWhenStopped = true
+  }
+
+  public func startSpinning() {
+    activityIndicator.startAnimating()
+    retryButton.isHidden = true
+  }
+
+  public func stopSpinning(withRetry retry: Bool) {
+    guard retry else { view.isHidden = true; return }
+
+    retryButton.isHidden = false
+    activityIndicator.stopAnimating()
+    retryButton.setTitle("Retry", for: .normal)
+    retryButton.setTitleColor(.red, for: .normal)
+
+    retryButton.titleLabel?.numberOfLines = 0
+    retryButton.titleLabel?.textAlignment = .center
+    retryButton.titleLabel?.font = Fonts.Mulish.bold.font(size: 16.0)
+  }
+
+  public func makeView() -> UIView {
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(activityIndicator)
+    stackView.addArrangedSubview(retryButton)
+
+    retryButton
+      .publisher(for: .touchUpInside)
+      .sink { [weak retrySubject] in retrySubject?.send() }
+      .store(in: &cancellables)
+
+    view.addSubview(stackView)
+    stackView.snp.makeConstraints { $0.edges.equalToSuperview() }
+    return view
+  }
 }
diff --git a/Sources/DrawerFeature/Items/DrawerRadio.swift b/Sources/DrawerFeature/Items/DrawerRadio.swift
index de3b764fe403ef3f2c6d80c0e1f91d57ac905382..a3251cf81e9f164ebd4ab6a6ae0317dca0f81872 100644
--- a/Sources/DrawerFeature/Items/DrawerRadio.swift
+++ b/Sources/DrawerFeature/Items/DrawerRadio.swift
@@ -1,79 +1,80 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 
 public final class DrawerRadio: DrawerItem {
-    private let title: String
-    private let isSelected: Bool
-    private var cancellables = Set<AnyCancellable>()
-    private let actionSubject = PassthroughSubject<Void, Never>()
+  private let title: String
+  private let isSelected: Bool
+  private var cancellables = Set<AnyCancellable>()
+  private let actionSubject = PassthroughSubject<Void, Never>()
 
-    public var spacingAfter: CGFloat? = 0
-    public var action: AnyPublisher<Void, Never> { actionSubject.eraseToAnyPublisher() }
+  public var spacingAfter: CGFloat? = 0
+  public var action: AnyPublisher<Void, Never> { actionSubject.eraseToAnyPublisher() }
 
-    public init(
-        title: String,
-        isSelected: Bool,
-        spacingAfter: CGFloat = 10
-    ) {
-        self.title = title
-        self.isSelected = isSelected
-        self.spacingAfter = spacingAfter
-    }
+  public init(
+    title: String,
+    isSelected: Bool,
+    spacingAfter: CGFloat = 10
+  ) {
+    self.title = title
+    self.isSelected = isSelected
+    self.spacingAfter = spacingAfter
+  }
 
-    public func makeView() -> UIView {
-        cancellables.removeAll()
+  public func makeView() -> UIView {
+    cancellables.removeAll()
 
-        let radioView = UIView()
-        let titleLabel = UILabel()
-        let radioInnerView = UIView()
+    let radioView = UIView()
+    let titleLabel = UILabel()
+    let radioInnerView = UIView()
 
-        let view = UIControl()
-        view.addSubview(titleLabel)
-        view.addSubview(radioView)
-        radioView.addSubview(radioInnerView)
+    let view = UIControl()
+    view.addSubview(titleLabel)
+    view.addSubview(radioView)
+    radioView.addSubview(radioInnerView)
 
-        titleLabel.text = title
-        titleLabel.textColor = Asset.neutralDark.color
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    titleLabel.text = title
+    titleLabel.textColor = Asset.neutralDark.color
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
 
-        radioView.layer.cornerRadius = 11.0
-        radioInnerView.layer.cornerRadius = 3
-        radioView.isUserInteractionEnabled = false
+    radioView.layer.cornerRadius = 11.0
+    radioInnerView.layer.cornerRadius = 3
+    radioView.isUserInteractionEnabled = false
 
-        if isSelected {
-            radioView.layer.borderWidth = 0.0
-            radioView.backgroundColor = Asset.brandLight.color
-            radioView.layer.borderColor = Asset.brandLight.color.cgColor
-            radioInnerView.backgroundColor = Asset.neutralWhite.color
-        } else {
-            radioView.layer.borderWidth = 1.0
-            radioView.backgroundColor = Asset.neutralSecondary.color
-            radioView.layer.borderColor = Asset.neutralLine.color.cgColor
-            radioInnerView.backgroundColor = .clear
-        }
+    if isSelected {
+      radioView.layer.borderWidth = 0.0
+      radioView.backgroundColor = Asset.brandLight.color
+      radioView.layer.borderColor = Asset.brandLight.color.cgColor
+      radioInnerView.backgroundColor = Asset.neutralWhite.color
+    } else {
+      radioView.layer.borderWidth = 1.0
+      radioView.backgroundColor = Asset.neutralSecondary.color
+      radioView.layer.borderColor = Asset.neutralLine.color.cgColor
+      radioInnerView.backgroundColor = .clear
+    }
 
-        titleLabel.snp.makeConstraints {
-            $0.left.equalToSuperview().offset(42)
-            $0.centerY.equalToSuperview()
-        }
+    titleLabel.snp.makeConstraints {
+      $0.left.equalToSuperview().offset(42)
+      $0.centerY.equalToSuperview()
+    }
 
-        radioView.snp.makeConstraints {
-            $0.right.equalTo(titleLabel.snp.left).offset(-12)
-            $0.width.height.equalTo(20)
-            $0.centerY.equalToSuperview()
-            $0.bottom.equalToSuperview().offset(-5)
-        }
+    radioView.snp.makeConstraints {
+      $0.right.equalTo(titleLabel.snp.left).offset(-12)
+      $0.width.height.equalTo(20)
+      $0.centerY.equalToSuperview()
+      $0.bottom.equalToSuperview().offset(-5)
+    }
 
-        radioInnerView.snp.makeConstraints {
-            $0.width.height.equalTo(6)
-            $0.center.equalToSuperview()
-        }
+    radioInnerView.snp.makeConstraints {
+      $0.width.height.equalTo(6)
+      $0.center.equalToSuperview()
+    }
 
-        view.publisher(for: .touchUpInside)
-            .sink { [weak self] in self?.actionSubject.send() }
-            .store(in: &cancellables)
+    view.publisher(for: .touchUpInside)
+      .sink { [weak self] in self?.actionSubject.send() }
+      .store(in: &cancellables)
 
-        return view
-    }
+    return view
+  }
 }
diff --git a/Sources/DrawerFeature/Items/DrawerSwitch.swift b/Sources/DrawerFeature/Items/DrawerSwitch.swift
index 449261487789f2685bc43b861ce313b8cf8aaa88..5db2555ed0a36ed68efc9042cdc9635030af4d3d 100644
--- a/Sources/DrawerFeature/Items/DrawerSwitch.swift
+++ b/Sources/DrawerFeature/Items/DrawerSwitch.swift
@@ -1,80 +1,81 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 
 public final class DrawerSwitch: DrawerItem {
-    public var isOnPublisher: AnyPublisher<Bool, Never> {
-        isOnSubject.eraseToAnyPublisher()
-    }
+  public var isOnPublisher: AnyPublisher<Bool, Never> {
+    isOnSubject.eraseToAnyPublisher()
+  }
 
-    private let title: String
-    private let content: String
-    private let isEnabled: Bool
-    private let isInitiallyOn: Bool
-    private var cancellables = Set<AnyCancellable>()
-    private let isOnSubject: CurrentValueSubject<Bool, Never>
+  private let title: String
+  private let content: String
+  private let isEnabled: Bool
+  private let isInitiallyOn: Bool
+  private var cancellables = Set<AnyCancellable>()
+  private let isOnSubject: CurrentValueSubject<Bool, Never>
 
-    public var spacingAfter: CGFloat? = 0
+  public var spacingAfter: CGFloat? = 0
 
-    public init(
-        title: String,
-        content: String,
-        isEnabled: Bool = true,
-        spacingAfter: CGFloat = 10,
-        isInitiallyOn: Bool = false
-    ) {
-        self.title = title
-        self.content = content
-        self.isEnabled = isEnabled
-        self.spacingAfter = spacingAfter
-        self.isInitiallyOn = isInitiallyOn
-        self.isOnSubject = .init(isInitiallyOn)
-    }
+  public init(
+    title: String,
+    content: String,
+    isEnabled: Bool = true,
+    spacingAfter: CGFloat = 10,
+    isInitiallyOn: Bool = false
+  ) {
+    self.title = title
+    self.content = content
+    self.isEnabled = isEnabled
+    self.spacingAfter = spacingAfter
+    self.isInitiallyOn = isInitiallyOn
+    self.isOnSubject = .init(isInitiallyOn)
+  }
 
-    public func makeView() -> UIView {
-        let view = UIView()
-        let titleLabel = UILabel()
-        let contentLabel = UILabel()
-        let switcherView = UISwitch()
+  public func makeView() -> UIView {
+    let view = UIView()
+    let titleLabel = UILabel()
+    let contentLabel = UILabel()
+    let switcherView = UISwitch()
 
-        titleLabel.text = title
-        contentLabel.text = content
+    titleLabel.text = title
+    contentLabel.text = content
 
-        switcherView.isOn = isInitiallyOn
-        switcherView.isEnabled = isEnabled
-        switcherView.onTintColor = Asset.brandPrimary.color
+    switcherView.isOn = isInitiallyOn
+    switcherView.isEnabled = isEnabled
+    switcherView.onTintColor = Asset.brandPrimary.color
 
-        titleLabel.textColor = Asset.neutralWeak.color
-        contentLabel.textColor = Asset.neutralActive.color
+    titleLabel.textColor = Asset.neutralWeak.color
+    contentLabel.textColor = Asset.neutralActive.color
 
-        titleLabel.font = Fonts.Mulish.bold.font(size: 12.0)
-        contentLabel.font = Fonts.Mulish.regular.font(size: 16.0)
+    titleLabel.font = Fonts.Mulish.bold.font(size: 12.0)
+    contentLabel.font = Fonts.Mulish.regular.font(size: 16.0)
 
-        view.addSubview(titleLabel)
-        view.addSubview(contentLabel)
-        view.addSubview(switcherView)
+    view.addSubview(titleLabel)
+    view.addSubview(contentLabel)
+    view.addSubview(switcherView)
 
-        titleLabel.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview()
-        }
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+    }
 
-        contentLabel.snp.makeConstraints {
-            $0.top.equalTo(titleLabel.snp.bottom).offset(5)
-            $0.left.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
+    contentLabel.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(5)
+      $0.left.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
 
-        switcherView.snp.makeConstraints {
-            $0.right.equalToSuperview()
-            $0.centerY.equalToSuperview()
-        }
+    switcherView.snp.makeConstraints {
+      $0.right.equalToSuperview()
+      $0.centerY.equalToSuperview()
+    }
 
-        switcherView.publisher(for: .valueChanged)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned self] in isOnSubject.send(switcherView.isOn) }
-            .store(in: &cancellables)
+    switcherView.publisher(for: .valueChanged)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned self] in isOnSubject.send(switcherView.isOn) }
+      .store(in: &cancellables)
 
-        return view
-    }
+    return view
+  }
 }
diff --git a/Sources/DrawerFeature/Items/DrawerTable.swift b/Sources/DrawerFeature/Items/DrawerTable.swift
index 665b660ea6656c3ad1ddb5a786cdbe7e508be61d..78f2b9299ca078c20fdbf426159d732a1af3366e 100644
--- a/Sources/DrawerFeature/Items/DrawerTable.swift
+++ b/Sources/DrawerFeature/Items/DrawerTable.swift
@@ -1,147 +1,148 @@
 import UIKit
 import Shared
 import SnapKit
+import AppResources
 
 enum DrawerTableSection {
-    case main
+  case main
 }
 
 public final class DrawerTable: DrawerItem {
-    private let view = UIView()
-    private let tableView = UITableView()
-    private var heightConstraint: Constraint?
-    private let dataSource: UITableViewDiffableDataSource<DrawerTableSection, DrawerTableCellModel>
-
-    public var spacingAfter: CGFloat? = 0
-
-    public init(spacingAfter: CGFloat? = 10) {
-        self.dataSource = .init(
-            tableView: tableView,
-            cellProvider: { tableView, indexPath, model in
-                let cell: DrawerTableCell = tableView.dequeueReusableCell(forIndexPath: indexPath)
-
-                cell.titleLabel.text = model.title
-                cell.avatarView.setupProfile(
-                    title: model.title,
-                    image: model.image,
-                    size: .medium
-                )
-
-                if model.isCreator {
-                    cell.subtitleLabel.text = "Creator"
-                    cell.subtitleLabel.isHidden = false
-                    cell.subtitleLabel.textColor = Asset.accentSafe.color
-                } else if !model.isConnection {
-                    cell.subtitleLabel.text = "Not a connection"
-                    cell.subtitleLabel.isHidden = false
-                    cell.subtitleLabel.textColor = Asset.neutralSecondaryAlternative.color
-                } else {
-                    cell.subtitleLabel.isHidden = true
-                }
-
-                return cell
-            })
-
-        self.spacingAfter = spacingAfter
-    }
+  private let view = UIView()
+  private let tableView = UITableView()
+  private var heightConstraint: Constraint?
+  private let dataSource: UITableViewDiffableDataSource<DrawerTableSection, DrawerTableCellModel>
+
+  public var spacingAfter: CGFloat? = 0
+
+  public init(spacingAfter: CGFloat? = 10) {
+    self.dataSource = .init(
+      tableView: tableView,
+      cellProvider: { tableView, indexPath, model in
+        let cell: DrawerTableCell = tableView.dequeueReusableCell(forIndexPath: indexPath)
+
+        cell.titleLabel.text = model.title
+        cell.avatarView.setupProfile(
+          title: model.title,
+          image: model.image,
+          size: .medium
+        )
+
+        if model.isCreator {
+          cell.subtitleLabel.text = "Creator"
+          cell.subtitleLabel.isHidden = false
+          cell.subtitleLabel.textColor = Asset.accentSafe.color
+        } else if !model.isConnection {
+          cell.subtitleLabel.text = "Not a connection"
+          cell.subtitleLabel.isHidden = false
+          cell.subtitleLabel.textColor = Asset.neutralSecondaryAlternative.color
+        } else {
+          cell.subtitleLabel.isHidden = true
+        }
 
-    public func makeView() -> UIView {
-        tableView.register(DrawerTableCell.self)
-        tableView.dataSource = dataSource
-        tableView.separatorStyle = .none
-        tableView.backgroundColor = UIColor.white
+        return cell
+      })
 
-        view.addSubview(tableView)
+    self.spacingAfter = spacingAfter
+  }
 
-        tableView.snp.makeConstraints {
-            $0.edges.equalToSuperview()
-            heightConstraint = $0.height.equalTo(1).priority(.low).constraint
-        }
+  public func makeView() -> UIView {
+    tableView.register(DrawerTableCell.self)
+    tableView.dataSource = dataSource
+    tableView.separatorStyle = .none
+    tableView.backgroundColor = UIColor.white
 
-        return view
+    view.addSubview(tableView)
+
+    tableView.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+      heightConstraint = $0.height.equalTo(1).priority(.low).constraint
     }
 
-    public func update(models: [DrawerTableCellModel]) {
-        let cellHeight = 56
-        self.heightConstraint?.update(offset: cellHeight * models.count)
+    return view
+  }
 
-        var snapshot = NSDiffableDataSourceSnapshot<DrawerTableSection, DrawerTableCellModel>()
-        snapshot.appendSections([.main])
-        snapshot.appendItems(models, toSection: .main)
-        dataSource.apply(snapshot, animatingDifferences: false) { [self] in
-            tableView.isScrollEnabled = tableView.contentSize.height > tableView.frame.height
-        }
+  public func update(models: [DrawerTableCellModel]) {
+    let cellHeight = 56
+    self.heightConstraint?.update(offset: cellHeight * models.count)
+
+    var snapshot = NSDiffableDataSourceSnapshot<DrawerTableSection, DrawerTableCellModel>()
+    snapshot.appendSections([.main])
+    snapshot.appendItems(models, toSection: .main)
+    dataSource.apply(snapshot, animatingDifferences: false) { [self] in
+      tableView.isScrollEnabled = tableView.contentSize.height > tableView.frame.height
     }
+  }
 }
 
 public struct DrawerTableCellModel: Hashable {
-    let id: Data
-    let title: String
-    let image: Data?
-    let isCreator: Bool
-    let isConnection: Bool
-
-    public init(
-        id: Data,
-        title: String,
-        image: Data? = nil,
-        isCreator: Bool = false,
-        isConnection: Bool = true
-    ) {
-        self.id = id
-        self.title = title
-        self.image = image
-        self.isCreator = isCreator
-        self.isConnection = isConnection
-    }
+  let id: Data
+  let title: String
+  let image: Data?
+  let isCreator: Bool
+  let isConnection: Bool
+
+  public init(
+    id: Data,
+    title: String,
+    image: Data? = nil,
+    isCreator: Bool = false,
+    isConnection: Bool = true
+  ) {
+    self.id = id
+    self.title = title
+    self.image = image
+    self.isCreator = isCreator
+    self.isConnection = isConnection
+  }
 }
 
 final class DrawerTableCell: UITableViewCell {
-    let titleLabel = UILabel()
-    let subtitleLabel = UILabel()
-    let avatarView = AvatarView()
-    let stackView = UIStackView()
-
-    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
-        super.init(style: style, reuseIdentifier: reuseIdentifier)
-
-        selectionStyle = .none
-        backgroundColor = Asset.neutralWhite.color
-
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
-        subtitleLabel.font = Fonts.Mulish.regular.font(size: 14.0)
-        titleLabel.textColor = Asset.neutralActive.color
-
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(titleLabel)
-        stackView.addArrangedSubview(subtitleLabel)
-
-        contentView.addSubview(avatarView)
-        contentView.addSubview(stackView)
-
-        avatarView.snp.makeConstraints {
-            $0.width.equalTo(36)
-            $0.height.equalTo(36)
-            $0.top.equalToSuperview().offset(10)
-            $0.left.equalToSuperview()
-            $0.bottom.equalToSuperview().offset(-10)
-        }
+  let titleLabel = UILabel()
+  let subtitleLabel = UILabel()
+  let avatarView = AvatarView()
+  let stackView = UIStackView()
+
+  override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+    super.init(style: style, reuseIdentifier: reuseIdentifier)
+
+    selectionStyle = .none
+    backgroundColor = Asset.neutralWhite.color
+
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
+    subtitleLabel.font = Fonts.Mulish.regular.font(size: 14.0)
+    titleLabel.textColor = Asset.neutralActive.color
+
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(titleLabel)
+    stackView.addArrangedSubview(subtitleLabel)
+
+    contentView.addSubview(avatarView)
+    contentView.addSubview(stackView)
+
+    avatarView.snp.makeConstraints {
+      $0.width.equalTo(36)
+      $0.height.equalTo(36)
+      $0.top.equalToSuperview().offset(10)
+      $0.left.equalToSuperview()
+      $0.bottom.equalToSuperview().offset(-10)
+    }
 
-        stackView.snp.makeConstraints {
-            $0.left.equalTo(avatarView.snp.right).offset(15)
-            $0.top.equalTo(avatarView)
-            $0.bottom.equalTo(avatarView)
-            $0.right.equalToSuperview()
-        }
+    stackView.snp.makeConstraints {
+      $0.left.equalTo(avatarView.snp.right).offset(15)
+      $0.top.equalTo(avatarView)
+      $0.bottom.equalTo(avatarView)
+      $0.right.equalToSuperview()
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 
-    override func prepareForReuse() {
-        super.prepareForReuse()
+  override func prepareForReuse() {
+    super.prepareForReuse()
 
-        titleLabel.text = nil
-        subtitleLabel.text = nil
-        avatarView.prepareForReuse()
-    }
+    titleLabel.text = nil
+    subtitleLabel.text = nil
+    avatarView.prepareForReuse()
+  }
 }
diff --git a/Sources/DrawerFeature/Items/DrawerText.swift b/Sources/DrawerFeature/Items/DrawerText.swift
index 8cfeaffa7487d0fe644b7538fd245648ef4cd21c..beac93e6951e417a42e5f2844f730c228af11dbf 100644
--- a/Sources/DrawerFeature/Items/DrawerText.swift
+++ b/Sources/DrawerFeature/Items/DrawerText.swift
@@ -1,70 +1,71 @@
 import UIKit
 import Shared
+import AppResources
 
 public final class DrawerText: DrawerItem {
-    private let font: UIFont
-    private let text: String
-    private let color: UIColor
-    private let leftImage: UIImage?
-    private let alignment: NSTextAlignment
-    private let lineHeightMultiple: CGFloat
-    private let customAttributes: [NSAttributedString.Key: Any]?
-    private let stackView = UIStackView()
+  private let font: UIFont
+  private let text: String
+  private let color: UIColor
+  private let leftImage: UIImage?
+  private let alignment: NSTextAlignment
+  private let lineHeightMultiple: CGFloat
+  private let customAttributes: [NSAttributedString.Key: Any]?
+  private let stackView = UIStackView()
 
-    public var spacingAfter: CGFloat? = 0
+  public var spacingAfter: CGFloat? = 0
 
-    public init(
-        font: UIFont = Fonts.Mulish.regular.font(size: 16.0),
-        text: String,
-        color: UIColor = Asset.neutralActive.color,
-        alignment: NSTextAlignment = .left,
-        lineHeightMultiple: CGFloat = 1.1,
-        spacingAfter: CGFloat = 10,
-        customAttributes: [NSAttributedString.Key: Any]? = nil,
-        leftImage: UIImage? = nil
-    ) {
-        self.font = font
-        self.text = text
-        self.color = color
-        self.leftImage = leftImage
-        self.alignment = alignment
-        self.spacingAfter = spacingAfter
-        self.customAttributes = customAttributes
-        self.lineHeightMultiple = lineHeightMultiple
-    }
-
-    public func makeView() -> UIView {
-        let label = UILabel()
-        label.numberOfLines = 0
+  public init(
+    font: UIFont = Fonts.Mulish.regular.font(size: 16.0),
+    text: String,
+    color: UIColor = Asset.neutralActive.color,
+    alignment: NSTextAlignment = .left,
+    lineHeightMultiple: CGFloat = 1.1,
+    spacingAfter: CGFloat = 10,
+    customAttributes: [NSAttributedString.Key: Any]? = nil,
+    leftImage: UIImage? = nil
+  ) {
+    self.font = font
+    self.text = text
+    self.color = color
+    self.leftImage = leftImage
+    self.alignment = alignment
+    self.spacingAfter = spacingAfter
+    self.customAttributes = customAttributes
+    self.lineHeightMultiple = lineHeightMultiple
+  }
 
-        let paragraphStyle = NSMutableParagraphStyle()
-        paragraphStyle.alignment = alignment
-        paragraphStyle.lineHeightMultiple = lineHeightMultiple
+  public func makeView() -> UIView {
+    let label = UILabel()
+    label.numberOfLines = 0
 
-        let attrString = NSMutableAttributedString(string: text)
-        attrString.addAttributes([
-            .paragraphStyle: paragraphStyle,
-            .foregroundColor: color,
-            .font: font as Any
-        ])
+    let paragraphStyle = NSMutableParagraphStyle()
+    paragraphStyle.alignment = alignment
+    paragraphStyle.lineHeightMultiple = lineHeightMultiple
 
-        if let customAttributes = customAttributes {
-            attrString.addAttributes(
-                attributes: customAttributes,
-                betweenCharacters: "#"
-            )
-        }
+    let attrString = NSMutableAttributedString(string: text)
+    attrString.addAttributes([
+      .paragraphStyle: paragraphStyle,
+      .foregroundColor: color,
+      .font: font as Any
+    ])
 
-        label.attributedText = attrString
+    if let customAttributes = customAttributes {
+      attrString.addAttributes(
+        attributes: customAttributes,
+        betweenCharacters: "#"
+      )
+    }
 
-        if let image = leftImage {
-            let imageView = UIImageView()
-            imageView.image = image
-            stackView.addArrangedSubview(imageView)
-        }
+    label.attributedText = attrString
 
-        stackView.addArrangedSubview(label)
-        stackView.spacing = 5
-        return stackView
+    if let image = leftImage {
+      let imageView = UIImageView()
+      imageView.image = image
+      stackView.addArrangedSubview(imageView)
     }
+
+    stackView.addArrangedSubview(label)
+    stackView.spacing = 5
+    return stackView
+  }
 }
diff --git a/Sources/InputField/InputField.swift b/Sources/InputField/InputField.swift
index e041db906a504c4a1e6295c84e14a456a18b357c..f0be951d47dbeeecebeb8abd5a3d56eb13c6e31c 100644
--- a/Sources/InputField/InputField.swift
+++ b/Sources/InputField/InputField.swift
@@ -1,351 +1,350 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 
 public final class InputField: UIView {
-    public enum Style {
-        case phone
-        case regular
+  public enum Style {
+    case phone
+    case regular
+  }
+
+  public enum LeftView {
+    case image(UIImage)
+  }
+
+  public enum RightView {
+    case image(UIImage)
+    case toggleSecureEntry
+  }
+
+  public enum ValidationStatus: Equatable {
+    case valid(String?)
+    case invalid(String)
+    case unknown(String?)
+  }
+
+  let title = UILabel()
+  let hide = UIButton()
+  let clear = UIButton()
+  let subtitle = UILabel()
+
+  let outerStack = UIStackView()
+  let codeContainer = UIView()
+  let code = PhoneCodeField()
+
+  let container = UIView()
+  let innerStack = UIStackView()
+  let left = UIImageView()
+  let field = UITextField()
+
+  let toolbar = UIToolbar()
+  let toolbarButton = UIButton()
+
+  var isPhone: Bool = false
+
+  // MARK: Properties
+
+  private var rightView: RightView? = .none {
+    didSet { set(rightView: rightView) }
+  }
+
+  private var clearable: Bool = false
+  private var allowsEmptySpace: Bool = true
+  private var cancellables = Set<AnyCancellable>()
+
+  private let codeSubject = PassthroughSubject<Void, Never>()
+  private let returnSubject = PassthroughSubject<Void, Never>()
+  private let textSubject = PassthroughSubject<String, Never>()
+
+  public var codePublisher: AnyPublisher<Void, Never> { codeSubject.eraseToAnyPublisher() }
+  public var textPublisher: AnyPublisher<String, Never> { textSubject.eraseToAnyPublisher() }
+  public var returnPublisher: AnyPublisher<Void, Never> { returnSubject.eraseToAnyPublisher() }
+
+  public init() {
+    super.init(frame: .zero)
+    setup()
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public func makeFirstResponder() {
+    field.becomeFirstResponder()
+  }
+
+  public func setup(
+    style: Style = .regular,
+    title: String? = nil,
+    placeholder: String? = nil,
+    leftView: LeftView? = nil,
+    rightView: RightView? = nil,
+    accessibility: String? = nil,
+    subtitleAccessibility: String? = nil,
+    subtitleColor: UIColor = Asset.neutralWhite.color,
+    allowsEmptySpace: Bool = true,
+    keyboardType: UIKeyboardType = .default,
+    autocapitalization: UITextAutocapitalizationType = .sentences,
+    autoCorrect: UITextAutocorrectionType = .no,
+    contentType: UITextContentType? = nil,
+    returnKeyType: UIReturnKeyType = .done,
+    toolbarButtonTitle: String = Localized.Shared.done,
+    codeAccessibility: String? = nil,
+    clearable: Bool = false
+  ) {
+    self.title.text = title
+    self.set(leftView: leftView)
+
+    self.rightView = rightView
+    self.field.attributedPlaceholder = NSAttributedString(
+      string: placeholder ?? "",
+      attributes: [
+        .font: Fonts.Mulish.semiBold.font(size: 14.0),
+        .foregroundColor: Asset.neutralDisabled.color
+      ])
+
+    if contentType == .telephoneNumber {
+      isPhone = true
+    } else {
+      self.field.textContentType = contentType
     }
 
-    public enum LeftView {
-        case image(UIImage)
+    self.field.returnKeyType = returnKeyType
+    self.field.keyboardType = keyboardType
+    self.subtitle.textColor = subtitleColor
+    self.allowsEmptySpace = allowsEmptySpace
+    self.field.autocorrectionType = autoCorrect
+    self.field.accessibilityIdentifier = accessibility
+    self.field.autocapitalizationType = autocapitalization
+    self.subtitle.accessibilityIdentifier = subtitleAccessibility
+    self.clearable = clearable
+
+    if style == .phone {
+      codeContainer.addSubview(code)
+      code.accessibilityIdentifier = codeAccessibility
+      code.snp.makeConstraints { $0.edges.equalToSuperview() }
+      outerStack.insertArrangedSubview(codeContainer, at: 0)
+
+      code.publisher(for: .touchUpInside)
+        .sink { [weak codeSubject] in codeSubject?.send() }
+        .store(in: &cancellables)
+
+      self.field.keyboardType = .numberPad
+      self.allowsEmptySpace = false
+
+      toolbar.barTintColor = Asset.neutralWhite.color
+      toolbarButton.setTitle(toolbarButtonTitle, for: .normal)
+      toolbarButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
+      toolbarButton.titleLabel?.font = Fonts.Mulish.bold.font(size: 17.0)
+      toolbar.setShadowImage(.color(Asset.neutralLine.color), forToolbarPosition: .any)
+      toolbarButton.addTarget(self, action: #selector(didTapDone), for: .touchUpInside)
+      toolbar.items = [UIBarButtonItem(customView: toolbarButton.pinning(at: .right(0)))]
+
+      toolbar.sizeToFit()
+      self.field.inputAccessoryView = toolbar
     }
-
-    public enum RightView {
-        case image(UIImage)
-        case toggleSecureEntry
-    }
-
-    public enum ValidationStatus: Equatable {
-        case valid(String?)
-        case invalid(String)
-        case unknown(String?)
-    }
-
-    let title = UILabel()
-    let hide = UIButton()
-    let clear = UIButton()
-    let subtitle = UILabel()
-
-    let outerStack = UIStackView()
-    let codeContainer = UIView()
-    let code = PhoneCodeField()
-
-    let container = UIView()
-    let innerStack = UIStackView()
-    let left = UIImageView()
-    let field = UITextField()
-
-    let toolbar = UIToolbar()
-    let toolbarButton = UIButton()
-
-    var isPhone: Bool = false
-
-    // MARK: Properties
-
-    private var rightView: RightView? = .none {
-        didSet { set(rightView: rightView) }
+  }
+
+  public func set(prefix: String) {
+    code.content.text = prefix
+  }
+
+  public func update(content: String) {
+    field.text = content
+  }
+
+  public func update(placeholder: String) {
+    field.placeholder = placeholder
+  }
+
+  public func update(status: ValidationStatus) {
+    switch status {
+    case .unknown(let text):
+      set(rightView: nil)
+      subtitle.text = text ?? " "
+    case .invalid(let text):
+      set(rightView: .image(Asset.sharedError.image))
+      subtitle.text = text
+    case .valid(let text):
+      set(rightView: .image(Asset.sharedSuccess.image))
+      subtitle.text = text ?? " "
     }
+  }
 
-    private var clearable: Bool = false
-    private var allowsEmptySpace: Bool = true
-    private var cancellables = Set<AnyCancellable>()
-
-    private let codeSubject = PassthroughSubject<Void, Never>()
-    private let returnSubject = PassthroughSubject<Void, Never>()
-    private let textSubject = PassthroughSubject<String, Never>()
+  // MARK: Private
 
-    public var codePublisher: AnyPublisher<Void, Never> { codeSubject.eraseToAnyPublisher() }
-    public var textPublisher: AnyPublisher<String, Never> { textSubject.eraseToAnyPublisher() }
-    public var returnPublisher: AnyPublisher<Void, Never> { returnSubject.eraseToAnyPublisher() }
-
-    public init() {
-        super.init(frame: .zero)
-        setup()
+  private func set(leftView: LeftView?) {
+    switch leftView {
+    case .image(let image):
+      left.image = image
+      left.tintColor = Asset.neutralDisabled.color
+    case .none:
+      innerStack.removeArrangedSubview(left)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    // MARK: Public
-
-    public func makeFirstResponder() {
-        field.becomeFirstResponder()
+  }
+
+  public func set(rightView: RightView?) {
+    switch rightView {
+    case.image(let image):
+      field.rightView = UIImageView(image: image)
+    case .toggleSecureEntry:
+      field.rightView = hide
+      field.isSecureTextEntry = true
+      hide.setImage(hideButtonImage(isSecureEntry: field.isSecureTextEntry), for: .normal)
+    case .none:
+      field.rightView = nil
     }
-
-    public func setup(
-        style: Style = .regular,
-        title: String? = nil,
-        placeholder: String? = nil,
-        leftView: LeftView? = nil,
-        rightView: RightView? = nil,
-        accessibility: String? = nil,
-        subtitleAccessibility: String? = nil,
-        subtitleColor: UIColor = Asset.neutralWhite.color,
-        allowsEmptySpace: Bool = true,
-        keyboardType: UIKeyboardType = .default,
-        autocapitalization: UITextAutocapitalizationType = .sentences,
-        autoCorrect: UITextAutocorrectionType = .no,
-        contentType: UITextContentType? = nil,
-        returnKeyType: UIReturnKeyType = .done,
-        toolbarButtonTitle: String = Localized.Shared.done,
-        codeAccessibility: String? = nil,
-        clearable: Bool = false
-    ) {
-        self.title.text = title
-        self.set(leftView: leftView)
-
-        self.rightView = rightView
-        self.field.attributedPlaceholder = NSAttributedString(
-            string: placeholder ?? "",
-            attributes: [
-                .font: Fonts.Mulish.semiBold.font(size: 14.0),
-                .foregroundColor: Asset.neutralDisabled.color
-            ])
-
-        if contentType == .telephoneNumber {
-            isPhone = true
-        } else {
-            self.field.textContentType = contentType
-        }
-
-        self.field.returnKeyType = returnKeyType
-        self.field.keyboardType = keyboardType
-        self.subtitle.textColor = subtitleColor
-        self.allowsEmptySpace = allowsEmptySpace
-        self.field.autocorrectionType = autoCorrect
-        self.field.accessibilityIdentifier = accessibility
-        self.field.autocapitalizationType = autocapitalization
-        self.subtitle.accessibilityIdentifier = subtitleAccessibility
-        self.clearable = clearable
-
-        if style == .phone {
-            codeContainer.addSubview(code)
-            code.accessibilityIdentifier = codeAccessibility
-            code.snp.makeConstraints { $0.edges.equalToSuperview() }
-            outerStack.insertArrangedSubview(codeContainer, at: 0)
-
-            code.publisher(for: .touchUpInside)
-                .sink { [weak codeSubject] in codeSubject?.send() }
-                .store(in: &cancellables)
-
-            self.field.keyboardType = .numberPad
-            self.allowsEmptySpace = false
-
-            toolbar.barTintColor = Asset.neutralWhite.color
-            toolbarButton.setTitle(toolbarButtonTitle, for: .normal)
-            toolbarButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
-            toolbarButton.titleLabel?.font = Fonts.Mulish.bold.font(size: 17.0)
-            toolbar.setShadowImage(.color(Asset.neutralLine.color), forToolbarPosition: .any)
-            toolbarButton.addTarget(self, action: #selector(didTapDone), for: .touchUpInside)
-            toolbar.items = [UIBarButtonItem(customView: toolbarButton.pinning(at: .right(0)))]
-
-            toolbar.sizeToFit()
-            self.field.inputAccessoryView = toolbar
-        }
-    }
-
-    public func set(prefix: String) {
-        code.content.text = prefix
-    }
-
-    public func update(content: String) {
-        field.text = content
-    }
-
-    public func update(placeholder: String) {
-        field.placeholder = placeholder
-    }
-
-    public func update(status: ValidationStatus) {
-        switch status {
-        case .unknown(let text):
-            set(rightView: nil)
-            subtitle.text = text ?? " "
-        case .invalid(let text):
-            set(rightView: .image(Asset.sharedError.image))
-            subtitle.text = text
-        case .valid(let text):
-            set(rightView: .image(Asset.sharedSuccess.image))
-            subtitle.text = text ?? " "
-        }
-    }
-
-    // MARK: Private
-
-    private func set(leftView: LeftView?) {
-        switch leftView {
-        case .image(let image):
-            left.image = image
-            left.tintColor = Asset.neutralDisabled.color
-        case .none:
-            innerStack.removeArrangedSubview(left)
-        }
+  }
+
+  private func hideButtonImage(isSecureEntry: Bool) -> UIImage? {
+    let openImage = Asset.eyeOpen.image.withTintColor(Asset.neutralWeak.color)
+    let closedImage = Asset.eyeClosed.image.withTintColor(Asset.neutralWeak.color)
+    return isSecureEntry ? closedImage : openImage
+  }
+
+  private func setup() {
+    subtitle.textAlignment = .right
+    subtitle.numberOfLines = 0
+    container.layer.cornerRadius = 4
+    container.backgroundColor = Asset.neutralSecondary.color
+
+    codeContainer.layer.cornerRadius = 4
+    codeContainer.backgroundColor = Asset.neutralSecondary.color
+
+    title.textColor = Asset.neutralWeak.color
+    field.textColor = Asset.neutralActive.color
+    subtitle.textColor = Asset.neutralWhite.color
+
+    title.font = Fonts.Mulish.regular.font(size: 12.0)
+    field.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    subtitle.font = Fonts.Mulish.regular.font(size: 12.0)
+
+    clear.setImage(Asset.sharedCross.image, for: .normal)
+
+    field.textPublisher
+      .sink { [weak textSubject] in textSubject?.send($0) }
+      .store(in: &cancellables)
+
+    hide.publisher(for: .touchUpInside)
+      .sink { [unowned self] _ in
+        field.isSecureTextEntry.toggle()
+        hide.setImage(hideButtonImage(isSecureEntry: field.isSecureTextEntry), for: .normal)
+      }.store(in: &cancellables)
+
+    clear.publisher(for: .touchUpInside)
+      .sink { [unowned self] in
+        field.text = ""
+        textSubject.send("")
+        field.resignFirstResponder()
+      }.store(in: &cancellables)
+
+    field.delegate = self
+    field.rightViewMode = .always
+
+    left.contentMode = .center
+    left.setContentHuggingPriority(.required, for: .horizontal)
+
+    innerStack.spacing = 12
+    innerStack.addArrangedSubview(left)
+    innerStack.addArrangedSubview(field)
+
+    outerStack.spacing = 8
+    container.addSubview(innerStack)
+    outerStack.addArrangedSubview(container)
+
+    addSubview(title)
+    addSubview(outerStack)
+    addSubview(subtitle)
+
+    setupConstraints()
+  }
+
+  private func setupConstraints() {
+    title.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview().offset(8)
     }
 
-    public func set(rightView: RightView?) {
-        switch rightView {
-        case.image(let image):
-            field.rightView = UIImageView(image: image)
-        case .toggleSecureEntry:
-            field.rightView = hide
-            field.isSecureTextEntry = true
-            hide.setImage(hideButtonImage(isSecureEntry: field.isSecureTextEntry), for: .normal)
-        case .none:
-            field.rightView = nil
-        }
+    outerStack.snp.makeConstraints {
+      $0.top.equalTo(title.snp.bottom).offset(10)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.height.equalTo(36)
     }
 
-    private func hideButtonImage(isSecureEntry: Bool) -> UIImage? {
-        let openImage = Asset.eyeOpen.image.withTintColor(Asset.neutralWeak.color)
-        let closedImage = Asset.eyeClosed.image.withTintColor(Asset.neutralWeak.color)
-        return isSecureEntry ? closedImage : openImage
+    innerStack.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview().offset(11)
+      $0.right.equalToSuperview().offset(-11)
+      $0.bottom.equalToSuperview()
     }
 
-    private func setup() {
-        subtitle.textAlignment = .right
-        subtitle.numberOfLines = 0
-        container.layer.cornerRadius = 4
-        container.backgroundColor = Asset.neutralSecondary.color
-
-        codeContainer.layer.cornerRadius = 4
-        codeContainer.backgroundColor = Asset.neutralSecondary.color
-
-        title.textColor = Asset.neutralWeak.color
-        field.textColor = Asset.neutralActive.color
-        subtitle.textColor = Asset.neutralWhite.color
-
-        title.font = Fonts.Mulish.regular.font(size: 12.0)
-        field.font = Fonts.Mulish.semiBold.font(size: 14.0)
-        subtitle.font = Fonts.Mulish.regular.font(size: 12.0)
-
-        clear.setImage(Asset.sharedCross.image, for: .normal)
-
-        field.textPublisher
-            .sink { [weak textSubject] in textSubject?.send($0) }
-            .store(in: &cancellables)
-
-        hide.publisher(for: .touchUpInside)
-            .sink { [unowned self] _ in
-                field.isSecureTextEntry.toggle()
-                hide.setImage(hideButtonImage(isSecureEntry: field.isSecureTextEntry), for: .normal)
-            }.store(in: &cancellables)
-
-        clear.publisher(for: .touchUpInside)
-            .sink { [unowned self] in
-                field.text = ""
-                textSubject.send("")
-                field.resignFirstResponder()
-            }.store(in: &cancellables)
-
-        field.delegate = self
-        field.rightViewMode = .always
-
-        left.contentMode = .center
-        left.setContentHuggingPriority(.required, for: .horizontal)
-
-        innerStack.spacing = 12
-        innerStack.addArrangedSubview(left)
-        innerStack.addArrangedSubview(field)
-
-        outerStack.spacing = 8
-        container.addSubview(innerStack)
-        outerStack.addArrangedSubview(container)
-
-        addSubview(title)
-        addSubview(outerStack)
-        addSubview(subtitle)
-
-        setupConstraints()
+    subtitle.snp.makeConstraints {
+      $0.top.equalTo(outerStack.snp.bottom).offset(8)
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+      $0.left.greaterThanOrEqualToSuperview()
     }
+  }
 
-    private func setupConstraints() {
-        title.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview().offset(8)
-        }
-
-        outerStack.snp.makeConstraints { make in
-            make.top.equalTo(title.snp.bottom).offset(10)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.height.equalTo(36)
-        }
-
-        innerStack.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview().offset(11)
-            make.right.equalToSuperview().offset(-11)
-            make.bottom.equalToSuperview()
-        }
+  @objc private func didTapDone() {
+    returnSubject.send()
+  }
 
-        subtitle.snp.makeConstraints { make in
-            make.top.equalTo(outerStack.snp.bottom).offset(8)
-            make.right.equalToSuperview()
-            make.bottom.equalToSuperview()
-            make.left.greaterThanOrEqualToSuperview()
-        }
+  public func textFieldDidBeginEditing(_ textField: UITextField) {
+    if clearable {
+      field.rightView = clear
     }
+  }
 
-    @objc private func didTapDone() {
-        returnSubject.send()
+  public func textFieldDidEndEditing(_ textField: UITextField) {
+    if clearable {
+      set(rightView: rightView)
     }
-
-    public func textFieldDidBeginEditing(_ textField: UITextField) {
-        if clearable {
-            field.rightView = clear
-        }
+  }
+
+  public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
+    returnSubject.send()
+    return true
+  }
+
+  public func textField(
+    _ textField: UITextField,
+    shouldChangeCharactersIn range: NSRange,
+    replacementString string: String
+  ) -> Bool {
+    if isPhone {
+      if string.count > 1 {
+        textField.text = string.replaceCharactersFromSet(characterSet: .decimalDigits.inverted)
+        textSubject.send(textField.text ?? "")
+        return false
+      } else {
+        return string.rangeOfCharacter(from: .decimalDigits) != nil || string == ""
+      }
     }
 
-    public func textFieldDidEndEditing(_ textField: UITextField) {
-        if clearable {
-            set(rightView: rightView)
+    if !allowsEmptySpace {
+      if string.count > 1 {
+        if textField.textContentType == .emailAddress && [".us", ".net", ".edu", ".org", ".com"].contains(string) {
+          textSubject.send(textField.text ?? "")
+          return true
         }
-    }
 
-    public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
-        returnSubject.send()
-        return true
+        textField.text = string.replaceCharactersFromSet(characterSet: .whitespacesAndNewlines)
+        textSubject.send(textField.text ?? "")
+        return false
+      } else {
+        return string != " "
+      }
     }
 
-    public func textField(
-        _ textField: UITextField,
-        shouldChangeCharactersIn range: NSRange,
-        replacementString string: String
-    ) -> Bool {
-        if isPhone {
-            if string.count > 1 {
-                textField.text = string.replaceCharactersFromSet(characterSet: .decimalDigits.inverted)
-                textSubject.send(textField.text ?? "")
-                return false
-            } else {
-                return string.rangeOfCharacter(from: .decimalDigits) != nil || string == ""
-            }
-        }
-
-        if !allowsEmptySpace {
-            if string.count > 1 {
-                if textField.textContentType == .emailAddress && [".us", ".net", ".edu", ".org", ".com"].contains(string) {
-                    textSubject.send(textField.text ?? "")
-                    return true
-                }
-
-                textField.text = string.replaceCharactersFromSet(characterSet: .whitespacesAndNewlines)
-                textSubject.send(textField.text ?? "")
-                return false
-            } else {
-                return string != " "
-            }
-        }
-
-        return true
-    }
+    return true
+  }
 }
 
 extension InputField: UITextFieldDelegate {}
 
 private extension String {
-    func replaceCharactersFromSet(characterSet: CharacterSet, replacementString: String = "") -> String {
-        return components(separatedBy: characterSet).joined(separator: replacementString)
-    }
+  func replaceCharactersFromSet(characterSet: CharacterSet, replacementString: String = "") -> String {
+    return components(separatedBy: characterSet).joined(separator: replacementString)
+  }
 }
diff --git a/Sources/InputField/OutlinedInputField.swift b/Sources/InputField/OutlinedInputField.swift
index 3bb8ad3005167b9e9e99511243da912f7082d434..9ae881bbf855cbff43b463e0e0cf2425568b9c2a 100644
--- a/Sources/InputField/OutlinedInputField.swift
+++ b/Sources/InputField/OutlinedInputField.swift
@@ -1,85 +1,86 @@
 import UIKit
 import Shared
 import Combine
+import AppResources
 
 public final class OutlinedInputField: UIView {
-    private let stackView = UIStackView()
-    private let textField = UITextField()
-    private let placeholderLabel = UILabel()
-    private let inputContainerView = UIView()
+  private let stackView = UIStackView()
+  private let textField = UITextField()
+  private let placeholderLabel = UILabel()
+  private let inputContainerView = UIView()
 
-    private let secureInputButton = SecureInputButton()
+  private let secureInputButton = SecureInputButton()
 
-    public var textPublisher: AnyPublisher<String, Never> {
-        textField.textPublisher
-    }
+  public var textPublisher: AnyPublisher<String, Never> {
+    textField.textPublisher
+  }
 
-    public init() {
-        super.init(frame: .zero)
+  public init() {
+    super.init(frame: .zero)
 
-        layer.borderWidth = 1.0
-        layer.cornerRadius = 4.0
-        layer.masksToBounds = true
-        layer.borderColor = Asset.neutralWeak.color.cgColor
+    layer.borderWidth = 1.0
+    layer.cornerRadius = 4.0
+    layer.masksToBounds = true
+    layer.borderColor = Asset.neutralWeak.color.cgColor
 
-        textField.delegate = self
-        textField.backgroundColor = .clear
-        textField.textColor = Asset.neutralDark.color
-        placeholderLabel.textColor = Asset.neutralWeak.color
-        placeholderLabel.font = Fonts.Mulish.regular.font(size: 16.0)
+    textField.delegate = self
+    textField.backgroundColor = .clear
+    textField.textColor = Asset.neutralDark.color
+    placeholderLabel.textColor = Asset.neutralWeak.color
+    placeholderLabel.font = Fonts.Mulish.regular.font(size: 16.0)
 
-        secureInputButton.button.addTarget(self, action: #selector(didTapRight), for: .touchUpInside)
+    secureInputButton.button.addTarget(self, action: #selector(didTapRight), for: .touchUpInside)
 
-        inputContainerView.addSubview(placeholderLabel)
-        inputContainerView.addSubview(textField)
+    inputContainerView.addSubview(placeholderLabel)
+    inputContainerView.addSubview(textField)
 
-        stackView.addArrangedSubview(inputContainerView)
-        stackView.addArrangedSubview(secureInputButton)
+    stackView.addArrangedSubview(inputContainerView)
+    stackView.addArrangedSubview(secureInputButton)
 
-        addSubview(stackView)
+    addSubview(stackView)
 
-        placeholderLabel.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(15)
-            $0.left.equalToSuperview().offset(15)
-            $0.right.lessThanOrEqualToSuperview().offset(-15)
-            $0.bottom.equalToSuperview().offset(-18)
-        }
+    placeholderLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(15)
+      $0.left.equalToSuperview().offset(15)
+      $0.right.lessThanOrEqualToSuperview().offset(-15)
+      $0.bottom.equalToSuperview().offset(-18)
+    }
 
-        textField.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(15)
-            $0.left.equalToSuperview().offset(15)
-            $0.right.equalToSuperview().offset(-15)
-            $0.bottom.equalToSuperview().offset(-18)
-        }
+    textField.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(15)
+      $0.left.equalToSuperview().offset(15)
+      $0.right.equalToSuperview().offset(-15)
+      $0.bottom.equalToSuperview().offset(-18)
+    }
 
-        stackView.snp.makeConstraints {
-            $0.edges.equalToSuperview()
-        }
+    stackView.snp.makeConstraints {
+      $0.edges.equalToSuperview()
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 
-    public func setup(title: String, sensitive: Bool = false) {
-        placeholderLabel.text = title
-        textField.isSecureTextEntry = sensitive
-        secureInputButton.isHidden = !sensitive
-    }
+  public func setup(title: String, sensitive: Bool = false) {
+    placeholderLabel.text = title
+    textField.isSecureTextEntry = sensitive
+    secureInputButton.isHidden = !sensitive
+  }
 
-    @objc private func didTapRight() {
-        textField.isSecureTextEntry.toggle()
-        secureInputButton.setSecure(textField.isSecureTextEntry)
-    }
+  @objc private func didTapRight() {
+    textField.isSecureTextEntry.toggle()
+    secureInputButton.setSecure(textField.isSecureTextEntry)
+  }
 }
 
 extension OutlinedInputField: UITextFieldDelegate {
-    public func textField(
-        _ textField: UITextField,
-        shouldChangeCharactersIn range: NSRange,
-        replacementString string: String
-    ) -> Bool {
-        placeholderLabel.alpha = (textField.text! as NSString)
-            .replacingCharacters(in: range, with: string)
-            .count > 0 ? 0.0 : 1.0
-        return true
-    }
+  public func textField(
+    _ textField: UITextField,
+    shouldChangeCharactersIn range: NSRange,
+    replacementString string: String
+  ) -> Bool {
+    placeholderLabel.alpha = (textField.text! as NSString)
+      .replacingCharacters(in: range, with: string)
+      .count > 0 ? 0.0 : 1.0
+    return true
+  }
 }
diff --git a/Sources/InputField/PhoneCodeField.swift b/Sources/InputField/PhoneCodeField.swift
index 2bb6b4343a94f2f93736df04bfcbe7883cbdd88d..e0504384c1873517e43ddaa43db422894846b7e3 100644
--- a/Sources/InputField/PhoneCodeField.swift
+++ b/Sources/InputField/PhoneCodeField.swift
@@ -1,34 +1,26 @@
 import UIKit
 import Shared
+import AppResources
 
 final class PhoneCodeField: UIButton {
-    // MARK: UI
+  public let content = UILabel()
 
-    public let content = UILabel()
+  public init() {
+    super.init(frame: .zero)
 
-    // MARK: Lifecycle
+    content.textColor = Asset.neutralActive.color
+    content.font = Fonts.Mulish.semiBold.font(size: 14.0)
 
-    public init() {
-        super.init(frame: .zero)
-        setup()
-    }
-
-    public required init?(coder: NSCoder) { nil }
-
-    // MARK: Private
+    addSubview(content)
 
-    private func setup() {
-        content.textColor = Asset.neutralActive.color
-        content.font = Fonts.Mulish.semiBold.font(size: 14.0)
-
-        addSubview(content)
-
-        content.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview().offset(11)
-            make.right.equalToSuperview().offset(-11)
-            make.width.equalTo(60)
-            make.bottom.equalToSuperview()
-        }
+    content.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview().offset(11)
+      $0.right.equalToSuperview().offset(-11)
+      $0.width.equalTo(60)
+      $0.bottom.equalToSuperview()
     }
+  }
+
+  public required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/InputField/SecureInputButton.swift b/Sources/InputField/SecureInputButton.swift
index 1f2e6b20751370755ec23b966c153ca5440c9f32..d40aa67be4143483570abb59750c528b9172d500 100644
--- a/Sources/InputField/SecureInputButton.swift
+++ b/Sources/InputField/SecureInputButton.swift
@@ -1,31 +1,32 @@
 import UIKit
 import Shared
+import AppResources
 
 final class SecureInputButton: UIView {
-    private(set) var button = UIButton()
-    private let color = Asset.neutralSecondaryAlternative.color
-    private lazy var openedImage = Asset.eyeOpen.image.withTintColor(color)
-    private lazy var closedImage = Asset.eyeClosed.image.withTintColor(color)
+  private(set) var button = UIButton()
+  private let color = Asset.neutralSecondaryAlternative.color
+  private lazy var openedImage = Asset.eyeOpen.image.withTintColor(color)
+  private lazy var closedImage = Asset.eyeClosed.image.withTintColor(color)
 
-    init() {
-        super.init(frame: .zero)
+  init() {
+    super.init(frame: .zero)
 
-        button.setContentCompressionResistancePriority(.required, for: .horizontal)
-        button.setImage(Asset.eyeClosed.image.withTintColor(color), for: .normal)
+    button.setContentCompressionResistancePriority(.required, for: .horizontal)
+    button.setImage(Asset.eyeClosed.image.withTintColor(color), for: .normal)
 
-        addSubview(button)
+    addSubview(button)
 
-        button.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview().offset(10)
-            $0.right.equalToSuperview().offset(-10)
-            $0.bottom.equalToSuperview()
-        }
+    button.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview().offset(10)
+      $0.right.equalToSuperview().offset(-10)
+      $0.bottom.equalToSuperview()
     }
+  }
 
-    required init?(coder: NSCoder) { nil }
+  required init?(coder: NSCoder) { nil }
 
-    func setSecure(_ bool: Bool) {
-        button.setImage(bool ? closedImage : openedImage, for: .normal)
-    }
+  func setSecure(_ bool: Bool) {
+    button.setImage(bool ? closedImage : openedImage, for: .normal)
+  }
 }
diff --git a/Sources/InputField/Validator.swift b/Sources/InputField/Validator.swift
index b649bd5df0e51e8e0361f12570794236c4374848..8d77034eec63a0178f0bccdfd4737cd062ed93e0 100644
--- a/Sources/InputField/Validator.swift
+++ b/Sources/InputField/Validator.swift
@@ -1,5 +1,6 @@
 import Shared
 import Foundation
+import AppResources
 
 private enum Constants {
     static let codeMinimum = Localized.Validator.Code.minimum
diff --git a/Sources/Keychain/KeychainHandler.swift b/Sources/Keychain/KeychainHandler.swift
index 26df90bdb133dffef5dae41cc126be53fe242606..3ed93be94118e9ec41f2ab86d80cf177d7fe0225 100644
--- a/Sources/Keychain/KeychainHandler.swift
+++ b/Sources/Keychain/KeychainHandler.swift
@@ -2,50 +2,50 @@ import Foundation
 import KeychainAccess
 
 public enum KeychainSFTP: String {
-    case pwd
-    case host
-    case username
+  case pwd
+  case host
+  case username
 }
 
 public protocol KeychainHandling {
-    func clear() throws
-    func getPassword() throws -> Data?
-    func remove(_ key: String) throws
-    func store(password pwd: Data) throws
+  func clear() throws
+  func getPassword() throws -> Data?
+  func remove(_ key: String) throws
+  func store(password pwd: Data) throws
 
-    func get(key: KeychainSFTP) throws -> String?
-    func store(key: KeychainSFTP, value: String) throws
+  func get(key: KeychainSFTP) throws -> String?
+  func store(key: KeychainSFTP, value: String) throws
 }
 
 public struct KeychainHandler: KeychainHandling {
-    private let keychain: Keychain
-    private let password = "password"
+  private let keychain: Keychain
+  private let password = "password"
 
-    public init() {
-        self.keychain = Keychain(service: "XXM")
-    }
+  public init() {
+    self.keychain = Keychain(service: "XXM")
+  }
 
-    public func remove(_ key: String) throws {
-        try keychain.remove(key)
-    }
+  public func remove(_ key: String) throws {
+    try keychain.remove(key)
+  }
 
-    public func clear() throws {
-        try keychain.removeAll()
-    }
+  public func clear() throws {
+    try keychain.removeAll()
+  }
 
-    public func store(password pwd: Data) throws {
-        try keychain.set(pwd, key: password)
-    }
+  public func store(password pwd: Data) throws {
+    try keychain.set(pwd, key: password)
+  }
 
-    public func getPassword() throws -> Data? {
-        try keychain.getData(password)
-    }
+  public func getPassword() throws -> Data? {
+    try keychain.getData(password)
+  }
 
-    public func get(key: KeychainSFTP) throws -> String? {
-        try keychain.get(key.rawValue)
-    }
+  public func get(key: KeychainSFTP) throws -> String? {
+    try keychain.get(key.rawValue)
+  }
 
-    public func store(key: KeychainSFTP, value: String) throws {
-        try keychain.set(value, key: key.rawValue)
-    }
+  public func store(key: KeychainSFTP, value: String) throws {
+    try keychain.set(value, key: key.rawValue)
+  }
 }
diff --git a/Sources/VersionChecking/BackendVersionInformation.swift b/Sources/LaunchFeature/BackendVersionInformation.swift
similarity index 100%
rename from Sources/VersionChecking/BackendVersionInformation.swift
rename to Sources/LaunchFeature/BackendVersionInformation.swift
diff --git a/Sources/VersionChecking/DappVersionInformation.swift b/Sources/LaunchFeature/DappVersionInformation.swift
similarity index 100%
rename from Sources/VersionChecking/DappVersionInformation.swift
rename to Sources/LaunchFeature/DappVersionInformation.swift
diff --git a/Sources/LaunchFeature/LaunchController.swift b/Sources/LaunchFeature/LaunchController.swift
index 48a8e1fe8b08cb9bad37448dabe77bbe35464e93..dbc4067bbfbdfeb388cf52a84b05eff5c24ff01e 100644
--- a/Sources/LaunchFeature/LaunchController.swift
+++ b/Sources/LaunchFeature/LaunchController.swift
@@ -1,13 +1,14 @@
 import UIKit
 import Shared
 import Combine
-import PushFeature
 import Navigation
+import PushFeature
 import DrawerFeature
-import DI
+import AppResources
+import ComposableArchitecture
 
 public final class LaunchController: UIViewController {
-  @Dependency var navigator: Navigator
+  @Dependency(\.navigator) var navigator: Navigator
 
   private lazy var screenView = LaunchView()
 
@@ -54,18 +55,18 @@ public final class LaunchController: UIViewController {
       .sink { [unowned self] in
         guard $0.shouldPushChats == false else {
           guard $0.shouldShowTerms == false else {
-            navigator.perform(PresentTermsAndConditions(popAllowed: false))
+            navigator.perform(PresentTermsAndConditions(replacing: true, on: navigationController!))
             return
           }
           if let route = pendingPushRoute {
             hasPendingPushRoute(route)
             return
           }
-          navigator.perform(PresentChatList())
+          navigator.perform(PresentChatList(on: navigationController!))
           return
         }
         guard $0.shouldPushOnboarding == false else {
-          navigator.perform(PresentOnboardingStart())
+          navigator.perform(PresentOnboardingStart(on: navigationController!))
           return
         }
         if let update = $0.shouldOfferUpdate {
@@ -77,21 +78,24 @@ public final class LaunchController: UIViewController {
   private func hasPendingPushRoute(_ route: PushRouter.Route) {
     switch route {
     case .requests:
-      navigator.perform(PresentRequests())
+      navigator.perform(PresentRequests(on: navigationController!))
     case .search(username: let username):
-      navigator.perform(PresentSearch(searching: username))
+      navigator.perform(PresentSearch(
+        searching: username,
+        replacing: true,
+        on: navigationController!))
     case .groupChat(id: let groupId):
       if let info = viewModel.getGroupInfoWith(groupId: groupId) {
-        navigator.perform(PresentGroupChat(model: info))
+        navigator.perform(PresentGroupChat(groupInfo: info, on: navigationController!))
         return
       }
-      navigator.perform(PresentChatList())
+      navigator.perform(PresentChatList(on: navigationController!))
     case .contactChat(id: let userId):
       if let model = viewModel.getContactWith(userId: userId) {
-        navigator.perform(PresentChat(contact: model))
+        navigator.perform(PresentChat(contact: model, on: navigationController!))
         return
       }
-      navigator.perform(PresentChatList())
+      navigator.perform(PresentChatList(on: navigationController!))
     }
   }
 
@@ -152,6 +156,6 @@ public final class LaunchController: UIViewController {
         axis: .vertical,
         views: actions
       )
-    ], dismissable: false))
+    ], isDismissable: false, from: self))
   }
 }
diff --git a/Sources/LaunchFeature/LaunchView.swift b/Sources/LaunchFeature/LaunchView.swift
index 8a9fc7a43cfdf3b3b498b365c57763b9c2d7d0d0..b1c3982f558dc0b79c2e369c68f1e5b79f442723 100644
--- a/Sources/LaunchFeature/LaunchView.swift
+++ b/Sources/LaunchFeature/LaunchView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class LaunchView: UIView {
   let imageView = UIImageView()
diff --git a/Sources/LaunchFeature/LaunchViewModel+Database.swift b/Sources/LaunchFeature/LaunchViewModel+Database.swift
index e2c7558b42680eed2d26722dc6e67f23c686c565..15ae6c42c88abf3f095c05d666720761707ffd22 100644
--- a/Sources/LaunchFeature/LaunchViewModel+Database.swift
+++ b/Sources/LaunchFeature/LaunchViewModel+Database.swift
@@ -1,7 +1,6 @@
 import XXModels
 import Foundation
 import XXDatabase
-import DI
 import XXLegacyDatabaseMigrator
 
 extension LaunchViewModel {
diff --git a/Sources/LaunchFeature/LaunchViewModel+Messenger.swift b/Sources/LaunchFeature/LaunchViewModel+Messenger.swift
index 9871a24d1b8ffd21b98385b3abc7a896c46b72c3..abf90591ceb280b045fb00babcbc65ee111337a9 100644
--- a/Sources/LaunchFeature/LaunchViewModel+Messenger.swift
+++ b/Sources/LaunchFeature/LaunchViewModel+Messenger.swift
@@ -1,8 +1,6 @@
-import DI
 import Shared
 import XXClient
 import XXModels
-import XXLogger
 import Foundation
 import XXMessengerClient
 
@@ -93,61 +91,6 @@ extension LaunchViewModel {
     }))
   }
 
-  func handleIncomingTransfer(_ receivedFile: ReceivedFile) {
-    //    if var model = try? database.saveFileTransfer(.init(
-    //      id: receivedFile.transferId,
-    //      contactId: receivedFile.senderId,
-    //      name: receivedFile.name,
-    //      type: receivedFile.type,
-    //      data: nil,
-    //      progress: 0.0,
-    //      isIncoming: true,
-    //      createdAt: Date()
-    //    )) {
-    //      try! database.saveMessage(.init(
-    //        networkId: nil,
-    //        senderId: receivedFile.senderId,
-    //        recipientId: messenger.e2e.get()!.getContact().getId(),
-    //        groupId: nil,
-    //        date: Date(),
-    //        status: .receiving,
-    //        isUnread: false,
-    //        text: "",
-    //        replyMessageId: nil,
-    //        roundURL: nil,
-    //        fileTransferId: model.id
-    //      ))
-    //
-    //      if let manager: XXClient.FileTransfer = try? DI.Container.shared.resolve() {
-    //        print(">>> registerReceivedProgressCallback")
-    //
-    //        try! manager.registerReceivedProgressCallback(
-    //          transferId: receivedFile.transferId,
-    //          period: 1_000,
-    //          callback: .init(handle: { [weak self] in
-    //            guard let self else { return }
-    //            switch $0 {
-    //            case .success(let cb):
-    //              if cb.progress.completed {
-    //                model.progress = 100
-    //                model.data = try! manager.receive(transferId: receivedFile.transferId)
-    //              } else {
-    //                model.progress = Float(cb.progress.transmitted/cb.progress.total)
-    //              }
-    //
-    //              model = try! self.database.saveFileTransfer(model)
-    //
-    //            case .failure(let error):
-    //              print(error.localizedDescription)
-    //            }
-    //          })
-    //        )
-    //      } else {
-    //        //print(DI.Container.shared.dependencies)
-    //      }
-    //    }
-  }
-
   func handleDirectRequest(from contact: XXClient.Contact) {
     guard let id = try? contact.getId() else {
       fatalError("Couldn't extract ID from contact request arrived.")
@@ -370,24 +313,6 @@ extension LaunchViewModel {
     DI.Container.shared.register(manager)
   }
 
-  func generateTransferManager() throws {
-    //    let manager = try InitFileTransfer.live(
-    //      e2eId: messenger.e2e()!.getId(),
-    //      callback: .init(handle: { [weak self] in
-    //        guard let self else { return }
-    //
-    //        switch $0 {
-    //        case .success(let receivedFile):
-    //          self.handleIncomingTransfer(receivedFile, messenger: messenger)
-    //        case .failure(let error):
-    //          print(error.localizedDescription)
-    //        }
-    //      })
-    //    )
-    //
-    //    DI.Container.shared.register(manager)
-  }
-
   func generateTrafficManager() throws {
     let manager = try NewDummyTrafficManager.live(
       cMixId: messenger.e2e()!.getId()
@@ -420,7 +345,6 @@ extension LaunchViewModel {
 
     try generateGroupManager()
     try generateTrafficManager()
-    try generateTransferManager()
     listenToNetworkUpdates()
 
     if messenger.isLoggedIn() == false {
@@ -449,3 +373,59 @@ extension LaunchViewModel {
     // TODO: Biometric auth
   }
 }
+
+
+//func handleIncomingTransfer(_ receivedFile: ReceivedFile) {
+//  if var model = try? database.saveFileTransfer(.init(
+//    id: receivedFile.transferId,
+//    contactId: receivedFile.senderId,
+//    name: receivedFile.name,
+//    type: receivedFile.type,
+//    data: nil,
+//    progress: 0.0,
+//    isIncoming: true,
+//    createdAt: Date()
+//  )) {
+//    try! database.saveMessage(.init(
+//      networkId: nil,
+//      senderId: receivedFile.senderId,
+//      recipientId: messenger.e2e.get()!.getContact().getId(),
+//      groupId: nil,
+//      date: Date(),
+//      status: .receiving,
+//      isUnread: false,
+//      text: "",
+//      replyMessageId: nil,
+//      roundURL: nil,
+//      fileTransferId: model.id
+//    ))
+//
+//    if let manager: XXClient.FileTransfer = try? DI.Container.shared.resolve() {
+//      print(">>> registerReceivedProgressCallback")
+//
+//      try! manager.registerReceivedProgressCallback(
+//        transferId: receivedFile.transferId,
+//        period: 1_000,
+//        callback: .init(handle: { [weak self] in
+//          guard let self else { return }
+//          switch $0 {
+//          case .success(let cb):
+//            if cb.progress.completed {
+//              model.progress = 100
+//              model.data = try! manager.receive(transferId: receivedFile.transferId)
+//            } else {
+//              model.progress = Float(cb.progress.transmitted/cb.progress.total)
+//            }
+//
+//            model = try! self.database.saveFileTransfer(model)
+//
+//          case .failure(let error):
+//            print(error.localizedDescription)
+//          }
+//        })
+//      )
+//    } else {
+//      //print(DI.Container.shared.dependencies)
+//    }
+//  }
+//}
diff --git a/Sources/LaunchFeature/LaunchViewModel.swift b/Sources/LaunchFeature/LaunchViewModel.swift
index 2097750bd4de11937e831653e4c56efdecc0ca4a..3bd27c5e7669f6f9bf98e6c11ab25cddfb870b85 100644
--- a/Sources/LaunchFeature/LaunchViewModel.swift
+++ b/Sources/LaunchFeature/LaunchViewModel.swift
@@ -8,13 +8,11 @@ import CloudFiles
 import Foundation
 import Permissions
 import BackupFeature
-import NetworkMonitor
 import VersionChecking
 import ReportingFeature
 import CombineSchedulers
 import CloudFilesDropbox
 import XXMessengerClient
-import DI
 
 import class XXClient.Cancellable
 
diff --git a/Sources/VersionChecking/VersionChecking.swift b/Sources/LaunchFeature/VersionChecking.swift
similarity index 95%
rename from Sources/VersionChecking/VersionChecking.swift
rename to Sources/LaunchFeature/VersionChecking.swift
index 5acc10b5a6def59c701fa794cd2fe720b532d5ce..5dce368728baf174cf24c92b88189cc4b2b7ee0f 100644
--- a/Sources/VersionChecking/VersionChecking.swift
+++ b/Sources/LaunchFeature/VersionChecking.swift
@@ -14,6 +14,8 @@ public struct VersionCheck {
 }
 
 public extension VersionCheck {
+  static let unimplemented: Self = .init(verify: { _ in fatalError() })
+
   static let mock: Self = .init { $0(.upToDate) }
 
   static let live: Self = .init { completion in
diff --git a/Sources/MenuFeature/Controllers/MenuController.swift b/Sources/MenuFeature/Controllers/MenuController.swift
index 6b2cd52cd380421ab923b4fb994fbad1a02c01af..1c7623d54d4f74dd0fb30d7c51c4876c067f2db9 100644
--- a/Sources/MenuFeature/Controllers/MenuController.swift
+++ b/Sources/MenuFeature/Controllers/MenuController.swift
@@ -74,7 +74,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .scan else { return }
-          self.navigator.perform(PresentScan())
+          self.navigator.perform(PresentScan(on: self.navigationController!))
         }
       }.store(in: &cancellables)
 
@@ -86,7 +86,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .profile else { return }
-          self.navigator.perform(PresentProfile())
+          self.navigator.perform(PresentProfile(on: self.navigationController!))
         }
       }.store(in: &cancellables)
 
@@ -97,7 +97,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .scan else { return }
-          self.navigator.perform(PresentScan())
+          self.navigator.perform(PresentScan(on: self.navigationController!))
         }
       }.store(in: &cancellables)
 
@@ -108,7 +108,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .chats else { return }
-          self.navigator.perform(PresentChatList())
+          self.navigator.perform(PresentChatList(on: self.navigationController!))
         }
       }.store(in: &cancellables)
 
@@ -119,7 +119,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .contacts else { return }
-          self.navigator.perform(PresentContactList())
+          self.navigator.perform(PresentContactList(on: self.navigationController!))
         }
       }.store(in: &cancellables)
 
@@ -130,7 +130,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .settings else { return }
-          self.navigator.perform(PresentSettings())
+          self.navigator.perform(PresentSettings(on: self.navigationController!))
         }
       }.store(in: &cancellables)
 
@@ -158,7 +158,7 @@ public final class MenuController: UIViewController {
       .sink { [unowned self] in
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self, self.currentItem != .requests else { return }
-          self.navigator.perform(PresentRequests())
+          self.navigator.perform(PresentRequests(on: self.navigationController!))
         }
       }.store(in: &cancellables)
 
@@ -188,7 +188,7 @@ public final class MenuController: UIViewController {
           guard let self, self.currentItem != .share else { return }
           self.navigator.perform(PresentActivitySheet(items: [
             Localized.Menu.shareContent(self.viewModel.referralDeeplink)
-          ]))
+          ], from: self))
         }
       }.store(in: &cancellables)
 
@@ -239,6 +239,6 @@ public final class MenuController: UIViewController {
         spacingAfter: 39
       ),
       actionButton
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/NetworkMonitor/MockNetworkMonitor.swift b/Sources/NetworkMonitor/MockNetworkMonitor.swift
deleted file mode 100644
index 30bf846df9e36359ed80a7572a966e56091dce4d..0000000000000000000000000000000000000000
--- a/Sources/NetworkMonitor/MockNetworkMonitor.swift
+++ /dev/null
@@ -1,44 +0,0 @@
-import Combine
-import Foundation
-
-public struct MockNetworkMonitor: NetworkMonitoring {
-    private let statusRelay = PassthroughSubject<NetworkStatus, Never>()
-
-    public var connType: AnyPublisher<ConnectionType, Never> {
-        Just(.wifi).eraseToAnyPublisher()
-    }
-
-    public var statusPublisher: AnyPublisher<NetworkStatus, Never> {
-        statusRelay.eraseToAnyPublisher()
-    }
-
-    public var xxStatus: NetworkStatus {
-        .available
-    }
-
-    public init() {
-        // TODO
-    }
-
-    public func start() {
-        simulateOscilation(.available)
-    }
-
-    public func update(_ status: Bool) {
-        // TODO
-    }
-
-    private func simulateOscilation(_ status: NetworkStatus) {
-        statusRelay.send(status)
-
-        if status == .available {
-            DispatchQueue.main.asyncAfter(deadline: .now() + 10) {
-                simulateOscilation(.internetNotAvailable)
-            }
-        } else if status == .internetNotAvailable {
-            DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
-                simulateOscilation(.available)
-            }
-        }
-    }
-}
diff --git a/Sources/NetworkMonitor/NetworkMonitor.swift b/Sources/NetworkMonitor/NetworkMonitor.swift
deleted file mode 100644
index 84899d7eb063acaab0f862fbb1b0031fa0a32d37..0000000000000000000000000000000000000000
--- a/Sources/NetworkMonitor/NetworkMonitor.swift
+++ /dev/null
@@ -1,91 +0,0 @@
-// https://www.reddit.com/r/swift/comments/ir8wn5/network_connectivity_is_always_unsatisfied_when/
-
-import Network
-import Combine
-import XXClient
-import Foundation
-
-public enum NetworkStatus: Equatable {
-    case unknown
-    case available
-    case xxNotAvailable
-    case internetNotAvailable
-}
-
-public enum ConnectionType {
-    case wifi
-    case ethernet
-    case cellular
-    case unknown
-}
-
-public protocol NetworkMonitoring {
-    func start()
-    func update(_ status: Bool)
-
-    var xxStatus: NetworkStatus { get }
-    var connType: AnyPublisher<ConnectionType, Never> { get }
-    var statusPublisher: AnyPublisher<NetworkStatus, Never> { get }
-}
-
-public struct NetworkMonitor: NetworkMonitoring {
-    public init() {}
-
-    private var monitor = NWPathMonitor()
-    private let isXXAvailableRelay = CurrentValueSubject<Bool?, Never>(nil)
-    private let isInternetAvailableRelay = CurrentValueSubject<Bool?, Never>(nil)
-    private let connTypeSubject = PassthroughSubject<ConnectionType, Never>()
-
-    public var xxStatus: NetworkStatus {
-        isXXAvailableRelay.value == true ? .available : .xxNotAvailable
-    }
-
-    public var connType: AnyPublisher<ConnectionType, Never> {
-        connTypeSubject.eraseToAnyPublisher()
-    }
-
-    public var statusPublisher: AnyPublisher<NetworkStatus, Never> {
-        isInternetAvailableRelay.combineLatest(isXXAvailableRelay)
-            .map { (isInternetAvailable, isXXAvailable) -> NetworkStatus in
-
-                guard let isInternetAvailable = isInternetAvailable,
-                      let isXXAvailable = isXXAvailable else { return .unknown }
-
-                switch (isInternetAvailable, isXXAvailable) {
-                case (true, true):
-                    return .available
-                case (true, false):
-                    return .xxNotAvailable
-                case (false, _):
-                    return .internetNotAvailable
-                }
-            }
-            .removeDuplicates()
-            .eraseToAnyPublisher()
-    }
-
-    public func start() {
-        monitor.pathUpdateHandler = { [weak isInternetAvailableRelay, weak connTypeSubject] in
-            connTypeSubject?.send(checkConnectionTypeForPath($0))
-            isInternetAvailableRelay?.send($0.status == .satisfied)
-        }
-
-        monitor.start(queue: .global())
-    }
-
-    public func update(_ status: Bool) {
-        isXXAvailableRelay.send(status)
-    }
-
-    private func checkConnectionTypeForPath(_ path: NWPath) -> ConnectionType {
-        if path.usesInterfaceType(.wifi) {
-            return .wifi
-        } else if path.usesInterfaceType(.wiredEthernet) {
-            return .ethernet
-        } else if path.usesInterfaceType(.cellular) {
-            return .cellular
-        }
-
-        return .unknown
-    }
-}
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift b/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift
index c9b91738175c76536e88cf78b2b572ba54bcd837..05f0be5bbc98ea56a1e57ada2328382b754cb712 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingCodeController.swift
@@ -2,13 +2,15 @@ import UIKit
 import Shared
 import Combine
 import Navigation
+import AppResources
 import DrawerFeature
-import DI
+import StatusBarFeature
 import ScrollViewController
+import ComposableArchitecture
 
 public final class OnboardingCodeController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
 
   private lazy var screenView = OnboardingCodeView()
   private lazy var scrollViewController = ScrollViewController()
@@ -39,7 +41,7 @@ public final class OnboardingCodeController: UIViewController {
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = ""
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.update(.darkContent)
     navigationController?.navigationBar.customize(translucent: true)
   }
 
@@ -103,9 +105,9 @@ public final class OnboardingCodeController: UIViewController {
       .sink { [unowned self] in
         guard $0 == true else { return }
         if isEmail {
-          navigator.perform(PresentOnboardingPhone())
+          navigator.perform(PresentOnboardingPhone(on: navigationController!))
         } else {
-          navigator.perform(PresentChatList())
+          navigator.perform(PresentChatList(on: navigationController!))
         }
       }.store(in: &cancellables)
 
@@ -174,6 +176,6 @@ public final class OnboardingCodeController: UIViewController {
         actionButton,
         FlexibleSpace()
       ])
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift b/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
index ab9a453eaef6e3e0ce3274fc0108cfdb96b9f5f3..df1fc7bfebd56330f8e76f518d9ffde6769f74e7 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingEmailController.swift
@@ -2,13 +2,15 @@ import UIKit
 import Shared
 import Combine
 import Navigation
+import AppResources
 import DrawerFeature
-import DI
+import StatusBarFeature
 import ScrollViewController
+import ComposableArchitecture
 
 public final class OnboardingEmailController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
 
   private lazy var screenView = OnboardingEmailView()
   private lazy var scrollViewController = ScrollViewController()
@@ -20,7 +22,7 @@ public final class OnboardingEmailController: UIViewController {
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = " "
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.update(.darkContent)
     navigationController?.navigationBar.customize(translucent: true)
   }
 
@@ -74,7 +76,8 @@ public final class OnboardingEmailController: UIViewController {
           PresentOnboardingCode(
             isEmail: true,
             content: $0.input,
-            confirmationId: id
+            confirmationId: id,
+            on: navigationController!
           )
         )
       }.store(in: &cancellables)
@@ -99,7 +102,7 @@ public final class OnboardingEmailController: UIViewController {
       .skipButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
-        navigator.perform(PresentOnboardingPhone())
+        navigator.perform(PresentOnboardingPhone(on: navigationController!))
       }.store(in: &cancellables)
   }
 
@@ -139,6 +142,6 @@ public final class OnboardingEmailController: UIViewController {
         actionButton,
         FlexibleSpace()
       ])
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift b/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
index c2d4aeba4f30aa7bd74aca903b0093f99790330f..0f4eebf87044c777e9af241523077fd1634f1d82 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingPhoneController.swift
@@ -2,13 +2,15 @@ import UIKit
 import Shared
 import Combine
 import Navigation
+import AppResources
 import DrawerFeature
-import DI
+import StatusBarFeature
 import ScrollViewController
+import ComposableArchitecture
 
 public final class OnboardingPhoneController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
 
   private lazy var screenView = OnboardingPhoneView()
   private lazy var scrollViewController = ScrollViewController()
@@ -20,7 +22,7 @@ public final class OnboardingPhoneController: UIViewController {
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = ""
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.update(.darkContent)
     navigationController?.navigationBar.customize(translucent: true)
   }
 
@@ -84,7 +86,7 @@ public final class OnboardingPhoneController: UIViewController {
       .skipButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
-        navigator.perform(PresentChatList())
+        navigator.perform(PresentChatList(on: navigationController!))
       }.store(in: &cancellables)
 
     screenView
@@ -96,7 +98,7 @@ public final class OnboardingPhoneController: UIViewController {
           guard let self else { return }
           self.navigator.perform(DismissModal(from: self))
           self.viewModel.didChooseCountry($0 as! Country)
-        }))
+        }, from: self))
       }.store(in: &cancellables)
 
     viewModel
@@ -109,7 +111,8 @@ public final class OnboardingPhoneController: UIViewController {
           PresentOnboardingCode(
             isEmail: false,
             content: content,
-            confirmationId: id
+            confirmationId: id,
+            on: navigationController!
           )
         )
       }.store(in: &cancellables)
@@ -161,6 +164,6 @@ public final class OnboardingPhoneController: UIViewController {
         actionButton,
         FlexibleSpace()
       ])
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift b/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
index 7cb3faf0f4c1b305f6c203ece1d58cad36be9b0f..4e09d6b6609e27454822912e2b844bf8b3e4aa1b 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingStartController.swift
@@ -1,10 +1,10 @@
 import UIKit
 import Combine
 import Navigation
-import DI
+import ComposableArchitecture
 
 public final class OnboardingStartController: UIViewController {
-  @Dependency var navigator: Navigator
+  @Dependency(\.navigator) var navigator: Navigator
 
   private lazy var screenView = OnboardingStartView()
 
@@ -45,7 +45,7 @@ public final class OnboardingStartController: UIViewController {
       .startButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
-        navigator.perform(PresentTermsAndConditions())
+        navigator.perform(PresentTermsAndConditions(replacing: false, on: navigationController!))
       }.store(in: &cancellables)
   }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift b/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
index 0f192fbb0228682593621a3935acb3b41abd227b..42f4f18981fabb12a44713d22f2904a4e831af54 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingUsernameController.swift
@@ -2,13 +2,15 @@ import UIKit
 import Shared
 import Combine
 import Navigation
+import AppResources
 import DrawerFeature
-import DI
+import StatusBarFeature
 import ScrollViewController
+import ComposableArchitecture
 
 public final class OnboardingUsernameController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
 
   private lazy var screenView = OnboardingUsernameView()
   private lazy var scrollViewController = ScrollViewController()
@@ -20,7 +22,7 @@ public final class OnboardingUsernameController: UIViewController {
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
     navigationItem.backButtonTitle = ""
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.update(.darkContent)
     navigationController?.navigationBar.customize(translucent: true)
   }
 
@@ -65,7 +67,7 @@ public final class OnboardingUsernameController: UIViewController {
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentRestoreList())
+        navigator.perform(PresentRestoreList(on: navigationController!))
       }.store(in: &cancellables)
 
     screenView
@@ -91,7 +93,7 @@ public final class OnboardingUsernameController: UIViewController {
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
         guard $0.didConfirm == true else { return }
-        navigator.perform(PresentOnboardingWelcome())
+        navigator.perform(PresentOnboardingWelcome(on: navigationController!))
       }.store(in: &cancellables)
 
     viewModel
@@ -140,6 +142,6 @@ public final class OnboardingUsernameController: UIViewController {
         actionButton,
         FlexibleSpace()
       ])
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift b/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
index 937524257df145b571957b51972c297b4ab679a1..09a9221ba5765e85d92a9626b41377566a0977c2 100644
--- a/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
+++ b/Sources/OnboardingFeature/Controllers/OnboardingWelcomeController.swift
@@ -3,12 +3,15 @@ import Shared
 import Combine
 import Defaults
 import Navigation
+import AppResources
 import DrawerFeature
-import DI
+import StatusBarFeature
+import ComposableArchitecture
 
 public final class OnboardingWelcomeController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
+  @Dependency(\.navigator) var navigator: Navigator
+  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
+
   @KeyObject(.username, defaultValue: "") var username: String
 
   private lazy var screenView = OnboardingWelcomeView()
@@ -22,7 +25,7 @@ public final class OnboardingWelcomeController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    barStylist.styleSubject.send(.darkContent)
+    statusBar.update(.darkContent)
     navigationController?.navigationBar.customize(translucent: true)
   }
 
@@ -35,14 +38,14 @@ public final class OnboardingWelcomeController: UIViewController {
       .continueButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
-        navigator.perform(PresentOnboardingEmail())
+        navigator.perform(PresentOnboardingEmail(on: navigationController!))
       }.store(in: &cancellables)
 
     screenView
       .skipButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
-        navigator.perform(PresentChatList())
+        navigator.perform(PresentChatList(on: navigationController!))
       }.store(in: &cancellables)
 
     screenView.didTapInfo = { [weak self] in
@@ -91,6 +94,6 @@ public final class OnboardingWelcomeController: UIViewController {
         actionButton,
         FlexibleSpace()
       ])
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/OnboardingFeature/OnboardingDependencies.swift b/Sources/OnboardingFeature/OnboardingDependencies.swift
new file mode 100644
index 0000000000000000000000000000000000000000..fe3dce7f61997d7fc4b4d80d2d4b20caf358bcf4
--- /dev/null
+++ b/Sources/OnboardingFeature/OnboardingDependencies.swift
@@ -0,0 +1,91 @@
+import Navigation
+import Dependencies
+
+private enum NavigatorKey: DependencyKey {
+  static let liveValue: Navigator = CombinedNavigator.core
+  static let testValue: Navigator = UnimplementedNavigator()
+}
+
+extension DependencyValues {
+  var navigator: Navigator {
+    get { self[NavigatorKey.self] }
+    set { self[NavigatorKey.self] = newValue }
+  }
+}
+
+import UIKit
+import XCTestDynamicOverlay
+import ComposableArchitecture
+
+public struct PresentStep: Navigation.Action, Equatable {
+  public init(viewController: UIViewController, from: UIViewController) {
+    self.viewController = viewController
+    self.from = from
+  }
+
+  public var viewController: UIViewController
+  public var from: UIViewController
+}
+
+struct PresentStepNavigator: Navigation.TypedNavigator {
+  @Dependency(\.navigator) var navigator
+
+  func perform(_ action: PresentStep, completion: @escaping () -> Void) {
+    guard let navigationController = action.from.navigationController else {
+      completion()
+      return
+    }
+    navigator.perform(
+      SetStack(
+        navigationController.viewControllers + [action.viewController],
+        on: navigationController
+      ),
+      completion: completion
+    )
+  }
+}
+
+public struct DismissToStep: Navigation.Action, Equatable {
+  public init(viewController: UIViewController) {
+    self.viewController = viewController
+  }
+
+  public var viewController: UIViewController
+}
+
+struct DismissToStepNavigator: Navigation.TypedNavigator {
+  @Dependency(\.navigator) var navigator
+
+  func perform(_ action: DismissToStep, completion: @escaping () -> Void) {
+    guard let navigationController = action.viewController.navigationController else {
+      completion()
+      return
+    }
+    navigator.perform(
+      PopTo(action.viewController, on: navigationController),
+      completion: completion
+    )
+  }
+}
+
+extension CombinedNavigator {
+  public static let core = CombinedNavigator(
+    SetStackNavigator(),
+    PopToNavigator(),
+    PresentStepNavigator(),
+    DismissToStepNavigator()
+  )
+}
+
+public struct UnimplementedNavigator: Navigator {
+  public init() {}
+
+  public func perform(_ action: Navigation.Action, completion: @escaping () -> Void) {
+    XCTestDynamicOverlay.XCTFail("UnimplementedNavigator.perform not implemented")
+  }
+
+  public func canPerform(_ action: Action) -> Bool {
+    XCTestDynamicOverlay.XCTFail("UnimplementedNavigator.canPerform not implemented")
+    return false
+  }
+}
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingCodeViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingCodeViewModel.swift
index 35dc2c9934294e5e245e77627e0257da4f1b8420..994b83b211a75eeb4bafb4e95ec683e263325881 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingCodeViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingCodeViewModel.swift
@@ -1,3 +1,4 @@
+import AppCore
 import Shared
 import Combine
 import Defaults
@@ -6,7 +7,7 @@ import InputField
 import Foundation
 import CombineSchedulers
 import XXMessengerClient
-import DI
+import ComposableArchitecture
 
 final class OnboardingCodeViewModel {
   struct ViewState: Equatable {
@@ -20,8 +21,10 @@ final class OnboardingCodeViewModel {
     stateSubject.eraseToAnyPublisher()
   }
 
-  @Dependency var messenger: Messenger
-  @Dependency var hudController: HUDController
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
+  @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
+
   @KeyObject(.email, defaultValue: nil) var email: String?
   @KeyObject(.phone, defaultValue: nil) var phone: String?
 
@@ -30,7 +33,6 @@ final class OnboardingCodeViewModel {
   private let content: String
   private let confirmationId: String
   private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
-  private var scheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
 
   init(
     isEmail: Bool,
@@ -61,8 +63,8 @@ final class OnboardingCodeViewModel {
   }
 
   func didTapNext() {
-    hudController.show()
-    scheduler.schedule { [weak self] in
+    hudManager.show()
+    bgQueue.schedule { [weak self] in
       guard let self else { return }
       do {
         try self.messenger.ud.get()!.confirmFact(
@@ -75,10 +77,10 @@ final class OnboardingCodeViewModel {
           self.phone = self.content
         }
         self.timer?.invalidate()
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.stateSubject.value.didConfirm = true
       } catch {
-        self.hudController.dismiss()
+        self.hudManager.hide()
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
         self.stateSubject.value.status = .invalid(xxError)
       }
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift
index 6d3295db39a175da6be05464ee573fed622c8ec8..a175a674fa981f7d48cf2409c8d84041f60da5dc 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingEmailViewModel.swift
@@ -1,3 +1,4 @@
+import AppCore
 import Shared
 import Combine
 import XXClient
@@ -5,7 +6,7 @@ import InputField
 import Foundation
 import CombineSchedulers
 import XXMessengerClient
-import DI
+import ComposableArchitecture
 
 final class OnboardingEmailViewModel {
   struct ViewState: Equatable {
@@ -14,15 +15,15 @@ final class OnboardingEmailViewModel {
     var status: InputField.ValidationStatus = .unknown(nil)
   }
 
-  @Dependency var messenger: Messenger
-  @Dependency var hudController: HUDController
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
+  @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
 
   var statePublisher: AnyPublisher<ViewState, Never> {
     stateSubject.eraseToAnyPublisher()
   }
 
   private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
-  private var scheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
 
   func clearUp() {
     stateSubject.value.confirmationId = nil
@@ -34,17 +35,17 @@ final class OnboardingEmailViewModel {
   }
 
   func didTapNext() {
-    hudController.show()
-    scheduler.schedule { [weak self] in
+    hudManager.show()
+    bgQueue.schedule { [weak self] in
       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.hudManager.hide()
         self.stateSubject.value.confirmationId = confirmationId
       } catch {
-        self.hudController.dismiss()
+        self.hudManager.hide()
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
         self.stateSubject.value.status = .invalid(xxError)
       }
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift
index bc6550f01c10bab35c4928faa2b5aa4e4835e343..39d9f282be5757d19bc7ef47ff450dcfd2d1f48e 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingPhoneViewModel.swift
@@ -1,12 +1,13 @@
+import AppCore
 import Shared
 import Combine
 import XXClient
-import Countries
 import InputField
 import Foundation
 import CombineSchedulers
 import XXMessengerClient
-import DI
+import CountryListFeature
+import ComposableArchitecture
 
 final class OnboardingPhoneViewModel {
   struct ViewState: Equatable {
@@ -17,15 +18,15 @@ final class OnboardingPhoneViewModel {
     var country: Country = .fromMyPhone()
   }
 
-  @Dependency var messenger: Messenger
-  @Dependency var hudController: HUDController
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
+  @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
 
   var statePublisher: AnyPublisher<ViewState, Never> {
     stateSubject.eraseToAnyPublisher()
   }
 
   private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
-  private var scheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
 
   func clearUp() {
     stateSubject.value.confirmationId = nil
@@ -42,19 +43,19 @@ final class OnboardingPhoneViewModel {
   }
 
   func didTapNext() {
-    hudController.show()
-    scheduler.schedule { [weak self] in
+    hudManager.show()
+    bgQueue.schedule { [weak self] in
       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(
           .init(type: .phone, value: content)
         )
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.stateSubject.value.content = content
         self.stateSubject.value.confirmationId = confirmationId
       } catch {
-        self.hudController.dismiss()
+        self.hudManager.hide()
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
         self.stateSubject.value.status = .invalid(xxError)
       }
diff --git a/Sources/OnboardingFeature/ViewModels/OnboardingUsernameViewModel.swift b/Sources/OnboardingFeature/ViewModels/OnboardingUsernameViewModel.swift
index 051e97838eda2756e8772f6600b2936ae6389995..917e9fea3bcd5f21227f5a285ceafe620b271e9f 100644
--- a/Sources/OnboardingFeature/ViewModels/OnboardingUsernameViewModel.swift
+++ b/Sources/OnboardingFeature/ViewModels/OnboardingUsernameViewModel.swift
@@ -1,3 +1,4 @@
+import AppCore
 import Shared
 import Combine
 import Defaults
@@ -6,8 +7,7 @@ import XXClient
 import InputField
 import Foundation
 import XXMessengerClient
-import CombineSchedulers
-import DI
+import ComposableArchitecture
 
 final class OnboardingUsernameViewModel {
   struct ViewState: Equatable {
@@ -16,9 +16,11 @@ final class OnboardingUsernameViewModel {
     var didConfirm: Bool = false
   }
 
-  @Dependency var database: Database
-  @Dependency var messenger: Messenger
-  @Dependency var hudController: HUDController
+  @Dependency(\.app.dbManager) var dbManager: DBManager
+  @Dependency(\.app.messenger) var messenger: Messenger
+  @Dependency(\.app.hudManager) var hudManager: HUDManager
+  @Dependency(\.app.bgQueue) var bgQueue: AnySchedulerOf<DispatchQueue>
+
   @KeyObject(.username, defaultValue: "") var username: String
 
   var statePublisher: AnyPublisher<ViewState, Never> {
@@ -26,7 +28,6 @@ final class OnboardingUsernameViewModel {
   }
 
   private let stateSubject = CurrentValueSubject<ViewState, Never>(.init())
-  private var scheduler: AnySchedulerOf<DispatchQueue> = DispatchQueue.global().eraseToAnyScheduler()
 
   func didInput(_ string: String) {
     stateSubject.value.input = string.trimmingCharacters(in: .whitespacesAndNewlines)
@@ -39,14 +40,14 @@ final class OnboardingUsernameViewModel {
   }
 
   func didTapRegister() {
-    hudController.show()
-    scheduler.schedule { [weak self] in
+    hudManager.show()
+    bgQueue.schedule { [weak self] in
       guard let self else { return }
       do {
         try self.messenger.register(
           username: self.stateSubject.value.input
         )
-        try self.database.saveContact(.init(
+        try self.dbManager.getDB().saveContact(.init(
           id: self.messenger.e2e.get()!.getContact().getId(),
           marshaled: self.messenger.e2e.get()!.getContact().data,
           username: self.stateSubject.value.input,
@@ -61,10 +62,10 @@ final class OnboardingUsernameViewModel {
           createdAt: Date()
         ))
         self.username = self.stateSubject.value.input
-        self.hudController.dismiss()
+        self.hudManager.hide()
         self.stateSubject.value.didConfirm = true
       } catch {
-        self.hudController.dismiss()
+        self.hudManager.hide()
         let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
         self.stateSubject.value.status = .invalid(xxError)
       }
diff --git a/Sources/OnboardingFeature/Views/OnboardingCodeView.swift b/Sources/OnboardingFeature/Views/OnboardingCodeView.swift
index 9f4b48d5385f69a7de78f0be828494829dbd2751..63a33f1bdcfe95b33f9335f32f3358bdbe3d354c 100644
--- a/Sources/OnboardingFeature/Views/OnboardingCodeView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingCodeView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
 final class OnboardingCodeView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/OnboardingFeature/Views/OnboardingEmailView.swift b/Sources/OnboardingFeature/Views/OnboardingEmailView.swift
index c681215e691626cdb694b16f229f6c4065e134a2..e98117828c9de253fe169b3cb4e9a8fff67e92d1 100644
--- a/Sources/OnboardingFeature/Views/OnboardingEmailView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingEmailView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
 final class OnboardingEmailView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/OnboardingFeature/Views/OnboardingPhoneConfirmationView.swift b/Sources/OnboardingFeature/Views/OnboardingPhoneConfirmationView.swift
index 8caa27679273d4ab0485e6d8254723e78fbb31c7..45584a61af46433c46833141b1cae00a00333275 100644
--- a/Sources/OnboardingFeature/Views/OnboardingPhoneConfirmationView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingPhoneConfirmationView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
 final class OnboardingPhoneConfirmationView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/OnboardingFeature/Views/OnboardingPhoneView.swift b/Sources/OnboardingFeature/Views/OnboardingPhoneView.swift
index a8df7c864d75041a34c23863595150dcda094ecc..f36c635ef4e0706297a6b40d328e9a387d3e556f 100644
--- a/Sources/OnboardingFeature/Views/OnboardingPhoneView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingPhoneView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
 final class OnboardingPhoneView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/OnboardingFeature/Views/OnboardingStartView.swift b/Sources/OnboardingFeature/Views/OnboardingStartView.swift
index 2a83c1b6aa004c3ca068ff27b419212ea9353480..b0864bb32bb8bdd4557b0a677df73068e5c747d5 100644
--- a/Sources/OnboardingFeature/Views/OnboardingStartView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingStartView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class OnboardingStartView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/OnboardingFeature/Views/OnboardingUsernameRestoreView.swift b/Sources/OnboardingFeature/Views/OnboardingUsernameRestoreView.swift
index 170d0a6344239781af13acd2835c5fa4519d9569..7a418f71686b90456b03f24af3f4165d416bd7a8 100644
--- a/Sources/OnboardingFeature/Views/OnboardingUsernameRestoreView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingUsernameRestoreView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class OnboardingUsernameRestoreView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/OnboardingFeature/Views/OnboardingUsernameView.swift b/Sources/OnboardingFeature/Views/OnboardingUsernameView.swift
index 7bd6e1026563d5a7de6fb17dce7e6a872b5c473d..8f5bf92b6a34377960f449c2d0a77aab28b3225c 100644
--- a/Sources/OnboardingFeature/Views/OnboardingUsernameView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingUsernameView.swift
@@ -1,6 +1,7 @@
 import UIKit
 import Shared
 import InputField
+import AppResources
 
 final class OnboardingUsernameView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/OnboardingFeature/Views/OnboardingWelcomeView.swift b/Sources/OnboardingFeature/Views/OnboardingWelcomeView.swift
index ae4b5a609864ffdeed59ddc164ca303eeb474a7a..2daddf4b716a515abe8d17c61e9f6e2ee464aa6f 100644
--- a/Sources/OnboardingFeature/Views/OnboardingWelcomeView.swift
+++ b/Sources/OnboardingFeature/Views/OnboardingWelcomeView.swift
@@ -1,5 +1,6 @@
 import UIKit
 import Shared
+import AppResources
 
 final class OnboardingWelcomeView: UIView {
   let titleLabel = UILabel()
diff --git a/Sources/Permissions/MockPermissionHandler.swift b/Sources/Permissions/MockPermissionHandler.swift
deleted file mode 100644
index d43dd9f1907f0faa671980f3ae0290828c0fc10d..0000000000000000000000000000000000000000
--- a/Sources/Permissions/MockPermissionHandler.swift
+++ /dev/null
@@ -1,38 +0,0 @@
-import AVFoundation
-
-public class MockPermissionHandler: PermissionHandling {
-    private var cameraStatus = false
-    private var photosStatus = false
-    private var biometricsStatus = false
-    private var microphoneStatus = false
-
-    public init() {}
-
-    public var isCameraAllowed: Bool { cameraStatus }
-
-    public var isPhotosAllowed: Bool { photosStatus }
-
-    public var isMicrophoneAllowed: Bool { microphoneStatus }
-
-    public var isBiometricsAvailable: Bool { biometricsStatus }
-
-    public func requestBiometrics(_ completion: @escaping (Result<Bool, Error>) -> Void) {
-        biometricsStatus = true
-        completion(.success(true))
-    }
-
-    public func requestCamera(_ completion: @escaping (Bool) -> Void) {
-        cameraStatus = true
-        completion(true)
-    }
-
-    public func requestMicrophone(_ completion: @escaping (Bool) -> Void) {
-        microphoneStatus = true
-        completion(true)
-    }
-
-    public func requestPhotos(_ completion: @escaping (Bool) -> Void) {
-        photosStatus = true
-        completion(true)
-    }
-}
diff --git a/Sources/Permissions/PermissionHandler.swift b/Sources/Permissions/PermissionHandler.swift
deleted file mode 100644
index 762a217f121daf85b61a172782ebef12dc8d6c21..0000000000000000000000000000000000000000
--- a/Sources/Permissions/PermissionHandler.swift
+++ /dev/null
@@ -1,68 +0,0 @@
-import Photos
-import AVFoundation
-import LocalAuthentication
-
-public protocol PermissionHandling {
-    var isCameraAllowed: Bool { get }
-    var isPhotosAllowed: Bool { get }
-    var isMicrophoneAllowed: Bool { get }
-    var isBiometricsAvailable: Bool { get }
-
-    func requestPhotos(_: @escaping (Bool) -> Void)
-    func requestCamera(_: @escaping (Bool) -> Void)
-    func requestMicrophone(_: @escaping (Bool) -> Void)
-    func requestBiometrics(_: @escaping (Result<Bool, Error>) -> Void)
-}
-
-public struct PermissionHandler: PermissionHandling {
-    public init() {}
-
-    public var isMicrophoneAllowed: Bool {
-        AVAudioSession.sharedInstance().recordPermission == .granted
-    }
-
-    public var isCameraAllowed: Bool {
-        AVCaptureDevice.authorizationStatus(for: .video) ==  .authorized
-    }
-
-    public var isPhotosAllowed: Bool {
-        PHPhotoLibrary.authorizationStatus() == .authorized
-    }
-
-    public var isBiometricsAvailable: Bool {
-        var error: NSError?
-        let context = LAContext()
-
-        if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) == true {
-            return true
-        } else {
-            let tooManyAttempts = LAError.Code.biometryLockout.rawValue
-            guard let error = error, error.code == tooManyAttempts else { return true }
-            return false
-        }
-    }
-
-    public func requestBiometrics(_ completion: @escaping (Result<Bool, Error>) -> Void) {
-        let reason = "Authentication is required to use xx messenger"
-        LAContext().evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason, reply: { success, error in
-            guard let error = error else {
-                completion(.success(success))
-                return
-            }
-
-            completion(.failure(error))
-        })
-    }
-
-    public func requestCamera(_ completion: @escaping (Bool) -> Void) {
-        AVCaptureDevice.requestAccess(for: .video, completionHandler: completion)
-    }
-
-    public func requestMicrophone(_ completion: @escaping (Bool) -> Void) {
-        AVAudioSession.sharedInstance().requestRecordPermission(completion)
-    }
-
-    public func requestPhotos(_ completion: @escaping (Bool) -> Void) {
-        PHPhotoLibrary.requestAuthorization { completion($0 == .authorized) }
-    }
-}
diff --git a/Sources/Permissions/RequestPermissionView.swift b/Sources/Permissions/RequestPermissionView.swift
deleted file mode 100644
index 52fd14da4f3d250ee5e8be9c9dd1efce9cd21e3a..0000000000000000000000000000000000000000
--- a/Sources/Permissions/RequestPermissionView.swift
+++ /dev/null
@@ -1,106 +0,0 @@
-import UIKit
-import Shared
-
-final class RequestPermissionView: UIView {
-    let titleLabel = UILabel()
-    let iconImage = UIImageView()
-    let subtitleLabel = UILabel()
-    let littleLogo = UIImageView()
-    private(set) var notNowButton = UIButton()
-    private(set) var continueButton = CapsuleButton()
-
-    init() {
-        super.init(frame: .zero)
-        setup()
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    func setup(title: String, subtitle: String, image: UIImage) {
-        iconImage.image = image
-        titleLabel.text = title
-
-        let paragraph = NSMutableParagraphStyle()
-        paragraph.lineHeightMultiple = 1.5
-        paragraph.alignment = .center
-
-        subtitleLabel.attributedText = NSAttributedString(
-            string: subtitle,
-            attributes: [
-                .paragraphStyle: paragraph,
-                .font: Fonts.Mulish.regular.font(size: 14.0),
-                .foregroundColor: Asset.neutralBody.color,
-            ]
-        )
-    }
-
-    private func setup() {
-        littleLogo.image = Asset.permissionLogo.image
-        notNowButton.setTitle(Localized.Chat.Actions.Permission.notnow, for: .normal)
-        continueButton.set(style: .brandColored, title: Localized.Chat.Actions.Permission.continue)
-
-        titleLabel.textAlignment = .center
-
-        backgroundColor = Asset.neutralWhite.color
-        titleLabel.textColor = Asset.neutralActive.color
-        notNowButton.setTitleColor(Asset.neutralWeak.color, for: .normal)
-
-        subtitleLabel.numberOfLines = 0
-
-        titleLabel.font = Fonts.Mulish.bold.font(size: 24.0)
-        notNowButton.titleLabel?.font = Fonts.Mulish.semiBold.font(size: 16)
-
-        let actionsContainer = UIView()
-        actionsContainer.addSubview(continueButton)
-        actionsContainer.addSubview(notNowButton)
-
-        addSubview(iconImage)
-        addSubview(titleLabel)
-        addSubview(littleLogo)
-        addSubview(subtitleLabel)
-        addSubview(actionsContainer)
-
-        iconImage.snp.makeConstraints { make in
-            make.centerX.equalToSuperview()
-        }
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalTo(iconImage.snp.bottom).offset(34)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-        }
-
-        subtitleLabel.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(8)
-            make.left.equalToSuperview().offset(32)
-            make.right.equalToSuperview().offset(-32)
-            make.bottom.equalTo(snp.centerY)
-        }
-
-        littleLogo.snp.makeConstraints { make in
-            make.centerX.equalToSuperview()
-            make.bottom.equalTo(safeAreaLayoutGuide).offset(-15)
-        }
-
-        actionsContainer.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualTo(subtitleLabel.snp.bottom)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.lessThanOrEqualTo(littleLogo.snp.top)
-        }
-
-        continueButton.snp.makeConstraints { make in
-            make.top.greaterThanOrEqualToSuperview()
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-            make.bottom.equalTo(actionsContainer.snp.centerY).offset(-5)
-        }
-
-        notNowButton.snp.makeConstraints { make in
-            make.top.equalTo(actionsContainer.snp.centerY).offset(5)
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-            make.bottom.lessThanOrEqualToSuperview()
-        }
-    }
-}
diff --git a/Sources/PermissionsFeature/PermissionBiometrics.swift b/Sources/PermissionsFeature/PermissionBiometrics.swift
new file mode 100644
index 0000000000000000000000000000000000000000..066d835af9b179233a89bc9bcebf57d8ce5a3fe4
--- /dev/null
+++ b/Sources/PermissionsFeature/PermissionBiometrics.swift
@@ -0,0 +1,65 @@
+import LocalAuthentication
+import XCTestDynamicOverlay
+
+public struct PermissionBiometrics {
+  public var status: PermissionBiometricsStatus
+  public var request: PermissionBiometricsRequest
+
+  public static let live = PermissionBiometrics(
+    status: .live,
+    request: .live
+  )
+  public static let unimplemented = PermissionBiometrics(
+    status: .unimplemented,
+    request: .unimplemented
+  )
+}
+
+public struct PermissionBiometricsStatus {
+  public var run: () -> Bool
+
+  public func callAsFunction() -> Bool {
+    run()
+  }
+
+  public static let live = PermissionBiometricsStatus {
+    var error: NSError?
+    let context = LAContext()
+
+    if context.canEvaluatePolicy(.deviceOwnerAuthentication, error: &error) == true {
+      return true
+    } else {
+      let tooManyAttempts = LAError.Code.biometryLockout.rawValue
+      guard let error = error, error.code == tooManyAttempts else { return true }
+      return false
+    }
+  }
+
+  public static let unimplemented = PermissionBiometricsStatus(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
+
+public struct PermissionBiometricsRequest {
+  public var run: (@escaping (Bool) -> Void) -> Void
+
+  public func callAsFunction(_ completion: @escaping (Bool) -> Void) -> Void {
+    run(completion)
+  }
+
+  public static let live = PermissionBiometricsRequest { completion in
+    let reason = "Authentication is required to use xx messenger"
+    LAContext().evaluatePolicy(.deviceOwnerAuthentication, localizedReason: reason) { success, error in
+      if let error {
+        completion(false)
+        return
+      }
+
+      completion(success)
+    }
+  }
+
+  public static let unimplemented = PermissionBiometricsRequest(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/PermissionsFeature/PermissionCamera.swift b/Sources/PermissionsFeature/PermissionCamera.swift
new file mode 100644
index 0000000000000000000000000000000000000000..1c4e263087b5428af0f7d85a54b00f83a072f71c
--- /dev/null
+++ b/Sources/PermissionsFeature/PermissionCamera.swift
@@ -0,0 +1,48 @@
+import AVFoundation
+import XCTestDynamicOverlay
+
+public struct PermissionCamera {
+  public var status: PermissionCameraStatus
+  public var request: PermissionCameraRequest
+
+  public static let live = PermissionCamera(
+    status: .live,
+    request: .live
+  )
+  public static let unimplemented = PermissionCamera(
+    status: .unimplemented,
+    request: .unimplemented
+  )
+}
+
+public struct PermissionCameraStatus {
+  public var run: () -> Bool
+
+  public func callAsFunction() -> Bool {
+    run()
+  }
+
+  public static let live = PermissionCameraStatus {
+    AVCaptureDevice.authorizationStatus(for: .video) == .authorized
+  }
+
+  public static let unimplemented = PermissionCameraStatus(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
+
+public struct PermissionCameraRequest {
+  public var run: (@escaping (Bool) -> Void) -> Void
+
+  public func callAsFunction(_ completion: @escaping (Bool) -> Void) -> Void {
+    run(completion)
+  }
+
+  public static let live = PermissionCameraRequest {
+    AVCaptureDevice.requestAccess(for: .video, completionHandler: $0)
+  }
+
+  public static let unimplemented = PermissionCameraRequest(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/PermissionsFeature/PermissionLibrary.swift b/Sources/PermissionsFeature/PermissionLibrary.swift
new file mode 100644
index 0000000000000000000000000000000000000000..485a666f58a7a6c04ff3cd425454798c6c711eda
--- /dev/null
+++ b/Sources/PermissionsFeature/PermissionLibrary.swift
@@ -0,0 +1,48 @@
+import Photos
+import XCTestDynamicOverlay
+
+public struct PermissionLibrary {
+  public var status: PermissionLibraryStatus
+  public var request: PermissionLibraryRequest
+
+  public static let live = PermissionLibrary(
+    status: .live,
+    request: .live
+  )
+  public static let unimplemented = PermissionLibrary(
+    status: .unimplemented,
+    request: .unimplemented
+  )
+}
+
+public struct PermissionLibraryStatus {
+  public var run: () -> Bool
+
+  public func callAsFunction() -> Bool {
+    run()
+  }
+
+  public static let live = PermissionLibraryStatus {
+    PHPhotoLibrary.authorizationStatus() == .authorized
+  }
+
+  public static let unimplemented = PermissionLibraryStatus(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
+
+public struct PermissionLibraryRequest {
+  public var run: (@escaping (Bool) -> Void) -> Void
+
+  public func callAsFunction(_ completion: @escaping (Bool) -> Void) -> Void {
+    run(completion)
+  }
+
+  public static let live = PermissionLibraryRequest { completion in
+    PHPhotoLibrary.requestAuthorization { completion($0 == .authorized) }
+  }
+
+  public static let unimplemented = PermissionLibraryRequest(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/PermissionsFeature/PermissionMicrophone.swift b/Sources/PermissionsFeature/PermissionMicrophone.swift
new file mode 100644
index 0000000000000000000000000000000000000000..0f5727837cbea30f05d920156d1dfd155f2f6bd4
--- /dev/null
+++ b/Sources/PermissionsFeature/PermissionMicrophone.swift
@@ -0,0 +1,56 @@
+import AVFoundation
+import XCTestDynamicOverlay
+
+public struct PermissionMicrophone {
+  public var status: PermissionMicrophoneStatus
+  public var request: PermissionMicrophoneRequest
+
+  public static let live = PermissionMicrophone(
+    status: .live,
+    request: .live
+  )
+  public static let unimplemented = PermissionMicrophone(
+    status: .unimplemented,
+    request: .unimplemented
+  )
+}
+
+public struct PermissionMicrophoneRequest {
+  public var run: (@escaping (Bool) -> Void) -> Void
+
+  public func callAsFunction(_ completion: @escaping (Bool) -> Void) -> Void {
+    run(completion)
+  }
+}
+
+extension PermissionMicrophoneRequest {
+  public static let live = PermissionMicrophoneRequest {
+    AVAudioSession.sharedInstance().requestRecordPermission($0)
+  }
+}
+
+extension PermissionMicrophoneRequest {
+  public static let unimplemented = PermissionMicrophoneRequest(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
+
+public struct PermissionMicrophoneStatus {
+  public var run: () -> Bool
+
+  public func callAsFunction() -> Bool {
+    run()
+  }
+}
+
+extension PermissionMicrophoneStatus {
+  public static let live = PermissionMicrophoneStatus {
+    AVAudioSession.sharedInstance().recordPermission == .granted
+  }
+}
+
+extension PermissionMicrophoneStatus {
+  public static let unimplemented = PermissionMicrophoneStatus(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/PermissionsFeature/PermissionType.swift b/Sources/PermissionsFeature/PermissionType.swift
new file mode 100644
index 0000000000000000000000000000000000000000..93b8ba3906708b240dc45fb39bbca98173ae0495
--- /dev/null
+++ b/Sources/PermissionsFeature/PermissionType.swift
@@ -0,0 +1,5 @@
+public enum PermissionType: Int {
+  case camera
+  case library
+  case microphone
+}
diff --git a/Sources/PermissionsFeature/PermissionsManager.swift b/Sources/PermissionsFeature/PermissionsManager.swift
new file mode 100644
index 0000000000000000000000000000000000000000..89fd4b377e122725bd112bc4a1fdc3c760688a61
--- /dev/null
+++ b/Sources/PermissionsFeature/PermissionsManager.swift
@@ -0,0 +1,33 @@
+public struct PermissionsManager {
+  public var camera: PermissionCamera
+  public var library: PermissionLibrary
+  public var microphone: PermissionMicrophone
+  public var biometrics: PermissionBiometrics
+
+  public static let live = PermissionsManager(
+    camera: .live,
+    library: .live,
+    microphone: .live,
+    biometrics: .live
+  )
+  public static let unimplemented = PermissionsManager(
+    camera: .unimplemented,
+    library: .unimplemented,
+    microphone: .unimplemented,
+    biometrics: .unimplemented
+  )
+}
+
+import Dependencies
+
+private enum PermissionsDependencyKey: DependencyKey {
+  static let liveValue: PermissionsManager = .live
+  static let testValue: PermissionsManager = .unimplemented
+}
+
+extension DependencyValues {
+  public var permissions: PermissionsManager {
+    get { self[PermissionsDependencyKey.self] }
+    set { self[PermissionsDependencyKey.self] = newValue }
+  }
+}
diff --git a/Sources/Presentation/BottomPresenter.swift b/Sources/Presentation/BottomPresenter.swift
deleted file mode 100644
index d4d5778b09e00ffaedb3357b1d621f6017da339a..0000000000000000000000000000000000000000
--- a/Sources/Presentation/BottomPresenter.swift
+++ /dev/null
@@ -1,33 +0,0 @@
-import UIKit
-
-public final class BottomPresenter: NSObject, Presenting {
-    private var transition: BottomTransition?
-    
-    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
-extension BottomPresenter: UIViewControllerTransitioningDelegate {
-    public func animationController(forPresented presented: UIViewController,
-                                    presenting: UIViewController,
-                                    source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
-        transition = BottomTransition(onDismissal: { [weak self] in
-            self?.transition = nil
-        })
-        
-        return transition
-    }
-    
-    public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
-        transition?.direction = .dismiss
-        return transition
-    }
-}
diff --git a/Sources/Presentation/BottomTransition.swift b/Sources/Presentation/BottomTransition.swift
deleted file mode 100644
index 28f41a490b2607e813ecd9123b373b673e579da2..0000000000000000000000000000000000000000
--- a/Sources/Presentation/BottomTransition.swift
+++ /dev/null
@@ -1,122 +0,0 @@
-import UIKit
-import Combine
-import SnapKit
-import Shared
-
-final class BottomTransition: NSObject, UIViewControllerAnimatedTransitioning {
-    enum Direction {
-        case present
-        case dismiss
-    }
-
-    var direction: Direction = .present
-    private let onDismissal: EmptyClosure
-    private weak var darkOverlayView: UIControl?
-    private weak var topConstraint: Constraint?
-    private weak var bottomConstraint: Constraint?
-    private var cancellables = Set<AnyCancellable>()
-
-    private var presentedConstraints: [NSLayoutConstraint] = []
-    private var dismissedConstraints: [NSLayoutConstraint] = []
-
-    init(onDismissal: @escaping EmptyClosure) {
-        self.onDismissal = onDismissal
-        super.init()
-    }
-
-    func transitionDuration(using context: UIViewControllerContextTransitioning?) -> TimeInterval { 0.5 }
-
-    func animateTransition(using context: UIViewControllerContextTransitioning) {
-        switch direction {
-        case .present:
-            present(using: context)
-        case .dismiss:
-            dismiss(using: context)
-        }
-    }
-
-    private func present(using context: UIViewControllerContextTransitioning) {
-        guard let presentingController = context.viewController(forKey: .from),
-              let presentedView = context.view(forKey: .to) else {
-            context.completeTransition(false)
-            return
-        }
-
-        let darkOverlayView = UIControl()
-        self.darkOverlayView = darkOverlayView
-
-        darkOverlayView.alpha = 0.0
-        darkOverlayView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
-        context.containerView.addSubview(darkOverlayView)
-        darkOverlayView.frame = context.containerView.bounds
-
-        darkOverlayView
-            .publisher(for: .touchUpInside)
-            .sink { [weak presentingController] _ in
-                presentingController?.dismiss(animated: true)
-            }.store(in: &cancellables)
-
-        context.containerView.addSubview(presentedView)
-        presentedView.translatesAutoresizingMaskIntoConstraints = false
-
-        presentedConstraints = [
-            presentedView.leftAnchor.constraint(equalTo: context.containerView.leftAnchor),
-            presentedView.rightAnchor.constraint(equalTo: context.containerView.rightAnchor),
-            presentedView.bottomAnchor.constraint(equalTo: context.containerView.bottomAnchor),
-            presentedView.topAnchor.constraint(
-                greaterThanOrEqualTo: context.containerView.safeAreaLayoutGuide.topAnchor,
-                constant: 60
-            )
-        ]
-
-        dismissedConstraints = [
-            presentedView.leftAnchor.constraint(equalTo: context.containerView.leftAnchor),
-            presentedView.rightAnchor.constraint(equalTo: context.containerView.rightAnchor),
-            presentedView.topAnchor.constraint(equalTo: context.containerView.bottomAnchor)
-        ]
-
-        NSLayoutConstraint.activate(dismissedConstraints)
-
-        context.containerView.setNeedsLayout()
-        context.containerView.layoutIfNeeded()
-
-        NSLayoutConstraint.deactivate(dismissedConstraints)
-        NSLayoutConstraint.activate(presentedConstraints)
-
-        UIView.animate(
-            withDuration: transitionDuration(using: context),
-            delay: 0,
-            usingSpringWithDamping: 1,
-            initialSpringVelocity: 0,
-            options: .curveEaseInOut,
-            animations: {
-                darkOverlayView.alpha = 1.0
-                context.containerView.setNeedsLayout()
-                context.containerView.layoutIfNeeded()
-            },
-            completion: { _ in
-                context.completeTransition(true)
-            })
-    }
-
-    private func dismiss(using context: UIViewControllerContextTransitioning) {
-        NSLayoutConstraint.deactivate(presentedConstraints)
-        NSLayoutConstraint.activate(dismissedConstraints)
-
-        UIView.animate(
-            withDuration: transitionDuration(using: context),
-            delay: 0,
-            usingSpringWithDamping: 1,
-            initialSpringVelocity: 0,
-            options: .curveEaseInOut,
-            animations: { [weak darkOverlayView] in
-                darkOverlayView?.alpha = 0.0
-                context.containerView.setNeedsLayout()
-                context.containerView.layoutIfNeeded()
-            },
-            completion: { [weak self] _ in
-                context.completeTransition(true)
-                self?.onDismissal()
-            })
-    }
-}
diff --git a/Sources/Presentation/CenterPresenter.swift b/Sources/Presentation/CenterPresenter.swift
deleted file mode 100644
index 99277dc5708680bcd74482edc5cc88d542072381..0000000000000000000000000000000000000000
--- a/Sources/Presentation/CenterPresenter.swift
+++ /dev/null
@@ -1,35 +0,0 @@
-import UIKit
-
-public protocol CenterPresenterNonDismissingTarget: UIViewController {}
-
-public final class CenterPresenter: NSObject, Presenting {
-    private var transition: CenterTransition?
-
-    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
-extension CenterPresenter: UIViewControllerTransitioningDelegate {
-    public func animationController(forPresented presented: UIViewController,
-                             presenting: UIViewController,
-                             source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
-        transition = CenterTransition(
-            onDismissal: { [weak self] in self?.transition = nil },
-            dismissable: (presented is CenterPresenterNonDismissingTarget) == false)
-
-        return transition
-    }
-
-    public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
-        transition?.direction = .dismiss
-        return transition
-    }
-}
diff --git a/Sources/Presentation/CenterTransition.swift b/Sources/Presentation/CenterTransition.swift
deleted file mode 100644
index ad94401d4e69f15d116fe5a98966e7d268914985..0000000000000000000000000000000000000000
--- a/Sources/Presentation/CenterTransition.swift
+++ /dev/null
@@ -1,136 +0,0 @@
-import UIKit
-import Combine
-import SnapKit
-import Shared
-
-final class CenterTransition: NSObject, UIViewControllerAnimatedTransitioning {
-    enum Direction {
-        case present
-        case dismiss
-    }
-
-    let dismissable: Bool
-    var direction: Direction = .present
-    private let onDismissal: EmptyClosure
-    private weak var darkOverlayView: UIControl?
-    private weak var topConstraint: Constraint?
-    private weak var bottomConstraint: Constraint?
-    private var cancellables = Set<AnyCancellable>()
-
-    private var presentedConstraints: [NSLayoutConstraint] = []
-    private var dismissedConstraints: [NSLayoutConstraint] = []
-
-    init(onDismissal: @escaping EmptyClosure,
-         dismissable: Bool = true) {
-        self.dismissable = dismissable
-        self.onDismissal = onDismissal
-        super.init()
-    }
-
-    func transitionDuration(using context: UIViewControllerContextTransitioning?) -> TimeInterval { 0.25 }
-
-    func animateTransition(using context: UIViewControllerContextTransitioning) {
-        switch direction {
-        case .present:
-            present(using: context)
-        case .dismiss:
-            dismiss(using: context)
-        }
-    }
-
-    private func present(using context: UIViewControllerContextTransitioning) {
-        guard let presentingController = context.viewController(forKey: .from),
-              let presentedView = context.view(forKey: .to) else {
-            context.completeTransition(false)
-            return
-        }
-
-        let darkOverlayView = UIControl()
-        self.darkOverlayView = darkOverlayView
-
-        darkOverlayView.alpha = 0.0
-        darkOverlayView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
-        context.containerView.addSubview(darkOverlayView)
-        darkOverlayView.frame = context.containerView.bounds
-
-        if dismissable {
-            darkOverlayView
-                .publisher(for: .touchUpInside)
-                .sink { [weak presentingController] _ in
-                    presentingController?.dismiss(animated: true)
-                }
-                .store(in: &cancellables)
-        }
-
-        context.containerView.addSubview(presentedView)
-        presentedView.translatesAutoresizingMaskIntoConstraints = false
-        presentedView.alpha = 0.0
-
-        presentedView.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
-
-        presentedConstraints = [
-            presentedView.leftAnchor.constraint(equalTo: context.containerView.leftAnchor, constant: 40),
-            presentedView.rightAnchor.constraint(equalTo: context.containerView.rightAnchor, constant: -40),
-            presentedView.centerYAnchor.constraint(equalTo: context.containerView.centerYAnchor)
-        ]
-
-        dismissedConstraints = [
-            presentedView.leftAnchor.constraint(equalTo: context.containerView.leftAnchor, constant: 40),
-            presentedView.rightAnchor.constraint(equalTo: context.containerView.rightAnchor, constant: -40),
-            presentedView.centerYAnchor.constraint(equalTo: context.containerView.centerYAnchor)
-        ]
-
-        NSLayoutConstraint.activate(dismissedConstraints)
-
-        context.containerView.setNeedsLayout()
-        context.containerView.layoutIfNeeded()
-
-        NSLayoutConstraint.deactivate(dismissedConstraints)
-        NSLayoutConstraint.activate(presentedConstraints)
-
-        UIView.animate(
-            withDuration: transitionDuration(using: context),
-            delay: 0,
-            usingSpringWithDamping: 1,
-            initialSpringVelocity: 0,
-            options: .curveEaseInOut,
-            animations: {
-                darkOverlayView.alpha = 1.0
-                presentedView.alpha = 1.0
-                context.containerView.setNeedsLayout()
-                context.containerView.layoutIfNeeded()
-                presentedView.transform = .identity
-            },
-            completion: { _ in
-                context.completeTransition(true)
-            })
-    }
-
-    private func dismiss(using context: UIViewControllerContextTransitioning) {
-        NSLayoutConstraint.deactivate(presentedConstraints)
-        NSLayoutConstraint.activate(dismissedConstraints)
-
-        guard let presentedView = context.view(forKey: .from) else {
-            context.completeTransition(false)
-            return
-        }
-
-        UIView.animate(
-            withDuration: transitionDuration(using: context),
-            delay: 0,
-            usingSpringWithDamping: 1,
-            initialSpringVelocity: 0,
-            options: .curveEaseInOut,
-            animations: { [weak darkOverlayView] in
-                darkOverlayView?.alpha = 0.0
-                presentedView.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
-                presentedView.alpha = 0.0
-                context.containerView.setNeedsLayout()
-                context.containerView.layoutIfNeeded()
-            },
-            completion: { [weak self] _ in
-                context.completeTransition(true)
-                self?.onDismissal()
-            })
-    }
-}
diff --git a/Sources/Presentation/FadePresenter.swift b/Sources/Presentation/FadePresenter.swift
deleted file mode 100644
index d4d27c85ec5af65355d97487b06fb39f4c4fa2e3..0000000000000000000000000000000000000000
--- a/Sources/Presentation/FadePresenter.swift
+++ /dev/null
@@ -1,29 +0,0 @@
-import UIKit
-
-public final class FadePresenter: NSObject, Presenting {
-    private var transition: FadeTransition?
-
-    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)
-    }
-}
-
-extension FadePresenter: UIViewControllerTransitioningDelegate {
-    public func animationController(forPresented presented: UIViewController,
-                                    presenting: UIViewController,
-                                    source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
-        transition = FadeTransition(didDismiss: { [weak self] in self?.transition = nil })
-        return transition
-    }
-
-    public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
-        transition?.direction = .dismiss
-        return transition
-    }
-}
diff --git a/Sources/Presentation/FadeTransition.swift b/Sources/Presentation/FadeTransition.swift
deleted file mode 100644
index 71841ccd9b4433c8d95066be3e835bffe4f49c41..0000000000000000000000000000000000000000
--- a/Sources/Presentation/FadeTransition.swift
+++ /dev/null
@@ -1,90 +0,0 @@
-import UIKit
-import Combine
-import SnapKit
-import Shared
-
-final class FadeTransition: NSObject, UIViewControllerAnimatedTransitioning {
-    enum Direction {
-        case present
-        case dismiss
-    }
-
-    var direction: Direction = .present
-    private let didDismiss: EmptyClosure
-    private weak var darkOverlayView: UIControl?
-
-    init(didDismiss: @escaping EmptyClosure) {
-        self.didDismiss = didDismiss
-        super.init()
-    }
-
-    func transitionDuration(using context: UIViewControllerContextTransitioning?) -> TimeInterval { 0.25 }
-
-    func animateTransition(using context: UIViewControllerContextTransitioning) {
-        switch direction {
-        case .present:
-            present(using: context)
-        case .dismiss:
-            dismiss(using: context)
-        }
-    }
-
-    private func present(using context: UIViewControllerContextTransitioning) {
-        guard let presentedView = context.view(forKey: .to) else {
-            context.completeTransition(false)
-            return
-        }
-
-        let darkOverlayView = UIControl()
-        self.darkOverlayView = darkOverlayView
-
-        darkOverlayView.alpha = 0.0
-        darkOverlayView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
-        context.containerView.addSubview(darkOverlayView)
-        darkOverlayView.frame = context.containerView.bounds
-
-        context.containerView.addSubview(presentedView)
-        presentedView.alpha = 0.0
-
-        presentedView.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
-        presentedView.snp.makeConstraints { $0.edges.equalToSuperview() }
-
-        UIView.animate(
-            withDuration: transitionDuration(using: context),
-            delay: 0,
-            usingSpringWithDamping: 1,
-            initialSpringVelocity: 0,
-            options: .curveEaseInOut,
-            animations: {
-                darkOverlayView.alpha = 1.0
-                presentedView.alpha = 1.0
-                presentedView.transform = .identity
-            },
-            completion: { _ in
-                context.completeTransition(true)
-            })
-    }
-
-    private func dismiss(using context: UIViewControllerContextTransitioning) {
-        guard let presentedView = context.view(forKey: .from) else {
-            context.completeTransition(false)
-            return
-        }
-
-        UIView.animate(
-            withDuration: transitionDuration(using: context),
-            delay: 0,
-            usingSpringWithDamping: 1,
-            initialSpringVelocity: 0,
-            options: .curveEaseInOut,
-            animations: { [weak darkOverlayView] in
-                darkOverlayView?.alpha = 0.0
-                presentedView.transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
-                presentedView.alpha = 0.0
-            },
-            completion: { [weak self] _ in
-                context.completeTransition(true)
-                self?.didDismiss()
-            })
-    }
-}
diff --git a/Sources/Presentation/FullscreenPresenter.swift b/Sources/Presentation/FullscreenPresenter.swift
deleted file mode 100644
index 207c77e66aabce11e6682b32701fc6a2e483befc..0000000000000000000000000000000000000000
--- a/Sources/Presentation/FullscreenPresenter.swift
+++ /dev/null
@@ -1,33 +0,0 @@
-import UIKit
-
-public final class FullscreenPresenter: NSObject, Presenting {
-    private var transition: FullscreenTransition?
-
-    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
-extension FullscreenPresenter: UIViewControllerTransitioningDelegate {
-    public func animationController(forPresented presented: UIViewController,
-                                    presenting: UIViewController,
-                                    source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
-        transition = FullscreenTransition(onDismissal: { [weak self] in
-            self?.transition = nil
-        })
-
-        return transition
-    }
-
-    public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
-        transition?.direction = .dismiss
-        return transition
-    }
-}
diff --git a/Sources/Presentation/FullscreenTransition.swift b/Sources/Presentation/FullscreenTransition.swift
deleted file mode 100644
index 7a36e5beb64cbe2227890c37cd7215b87088193e..0000000000000000000000000000000000000000
--- a/Sources/Presentation/FullscreenTransition.swift
+++ /dev/null
@@ -1,120 +0,0 @@
-import UIKit
-import Combine
-import SnapKit
-import Shared
-
-final class FullscreenTransition: NSObject, UIViewControllerAnimatedTransitioning {
-    enum Direction {
-        case present
-        case dismiss
-    }
-
-    var direction: Direction = .present
-    private let onDismissal: EmptyClosure
-    private weak var darkOverlayView: UIControl?
-    private weak var topConstraint: Constraint?
-    private weak var bottomConstraint: Constraint?
-    private var cancellables = Set<AnyCancellable>()
-
-    private var presentedConstraints: [NSLayoutConstraint] = []
-    private var dismissedConstraints: [NSLayoutConstraint] = []
-
-    init(onDismissal: @escaping EmptyClosure) {
-        self.onDismissal = onDismissal
-        super.init()
-    }
-
-    func transitionDuration(using context: UIViewControllerContextTransitioning?) -> TimeInterval { 0.5 }
-
-    func animateTransition(using context: UIViewControllerContextTransitioning) {
-        switch direction {
-        case .present:
-            present(using: context)
-        case .dismiss:
-            dismiss(using: context)
-        }
-    }
-
-    private func present(using context: UIViewControllerContextTransitioning) {
-        guard let presentingController = context.viewController(forKey: .from),
-              let presentedView = context.view(forKey: .to) else {
-                  context.completeTransition(false)
-                  return
-              }
-
-        let darkOverlayView = UIControl()
-        self.darkOverlayView = darkOverlayView
-
-        darkOverlayView.alpha = 0.0
-        darkOverlayView.backgroundColor = UIColor.black.withAlphaComponent(0.5)
-        context.containerView.addSubview(darkOverlayView)
-        darkOverlayView.frame = context.containerView.bounds
-
-        darkOverlayView
-            .publisher(for: .touchUpInside)
-            .sink { [weak presentingController] _ in
-                presentingController?.dismiss(animated: true)
-            }.store(in: &cancellables)
-
-        context.containerView.addSubview(presentedView)
-        presentedView.translatesAutoresizingMaskIntoConstraints = false
-
-        presentedConstraints = [
-            presentedView.topAnchor.constraint(equalTo: context.containerView.topAnchor),
-            presentedView.leftAnchor.constraint(equalTo: context.containerView.leftAnchor),
-            presentedView.rightAnchor.constraint(equalTo: context.containerView.rightAnchor),
-            presentedView.bottomAnchor.constraint(equalTo: context.containerView.bottomAnchor)
-        ]
-
-        dismissedConstraints = [
-            presentedView.leftAnchor.constraint(equalTo: context.containerView.leftAnchor),
-            presentedView.rightAnchor.constraint(equalTo: context.containerView.rightAnchor),
-            presentedView.topAnchor.constraint(equalTo: context.containerView.bottomAnchor),
-            presentedView.heightAnchor.constraint(equalTo: context.containerView.heightAnchor)
-        ]
-
-        NSLayoutConstraint.activate(dismissedConstraints)
-
-        context.containerView.setNeedsLayout()
-        context.containerView.layoutIfNeeded()
-
-        NSLayoutConstraint.deactivate(dismissedConstraints)
-        NSLayoutConstraint.activate(presentedConstraints)
-
-        UIView.animate(
-            withDuration: transitionDuration(using: context),
-            delay: 0,
-            usingSpringWithDamping: 1,
-            initialSpringVelocity: 0,
-            options: .curveEaseInOut,
-            animations: {
-                darkOverlayView.alpha = 1.0
-                context.containerView.setNeedsLayout()
-                context.containerView.layoutIfNeeded()
-            },
-            completion: { _ in
-                context.completeTransition(true)
-            })
-    }
-
-    private func dismiss(using context: UIViewControllerContextTransitioning) {
-        NSLayoutConstraint.deactivate(presentedConstraints)
-        NSLayoutConstraint.activate(dismissedConstraints)
-
-        UIView.animate(
-            withDuration: transitionDuration(using: context),
-            delay: 0,
-            usingSpringWithDamping: 1,
-            initialSpringVelocity: 0,
-            options: .curveEaseInOut,
-            animations: { [weak darkOverlayView] in
-                darkOverlayView?.alpha = 0.0
-                context.containerView.setNeedsLayout()
-                context.containerView.layoutIfNeeded()
-            },
-            completion: { [weak self] _ in
-                context.completeTransition(true)
-                self?.onDismissal()
-            })
-    }
-}
diff --git a/Sources/Presentation/Presenting.swift b/Sources/Presentation/Presenting.swift
deleted file mode 100644
index b79da38e915bca7cefe9a82997ade14eae846135..0000000000000000000000000000000000000000
--- a/Sources/Presentation/Presenting.swift
+++ /dev/null
@@ -1,100 +0,0 @@
-import UIKit
-import Shared
-
-public protocol Presenting {
-    func present(_ target: UIViewController..., from parent: UIViewController)
-    func dismiss(from parent: UIViewController)
-}
-
-public extension Presenting {
-    func dismiss(from parent: UIViewController) {
-        parent.dismiss(animated: true)
-    }
-}
-
-public struct PushPresenter: Presenting {
-    public init() {}
-
-    public func present(_ target: UIViewController..., from parent: UIViewController) {
-        parent.navigationController?.pushViewController(target.first!, animated: true)
-    }
-}
-
-public struct ModalPresenter: Presenting {
-    public init() {}
-
-    public func present(_ target: UIViewController..., from parent: UIViewController) {
-      let statusBarVC = RootViewController(UINavigationController(rootViewController: target.first!))
-        statusBarVC.modalPresentationStyle = .fullScreen
-        parent.present(statusBarVC, animated: true)
-    }
-}
-
-public struct ReplacePresenter: Presenting {
-    public enum Mode {
-        case replaceAll
-        case replaceLast
-        case replaceBackwards(AnyObject.Type)
-    }
-
-    var mode: Mode
-
-    public init(mode: Mode = .replaceAll) {
-        self.mode = mode
-    }
-
-    public func present(_ target: UIViewController..., from parent: UIViewController) {
-        guard let navigationController = parent.navigationController else { return }
-
-        switch mode {
-        case .replaceAll:
-            navigationController.setViewControllers(target, animated: true)
-
-        case .replaceBackwards(let OlderInStack):
-            if let oldScreen = navigationController.viewControllers.filter({ $0.isKind(of: OlderInStack.self) }).first,
-               let index = navigationController.viewControllers.firstIndex(of: oldScreen) {
-
-                let viewControllersBefore =
-                    navigationController.viewControllers.dropLast(
-                        navigationController.viewControllers.count - index
-                    )
-
-                if let coordinator = navigationController.transitionCoordinator {
-                    coordinator.animate(alongsideTransition: nil) { _ in
-                        navigationController.setViewControllers(viewControllersBefore + target , animated: true)
-                    }
-                } else {
-                    navigationController.setViewControllers(viewControllersBefore + target , animated: true)
-                }
-
-            } else {
-                navigationController.pushViewController(target.first!, animated: true)
-            }
-        case .replaceLast:
-            let viewControllersBefore = navigationController.viewControllers.dropLast()
-
-            func replace() {
-                navigationController.setViewControllers(viewControllersBefore + target , animated: true)
-            }
-
-            if let coordinator = navigationController.transitionCoordinator {
-                coordinator.animate(alongsideTransition: nil) { _ in
-                    replace()
-                }
-            } else {
-                replace()
-            }
-        }
-    }
-}
-
-public struct PopReplacePresenter: Presenting {
-    public init() {}
-
-    public func present(_ target: UIViewController..., from parent: UIViewController) {
-        if let lastViewController = parent.navigationController?.viewControllers.last {
-            parent.navigationController?.setViewControllers([target.first!, lastViewController], animated: false)
-            parent.navigationController?.setViewControllers([target.first!], animated: true)
-        }
-    }
-}
diff --git a/Sources/Presentation/SideMenuAnimator.swift b/Sources/Presentation/SideMenuAnimator.swift
deleted file mode 100644
index 02f302616920022d137f73b8bc704fac75883382..0000000000000000000000000000000000000000
--- a/Sources/Presentation/SideMenuAnimator.swift
+++ /dev/null
@@ -1,26 +0,0 @@
-import UIKit
-
-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)
-    }
-}
diff --git a/Sources/Presentation/SideMenuDismissInteractor.swift b/Sources/Presentation/SideMenuDismissInteractor.swift
deleted file mode 100644
index d170ebce1aff83b1e75641ee6970a51497ccb44c..0000000000000000000000000000000000000000
--- a/Sources/Presentation/SideMenuDismissInteractor.swift
+++ /dev/null
@@ -1,73 +0,0 @@
-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()
-        }
-    }
-}
diff --git a/Sources/Presentation/SideMenuDismissTransition.swift b/Sources/Presentation/SideMenuDismissTransition.swift
deleted file mode 100644
index 829367fec8d564210b9f018eba1a0c6a4ac9a04b..0000000000000000000000000000000000000000
--- a/Sources/Presentation/SideMenuDismissTransition.swift
+++ /dev/null
@@ -1,31 +0,0 @@
-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)
-            }
-        )
-    }
-}
diff --git a/Sources/Presentation/SideMenuPresentTransition.swift b/Sources/Presentation/SideMenuPresentTransition.swift
deleted file mode 100644
index a29d7aea09e7e6414116bfb4ebd38da78b7d07c8..0000000000000000000000000000000000000000
--- a/Sources/Presentation/SideMenuPresentTransition.swift
+++ /dev/null
@@ -1,67 +0,0 @@
-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)
-            }
-        )
-    }
-}
diff --git a/Sources/Presentation/SideMenuPresenter.swift b/Sources/Presentation/SideMenuPresenter.swift
deleted file mode 100644
index 5d9036dee7ef729973eeef8cf4f5d56e7b3d0bab..0000000000000000000000000000000000000000
--- a/Sources/Presentation/SideMenuPresenter.swift
+++ /dev/null
@@ -1,56 +0,0 @@
-import UIKit
-
-public final class SideMenuPresenter: NSObject,
-                                      Presenting,
-                                      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
-    }
-}
diff --git a/Sources/Presentation/UIViewAnimating.swift b/Sources/Presentation/UIViewAnimating.swift
deleted file mode 100644
index 63210a2c3ef1b1cd921540d0f994418c18f089a5..0000000000000000000000000000000000000000
--- a/Sources/Presentation/UIViewAnimating.swift
+++ /dev/null
@@ -1,12 +0,0 @@
-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/ProfileFeature/Controllers/ProfileController.swift b/Sources/ProfileFeature/Controllers/ProfileController.swift
index d80d7a9c3f48079eaaacc2f7d5a859ff472745f2..3662169233784d0c2f6420e0e5d1c512a414334c 100644
--- a/Sources/ProfileFeature/Controllers/ProfileController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfileController.swift
@@ -65,7 +65,7 @@ public final class ProfileController: UIViewController {
               self.viewModel.didTapDelete(isEmail: true)
             }
         } else {
-          navigator.perform(PresentProfileEmail())
+          navigator.perform(PresentProfileEmail(on: navigationController!))
         }
       }.store(in: &cancellables)
 
@@ -87,7 +87,7 @@ public final class ProfileController: UIViewController {
               self.viewModel.didTapDelete(isEmail: false)
             }
         } else {
-          navigator.perform(PresentProfilePhone())
+          navigator.perform(PresentProfilePhone(on: navigationController!))
         }
       }.store(in: &cancellables)
 
@@ -112,10 +112,10 @@ public final class ProfileController: UIViewController {
             title: Localized.Profile.Photo.title,
             subtitle: Localized.Profile.Photo.subtitle,
             actionTitle: Localized.Profile.Photo.continue) {
-              self.navigator.perform(PresentPhotoLibrary())
+              self.navigator.perform(PresentPhotoLibrary(from: self))
           }
         case .libraryPermission:
-          self.navigator.perform(PresentPermissionRequest(type: .library))
+          self.navigator.perform(PresentPermissionRequest(type: .library, from: self))
         case .none:
           break
         }
@@ -190,11 +190,11 @@ public final class ProfileController: UIViewController {
         spacingAfter: 37
       ),
       actionButton
-    ]))
+    ], isDismissable: true, from: self))
   }
 
   @objc private func didTapMenu() {
-    navigator.perform(PresentMenu(currentItem: .profile))
+    navigator.perform(PresentMenu(currentItem: .profile, from: self))
   }
 }
 
diff --git a/Sources/ProfileFeature/Controllers/ProfileEmailController.swift b/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
index 4fb0b42f4e56f373d28c45dc70fb2315fff4ba51..1bfc1c789b7f4de906f56aaad09c94f08a8fb7ba 100644
--- a/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfileEmailController.swift
@@ -64,7 +64,8 @@ public final class ProfileEmailController: UIViewController {
           PresentProfileCode(
             isEmail: true,
             content: $0.input,
-            confirmationId: id
+            confirmationId: id,
+            on: navigationController!
           )
         )
       }.store(in: &cancellables)
diff --git a/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift b/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
index a1e4216839cddacd3ce96622c6d8a872462b0cc5..bd9689a44bcc96f648bb1c6427de7b15148957a7 100644
--- a/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
+++ b/Sources/ProfileFeature/Controllers/ProfilePhoneController.swift
@@ -63,7 +63,7 @@ public final class ProfilePhoneController: UIViewController {
         navigator.perform(PresentCountryList(completion: { [weak self] in
           guard let self else { return }
           self.viewModel.didChooseCountry($0 as! Country)
-        }))
+        }, from: self))
       }.store(in: &cancellables)
 
     viewModel
@@ -76,7 +76,8 @@ public final class ProfilePhoneController: UIViewController {
           PresentProfileCode(
             isEmail: false,
             content: content,
-            confirmationId: id
+            confirmationId: id,
+            on: navigationController!
           )
         )
       }.store(in: &cancellables)
diff --git a/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
index a71cb16be3e8d4643d01112dfedb8200fb4924d5..2eadd36da44361a596cc1ddaa81dbbefb60c5d0b 100644
--- a/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfilePhoneViewModel.swift
@@ -1,11 +1,11 @@
 import Shared
 import Combine
 import XXClient
-import Countries
 import InputField
 import Foundation
 import CombineSchedulers
 import XXMessengerClient
+import CountryListFeature
 import DI
 
 final class ProfilePhoneViewModel {
diff --git a/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift b/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
index 1b0803add61d03bba84bb92e4dc989e442c4908e..17daebf9d9bbbba24b545c59f7dca5c8a0e88660 100644
--- a/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
+++ b/Sources/ProfileFeature/ViewModels/ProfileViewModel.swift
@@ -3,12 +3,12 @@ import Shared
 import Combine
 import Defaults
 import XXClient
-import Countries
 import Foundation
 import Permissions
 import BackupFeature
 import XXMessengerClient
 import CombineSchedulers
+import CountryListFeature
 import DI
 
 enum ProfileNavigationRoutes {
diff --git a/Sources/PushFeature/PushExtractor.swift b/Sources/PushFeature/PushExtractor.swift
index c2848caeaf8f10aae030177b8367935d8ffffa3b..75c6a69070d0d301498122896ac90ab2ab48c987 100644
--- a/Sources/PushFeature/PushExtractor.swift
+++ b/Sources/PushFeature/PushExtractor.swift
@@ -1,6 +1,6 @@
 import XXModels
-import Foundation
 import XXClient
+import Foundation
 import XXMessengerClient
 import DI
 
diff --git a/Sources/ReportingFeature/MakeReportDrawer.swift b/Sources/ReportingFeature/MakeReportDrawer.swift
index bd102a6ee2e046b03c787d250f8a0573d25af7c3..249683a0de30030e305fc399fcdc841dbee1bd75 100644
--- a/Sources/ReportingFeature/MakeReportDrawer.swift
+++ b/Sources/ReportingFeature/MakeReportDrawer.swift
@@ -1,86 +1,87 @@
-import DrawerFeature
-import Shared
 import UIKit
+import Shared
+import AppResources
+import DrawerFeature
 import XCTestDynamicOverlay
 
 public struct MakeReportDrawer {
-    public struct Config {
-        public init(
-            onReport: @escaping () -> Void = {},
-            onCancel: @escaping () -> Void = {}
-        ) {
-            self.onReport = onReport
-            self.onCancel = onCancel
-        }
-
-        public var onReport: () -> Void
-        public var onCancel: () -> Void
+  public struct Config {
+    public init(
+      onReport: @escaping () -> Void = {},
+      onCancel: @escaping () -> Void = {}
+    ) {
+      self.onReport = onReport
+      self.onCancel = onCancel
     }
 
-    public var run: (Config) -> UIViewController
+    public var onReport: () -> Void
+    public var onCancel: () -> Void
+  }
 
-    public func callAsFunction(_ config: Config) -> UIViewController {
-        run(config)
-    }
+  public var run: (Config) -> UIViewController
+
+  public func callAsFunction(_ config: Config) -> UIViewController {
+    run(config)
+  }
 }
 
 extension MakeReportDrawer {
-    public static let live = MakeReportDrawer { config in
-        let cancelButton = CapsuleButton()
-        cancelButton.setStyle(.seeThrough)
-        cancelButton.setTitle(Localized.Chat.Report.cancel, for: .normal)
+  public static let live = MakeReportDrawer { config in
+    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)
+    let reportButton = CapsuleButton()
+    reportButton.setStyle(.red)
+    reportButton.setTitle(Localized.Chat.Report.action, for: .normal)
 
-        let drawer = DrawerController([
-            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]
-            )
-        ])
+    let drawer = DrawerController([
+      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]
+      )
+    ])
 
-        reportButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned drawer] in
-                drawer.dismiss(animated: true) {
-                    config.onReport()
-                }
-            }
-            .store(in: &drawer.cancellables)
+    reportButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned drawer] in
+        drawer.dismiss(animated: true) {
+          config.onReport()
+        }
+      }
+      .store(in: &drawer.cancellables)
 
-        cancelButton.publisher(for: .touchUpInside)
-            .receive(on: DispatchQueue.main)
-            .sink { [unowned drawer] in
-                drawer.dismiss(animated: true) {
-                    config.onCancel()
-                }
-            }
-            .store(in: &drawer.cancellables)
+    cancelButton.publisher(for: .touchUpInside)
+      .receive(on: DispatchQueue.main)
+      .sink { [unowned drawer] in
+        drawer.dismiss(animated: true) {
+          config.onCancel()
+        }
+      }
+      .store(in: &drawer.cancellables)
 
-        return drawer
-    }
+    return drawer
+  }
 }
 
 extension MakeReportDrawer {
-    public static let unimplemented = MakeReportDrawer(
-        run: XCTUnimplemented("\(Self.self)")
-    )
+  public static let unimplemented = MakeReportDrawer(
+    run: XCTUnimplemented("\(Self.self)")
+  )
 }
diff --git a/Sources/Permissions/RequestPermissionController.swift b/Sources/RequestPermissionFeature/RequestPermissionController.swift
similarity index 78%
rename from Sources/Permissions/RequestPermissionController.swift
rename to Sources/RequestPermissionFeature/RequestPermissionController.swift
index 24b09405aa22942886d84ffa9b1012fcd2d34a80..2a8e364d2315742f0e0d674549830ac9a9778744 100644
--- a/Sources/Permissions/RequestPermissionController.swift
+++ b/Sources/RequestPermissionFeature/RequestPermissionController.swift
@@ -1,13 +1,14 @@
-import DI
 import UIKit
 import Shared
 import Combine
-import Navigation
+import AppResources
+import StatusBarFeature
+import PermissionsFeature
+import ComposableArchitecture
 
 public final class RequestPermissionController: UIViewController {
-  @Dependency var navigator: Navigator
-  @Dependency var barStylist: StatusBarStylist
-  @Dependency var permissions: PermissionHandling
+  @Dependency(\.statusBar) var statusBar: StatusBarStyleManager
+  @Dependency(\.permissions) var permissions: PermissionsManager
 
   private lazy var screenView = RequestPermissionView()
 
@@ -27,10 +28,7 @@ public final class RequestPermissionController: UIViewController {
 
   public override func viewWillAppear(_ animated: Bool) {
     super.viewWillAppear(animated)
-    navigationItem.backButtonTitle = ""
-    barStylist.styleSubject.send(.darkContent)
-    navigationController?.navigationBar
-      .customize(backgroundColor: Asset.neutralWhite.color)
+    statusBar.update(.darkContent)
   }
 
   public override func viewDidLoad() {
@@ -62,7 +60,7 @@ public final class RequestPermissionController: UIViewController {
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(DismissModal(from: self))
+        dismiss(animated: true)
       }.store(in: &cancellables)
 
     screenView
@@ -72,17 +70,17 @@ public final class RequestPermissionController: UIViewController {
       .sink { [unowned self] in
         switch permissionType {
         case .camera:
-          permissions.requestCamera { [weak self] _ in
+          permissions.camera.request { [weak self] _ in
             guard let self else { return }
             self.shouldDismissModal()
           }
         case .library:
-          permissions.requestPhotos { [weak self] _ in
+          permissions.library.request { [weak self] _ in
             guard let self else { return }
             self.shouldDismissModal()
           }
         case .microphone:
-          permissions.requestMicrophone { [weak self] _ in
+          permissions.microphone.request { [weak self] _ in
             guard let self else { return }
             self.shouldDismissModal()
           }
@@ -93,7 +91,7 @@ public final class RequestPermissionController: UIViewController {
   private func shouldDismissModal() {
     DispatchQueue.main.async { [weak self] in
       guard let self else { return }
-      self.navigator.perform(DismissModal(from: self))
+      self.dismiss(animated: true)
     }
   }
 }
diff --git a/Sources/RequestPermissionFeature/RequestPermissionView.swift b/Sources/RequestPermissionFeature/RequestPermissionView.swift
new file mode 100644
index 0000000000000000000000000000000000000000..ab4405bd0844fce7bf2273f8e8a0944106e4c894
--- /dev/null
+++ b/Sources/RequestPermissionFeature/RequestPermissionView.swift
@@ -0,0 +1,103 @@
+import UIKit
+import Shared
+import AppResources
+
+final class RequestPermissionView: UIView {
+  let titleLabel = UILabel()
+  let iconImage = UIImageView()
+  let subtitleLabel = UILabel()
+  let littleLogo = UIImageView()
+  let notNowButton = UIButton()
+  let continueButton = CapsuleButton()
+
+  init() {
+    super.init(frame: .zero)
+    littleLogo.image = Asset.permissionLogo.image
+    notNowButton.setTitle(Localized.Chat.Actions.Permission.notnow, for: .normal)
+    continueButton.set(style: .brandColored, title: Localized.Chat.Actions.Permission.continue)
+
+    titleLabel.textAlignment = .center
+
+    backgroundColor = Asset.neutralWhite.color
+    titleLabel.textColor = Asset.neutralActive.color
+    notNowButton.setTitleColor(Asset.neutralWeak.color, for: .normal)
+
+    subtitleLabel.numberOfLines = 0
+
+    titleLabel.font = Fonts.Mulish.bold.font(size: 24.0)
+    notNowButton.titleLabel?.font = Fonts.Mulish.semiBold.font(size: 16)
+
+    let actionsContainer = UIView()
+    actionsContainer.addSubview(continueButton)
+    actionsContainer.addSubview(notNowButton)
+
+    addSubview(iconImage)
+    addSubview(titleLabel)
+    addSubview(littleLogo)
+    addSubview(subtitleLabel)
+    addSubview(actionsContainer)
+
+    iconImage.snp.makeConstraints {
+      $0.centerX.equalToSuperview()
+    }
+
+    titleLabel.snp.makeConstraints {
+      $0.top.equalTo(iconImage.snp.bottom).offset(34)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+    }
+
+    subtitleLabel.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(8)
+      $0.left.equalToSuperview().offset(32)
+      $0.right.equalToSuperview().offset(-32)
+      $0.bottom.equalTo(snp.centerY)
+    }
+
+    littleLogo.snp.makeConstraints {
+      $0.centerX.equalToSuperview()
+      $0.bottom.equalTo(safeAreaLayoutGuide).offset(-15)
+    }
+
+    actionsContainer.snp.makeConstraints {
+      $0.top.greaterThanOrEqualTo(subtitleLabel.snp.bottom)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.lessThanOrEqualTo(littleLogo.snp.top)
+    }
+
+    continueButton.snp.makeConstraints {
+      $0.top.greaterThanOrEqualToSuperview()
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
+      $0.bottom.equalTo(actionsContainer.snp.centerY).offset(-5)
+    }
+
+    notNowButton.snp.makeConstraints {
+      $0.top.equalTo(actionsContainer.snp.centerY).offset(5)
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
+      $0.bottom.lessThanOrEqualToSuperview()
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  func setup(title: String, subtitle: String, image: UIImage) {
+    iconImage.image = image
+    titleLabel.text = title
+
+    let paragraph = NSMutableParagraphStyle()
+    paragraph.lineHeightMultiple = 1.5
+    paragraph.alignment = .center
+
+    subtitleLabel.attributedText = NSAttributedString(
+      string: subtitle,
+      attributes: [
+        .paragraphStyle: paragraph,
+        .font: Fonts.Mulish.regular.font(size: 14.0),
+        .foregroundColor: Asset.neutralBody.color,
+      ]
+    )
+  }
+}
diff --git a/Sources/RequestsFeature/Controllers/RequestsContainerController.swift b/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
index 3a1c2488cf57eeebbe90eb14706a9069d74aead1..97615508af52356b838b25614e59dc15d29da2b6 100644
--- a/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsContainerController.swift
@@ -77,7 +77,11 @@ public final class RequestsContainerController: UIViewController {
       .connectionsPublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentSearch(replacing: false))
+        navigator.perform(PresentSearch(
+          searching: nil,
+          replacing: false,
+          on: navigationController!
+        ))
       }.store(in: &cancellables)
 
     screenView
@@ -108,7 +112,7 @@ public final class RequestsContainerController: UIViewController {
   }
 
   @objc private func didTapMenu() {
-    navigator.perform(PresentMenu(currentItem: .requests))
+    navigator.perform(PresentMenu(currentItem: .requests, from: self))
   }
 }
 
diff --git a/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift b/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
index fe07a5bd8a326a075143154fde4ae58e24d622f2..674e3bd10232c2d4e615200526e4c5ebe1c2264b 100644
--- a/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
+++ b/Sources/RequestsFeature/Controllers/RequestsReceivedController.swift
@@ -2,9 +2,9 @@ import UIKit
 import Shared
 import Combine
 import XXModels
-import Countries
 import Navigation
 import DrawerFeature
+import CountryListFeature
 import DI
 
 final class RequestsReceivedController: UIViewController {
@@ -183,7 +183,8 @@ extension RequestsReceivedController {
           guard let self else { return }
           self.drawerCancellables.removeAll()
           self.navigator.perform(PresentGroupChat(
-            model: self.viewModel.groupChatWith(group: group)
+            groupInfo: self.viewModel.groupChatWith(group: group),
+            on: self.navigationController!
           ))
         }
       }.store(in: &drawerCancellables)
@@ -198,7 +199,7 @@ extension RequestsReceivedController {
         }
       }.store(in: &drawerCancellables)
 
-    navigator.perform(PresentDrawer(items: items))
+    navigator.perform(PresentDrawer(items: items, isDismissable: true, from: self))
   }
 }
 
@@ -264,7 +265,7 @@ extension RequestsReceivedController {
         navigator.perform(DismissModal(from: self)) { [weak self] in
           guard let self else { return }
           self.drawerCancellables.removeAll()
-          self.navigator.perform(PresentChat(contact: contact))
+          self.navigator.perform(PresentChat(contact: contact, on: navigationController!))
         }
       }.store(in: &drawerCancellables)
 
@@ -278,7 +279,7 @@ extension RequestsReceivedController {
         }
       }.store(in: &drawerCancellables)
 
-    navigator.perform(PresentDrawer(items: items))
+    navigator.perform(PresentDrawer(items: items, isDismissable: true,  from: self))
   }
 }
 
@@ -389,7 +390,7 @@ extension RequestsReceivedController {
         }
       }.store(in: &drawerCancellables)
 
-    navigator.perform(PresentDrawer(items: items))
+    navigator.perform(PresentDrawer(items: items, isDismissable: true, from: self))
   }
 }
 
@@ -540,7 +541,7 @@ extension RequestsReceivedController {
         }
       }.store(in: &drawerCancellables)
 
-    navigator.perform(PresentDrawer(items: items))
+    navigator.perform(PresentDrawer(items: items, isDismissable: true, from: self))
   }
 }
 
@@ -588,6 +589,6 @@ extension RequestsReceivedController {
         }
       }.store(in: &drawerCancellables)
 
-    navigator.perform(PresentDrawer(items: items))
+    navigator.perform(PresentDrawer(items: items, isDismissable: true, from: self))
   }
 }
diff --git a/Sources/RequestsFeature/Views/RequestCell.swift b/Sources/RequestsFeature/Views/RequestCell.swift
index e0af9ec6017ef1241ed0831ee0dbad71af7dc3d4..c1c81d28222654804ad1b0332608ce807c080c9d 100644
--- a/Sources/RequestsFeature/Views/RequestCell.swift
+++ b/Sources/RequestsFeature/Views/RequestCell.swift
@@ -1,259 +1,259 @@
 import UIKit
 import Shared
 import Combine
-import Countries
+import CountryListFeature
 
 final class RequestCell: UICollectionViewCell {
-    let titleLabel = UILabel()
-    let leaderLabel = UILabel()
-    let emailLabel = UILabel()
-    let phoneLabel = UILabel()
-    let dateLabel = UILabel()
-    let stackView = UIStackView()
-    let avatarView = AvatarView()
-    let stateButton = RequestCellButton()
-
-    var cancellables = Set<AnyCancellable>()
-    var didTapStateButton: (() -> Void)!
-
-    override init(frame: CGRect) {
-        super.init(frame: frame)
-        backgroundColor = Asset.neutralWhite.color
-
-        titleLabel.textColor = Asset.neutralActive.color
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
-
-        emailLabel.font = Fonts.Mulish.regular.font(size: 14.0)
-        phoneLabel.font = Fonts.Mulish.regular.font(size: 14.0)
-        leaderLabel.font = Fonts.Mulish.regular.font(size: 14.0)
-
-        emailLabel.textColor = Asset.neutralSecondaryAlternative.color
-        phoneLabel.textColor = Asset.neutralSecondaryAlternative.color
-        leaderLabel.textColor = Asset.neutralSecondaryAlternative.color
-
-        dateLabel.font = Fonts.Mulish.regular.font(size: 10.0)
-        dateLabel.textColor = Asset.neutralWeak.color
-
-        stackView.axis = .vertical
-        stackView.spacing = 4
-        stackView.addArrangedSubview(titleLabel)
-        stackView.addArrangedSubview(leaderLabel)
-        stackView.addArrangedSubview(emailLabel)
-        stackView.addArrangedSubview(phoneLabel)
-        stackView.addArrangedSubview(dateLabel)
-
-        contentView.addSubview(avatarView)
-        contentView.addSubview(stateButton)
-        contentView.addSubview(stackView)
-
-        avatarView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(15)
-            $0.width.height.equalTo(36)
-            $0.left.equalToSuperview().offset(27)
-            $0.bottom.lessThanOrEqualToSuperview().offset(-15)
-        }
-
-        stackView.snp.makeConstraints {
-            $0.top.equalTo(avatarView).offset(-5)
-            $0.left.equalTo(avatarView.snp.right).offset(20)
-            $0.right.lessThanOrEqualTo(stateButton.snp.left).offset(-20)
-            $0.bottom.lessThanOrEqualToSuperview().offset(-15)
-        }
-
-        stateButton.snp.makeConstraints {
-            $0.centerY.equalTo(stackView)
-            $0.right.equalToSuperview().offset(-24)
-        }
+  let titleLabel = UILabel()
+  let leaderLabel = UILabel()
+  let emailLabel = UILabel()
+  let phoneLabel = UILabel()
+  let dateLabel = UILabel()
+  let stackView = UIStackView()
+  let avatarView = AvatarView()
+  let stateButton = RequestCellButton()
+
+  var cancellables = Set<AnyCancellable>()
+  var didTapStateButton: (() -> Void)!
+
+  override init(frame: CGRect) {
+    super.init(frame: frame)
+    backgroundColor = Asset.neutralWhite.color
+
+    titleLabel.textColor = Asset.neutralActive.color
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
+
+    emailLabel.font = Fonts.Mulish.regular.font(size: 14.0)
+    phoneLabel.font = Fonts.Mulish.regular.font(size: 14.0)
+    leaderLabel.font = Fonts.Mulish.regular.font(size: 14.0)
+
+    emailLabel.textColor = Asset.neutralSecondaryAlternative.color
+    phoneLabel.textColor = Asset.neutralSecondaryAlternative.color
+    leaderLabel.textColor = Asset.neutralSecondaryAlternative.color
+
+    dateLabel.font = Fonts.Mulish.regular.font(size: 10.0)
+    dateLabel.textColor = Asset.neutralWeak.color
+
+    stackView.axis = .vertical
+    stackView.spacing = 4
+    stackView.addArrangedSubview(titleLabel)
+    stackView.addArrangedSubview(leaderLabel)
+    stackView.addArrangedSubview(emailLabel)
+    stackView.addArrangedSubview(phoneLabel)
+    stackView.addArrangedSubview(dateLabel)
+
+    contentView.addSubview(avatarView)
+    contentView.addSubview(stateButton)
+    contentView.addSubview(stackView)
+
+    avatarView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(15)
+      $0.width.height.equalTo(36)
+      $0.left.equalToSuperview().offset(27)
+      $0.bottom.lessThanOrEqualToSuperview().offset(-15)
     }
 
-    required init?(coder: NSCoder) { nil }
-
-    override func prepareForReuse() {
-        super.prepareForReuse()
-        titleLabel.text = nil
-        dateLabel.text = nil
-        phoneLabel.text = nil
-        emailLabel.text = nil
-        leaderLabel.text = nil
-        avatarView.prepareForReuse()
-        cancellables.removeAll()
+    stackView.snp.makeConstraints {
+      $0.top.equalTo(avatarView).offset(-5)
+      $0.left.equalTo(avatarView.snp.right).offset(20)
+      $0.right.lessThanOrEqualTo(stateButton.snp.left).offset(-20)
+      $0.bottom.lessThanOrEqualToSuperview().offset(-15)
     }
 
-    func setupFor(requestSent: RequestSent) {
-        cancellables.removeAll()
-        guard case .contact(let contact) = requestSent.request else { fatalError("A sent request -must- be of type contact") }
-
-        var phone: String?
-        if let contactPhone = contact.phone {
-            phone = "\(Country.findFrom(contactPhone).prefix) \(contactPhone.dropLast(2))"
-        }
-
-        setupContact(
-            title: (contact.nickname ?? contact.username) ?? "",
-            photo: contact.photo,
-            phone: phone,
-            email: contact.email,
-            createdAt: contact.createdAt,
-            backgroundColor: Asset.brandPrimary.color
-        )
-
-        var buttonTitle: String? = nil
-        var buttonImage: UIImage? = nil
-        var buttonTitleColor: UIColor? = nil
-
-        if requestSent.isResent {
-            buttonTitle = Localized.Requests.Cell.resent
-            buttonImage = Asset.requestsResent.image
-            buttonTitleColor = Asset.neutralWeak.color
-        } else {
-            buttonTitle = Localized.Requests.Cell.requested
-            buttonImage = Asset.requestsResend.image
-            buttonTitleColor = Asset.brandPrimary.color
-        }
-
-        setupStateButton(
-            image: buttonImage,
-            title: buttonTitle,
-            color: buttonTitleColor
-        )
+    stateButton.snp.makeConstraints {
+      $0.centerY.equalTo(stackView)
+      $0.right.equalToSuperview().offset(-24)
     }
-
-    func setupFor(requestFailed request: Request) {
-        cancellables.removeAll()
-        guard case .contact(let contact) = request else { fatalError("A failed request -must- be of type contact") }
-
-        var phone: String?
-        if let contactPhone = contact.phone {
-            phone = "\(Country.findFrom(contactPhone).prefix) \(contactPhone.dropLast(2))"
-        }
-
-        setupContact(
-            title: (contact.nickname ?? contact.username) ?? "",
-            photo: contact.photo,
-            phone: phone,
-            email: contact.email,
-            createdAt: contact.createdAt,
-            backgroundColor: Asset.brandPrimary.color
-        )
-
-        setupStateButton(
-            image: Asset.requestsResend.image,
-            title: Localized.Requests.Cell.failedRequest,
-            color: Asset.brandPrimary.color
-        )
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  override func prepareForReuse() {
+    super.prepareForReuse()
+    titleLabel.text = nil
+    dateLabel.text = nil
+    phoneLabel.text = nil
+    emailLabel.text = nil
+    leaderLabel.text = nil
+    avatarView.prepareForReuse()
+    cancellables.removeAll()
+  }
+
+  func setupFor(requestSent: RequestSent) {
+    cancellables.removeAll()
+    guard case .contact(let contact) = requestSent.request else { fatalError("A sent request -must- be of type contact") }
+
+    var phone: String?
+    if let contactPhone = contact.phone {
+      phone = "\(Country.findFrom(contactPhone).prefix) \(contactPhone.dropLast(2))"
     }
 
-    func setupFor(requestReceived: RequestReceived, isHidden: Bool = false) {
-        cancellables.removeAll()
-        guard let request = requestReceived.request else { return }
-        let color = isHidden ? Asset.neutralDisabled.color : Asset.brandPrimary.color
-
-        switch request {
-        case .group(let group):
-            setupGroup(
-                name: group.name,
-                createdAt: group.createdAt,
-                leader: requestReceived.leader,
-                backgroundColor: color
-            )
-
-        case .contact(let contact):
-
-            var phone: String?
-            if let contactPhone = contact.phone {
-                phone = "\(Country.findFrom(contactPhone).prefix) \(contactPhone.dropLast(2))"
-            }
-
-            setupContact(
-                title: (contact.nickname ?? contact.username) ?? "",
-                photo: contact.photo,
-                phone: phone,
-                email: contact.email,
-                createdAt: contact.createdAt,
-                backgroundColor: color
-            )
-
-            var buttonTitle: String? = nil
-            var buttonImage: UIImage? = nil
-            var buttonTitleColor: UIColor? = nil
-
-            switch request.status {
-            case .verified, .confirming, .failedToConfirm:
-                break // TODO: These statuses don't need UI
-
-            case .verifying:
-                buttonTitle = Localized.Requests.Cell.verifying
-                buttonTitleColor = Asset.neutralWeak.color
-
-            case .failedToVerify:
-                buttonTitle = Localized.Requests.Cell.failedVerification
-                buttonImage = Asset.requestsVerificationFailed.image
-                buttonTitleColor = Asset.accentDanger.color
-
-            case .requesting, .requested, .failedToRequest:
-                fatalError("A receivedRequest can never have the statuses: .requesting, .requested or .failedToRequest")
-            }
-
-            setupStateButton(
-                image: buttonImage,
-                title: buttonTitle,
-                color: buttonTitleColor
-            )
-        }
+    setupContact(
+      title: (contact.nickname ?? contact.username) ?? "",
+      photo: contact.photo,
+      phone: phone,
+      email: contact.email,
+      createdAt: contact.createdAt,
+      backgroundColor: Asset.brandPrimary.color
+    )
+
+    var buttonTitle: String? = nil
+    var buttonImage: UIImage? = nil
+    var buttonTitleColor: UIColor? = nil
+
+    if requestSent.isResent {
+      buttonTitle = Localized.Requests.Cell.resent
+      buttonImage = Asset.requestsResent.image
+      buttonTitleColor = Asset.neutralWeak.color
+    } else {
+      buttonTitle = Localized.Requests.Cell.requested
+      buttonImage = Asset.requestsResend.image
+      buttonTitleColor = Asset.brandPrimary.color
     }
 
-    private func setupContact(
-        title: String,
-        photo: Data?,
-        phone: String?,
-        email: String?,
-        createdAt: Date,
-        backgroundColor: UIColor
-    ) {
-        titleLabel.text = title
-        phoneLabel.text = phone
-        emailLabel.text = email
-        dateLabel.text = createdAt.asRelativeFromNow()
-        avatarView.setupProfile(title: title, image: photo, size: .small)
-
-        leaderLabel.isHidden = true
-        phoneLabel.isHidden = phone == nil
-        emailLabel.isHidden = email == nil
-        avatarView.backgroundColor = backgroundColor
-    }
+    setupStateButton(
+      image: buttonImage,
+      title: buttonTitle,
+      color: buttonTitleColor
+    )
+  }
+
+  func setupFor(requestFailed request: Request) {
+    cancellables.removeAll()
+    guard case .contact(let contact) = request else { fatalError("A failed request -must- be of type contact") }
 
-    private func setupGroup(
-        name: String,
-        createdAt: Date,
-        leader: String?,
-        backgroundColor: UIColor
-    ) {
-        titleLabel.text = name
-        stateButton.imageView.image = nil
-        stateButton.titleLabel.text = nil
-        avatarView.setupGroup(size: .small)
-        dateLabel.text = createdAt.asRelativeFromNow()
-
-        leaderLabel.text = leader
-        leaderLabel.isHidden = false
-        phoneLabel.isHidden = true
-        emailLabel.isHidden = true
-        avatarView.backgroundColor = backgroundColor
+    var phone: String?
+    if let contactPhone = contact.phone {
+      phone = "\(Country.findFrom(contactPhone).prefix) \(contactPhone.dropLast(2))"
     }
 
-    private func setupStateButton(
-        image: UIImage?,
-        title: String?,
-        color: UIColor?
-    ) {
-        stateButton.imageView.image = image
-        stateButton.titleLabel.text = title
-        stateButton.titleLabel.textColor = color
-
-        stateButton
-            .publisher(for: .touchUpInside)
-            .sink { [unowned self] in didTapStateButton() }
-            .store(in: &cancellables)
+    setupContact(
+      title: (contact.nickname ?? contact.username) ?? "",
+      photo: contact.photo,
+      phone: phone,
+      email: contact.email,
+      createdAt: contact.createdAt,
+      backgroundColor: Asset.brandPrimary.color
+    )
+
+    setupStateButton(
+      image: Asset.requestsResend.image,
+      title: Localized.Requests.Cell.failedRequest,
+      color: Asset.brandPrimary.color
+    )
+  }
+
+  func setupFor(requestReceived: RequestReceived, isHidden: Bool = false) {
+    cancellables.removeAll()
+    guard let request = requestReceived.request else { return }
+    let color = isHidden ? Asset.neutralDisabled.color : Asset.brandPrimary.color
+
+    switch request {
+    case .group(let group):
+      setupGroup(
+        name: group.name,
+        createdAt: group.createdAt,
+        leader: requestReceived.leader,
+        backgroundColor: color
+      )
+
+    case .contact(let contact):
+
+      var phone: String?
+      if let contactPhone = contact.phone {
+        phone = "\(Country.findFrom(contactPhone).prefix) \(contactPhone.dropLast(2))"
+      }
+
+      setupContact(
+        title: (contact.nickname ?? contact.username) ?? "",
+        photo: contact.photo,
+        phone: phone,
+        email: contact.email,
+        createdAt: contact.createdAt,
+        backgroundColor: color
+      )
+
+      var buttonTitle: String? = nil
+      var buttonImage: UIImage? = nil
+      var buttonTitleColor: UIColor? = nil
+
+      switch request.status {
+      case .verified, .confirming, .failedToConfirm:
+        break // TODO: These statuses don't need UI
+
+      case .verifying:
+        buttonTitle = Localized.Requests.Cell.verifying
+        buttonTitleColor = Asset.neutralWeak.color
+
+      case .failedToVerify:
+        buttonTitle = Localized.Requests.Cell.failedVerification
+        buttonImage = Asset.requestsVerificationFailed.image
+        buttonTitleColor = Asset.accentDanger.color
+
+      case .requesting, .requested, .failedToRequest:
+        fatalError("A receivedRequest can never have the statuses: .requesting, .requested or .failedToRequest")
+      }
+
+      setupStateButton(
+        image: buttonImage,
+        title: buttonTitle,
+        color: buttonTitleColor
+      )
     }
+  }
+
+  private func setupContact(
+    title: String,
+    photo: Data?,
+    phone: String?,
+    email: String?,
+    createdAt: Date,
+    backgroundColor: UIColor
+  ) {
+    titleLabel.text = title
+    phoneLabel.text = phone
+    emailLabel.text = email
+    dateLabel.text = createdAt.asRelativeFromNow()
+    avatarView.setupProfile(title: title, image: photo, size: .small)
+
+    leaderLabel.isHidden = true
+    phoneLabel.isHidden = phone == nil
+    emailLabel.isHidden = email == nil
+    avatarView.backgroundColor = backgroundColor
+  }
+
+  private func setupGroup(
+    name: String,
+    createdAt: Date,
+    leader: String?,
+    backgroundColor: UIColor
+  ) {
+    titleLabel.text = name
+    stateButton.imageView.image = nil
+    stateButton.titleLabel.text = nil
+    avatarView.setupGroup(size: .small)
+    dateLabel.text = createdAt.asRelativeFromNow()
+
+    leaderLabel.text = leader
+    leaderLabel.isHidden = false
+    phoneLabel.isHidden = true
+    emailLabel.isHidden = true
+    avatarView.backgroundColor = backgroundColor
+  }
+
+  private func setupStateButton(
+    image: UIImage?,
+    title: String?,
+    color: UIColor?
+  ) {
+    stateButton.imageView.image = image
+    stateButton.titleLabel.text = title
+    stateButton.titleLabel.textColor = color
+
+    stateButton
+      .publisher(for: .touchUpInside)
+      .sink { [unowned self] in didTapStateButton() }
+      .store(in: &cancellables)
+  }
 }
 
diff --git a/Sources/RequestsFeature/Views/RequestCellButton.swift b/Sources/RequestsFeature/Views/RequestCellButton.swift
index 22332912310da3912439621b425f614b1123a32d..b876ba691252c0a938ea40e162856a4102fb0ae2 100644
--- a/Sources/RequestsFeature/Views/RequestCellButton.swift
+++ b/Sources/RequestsFeature/Views/RequestCellButton.swift
@@ -2,34 +2,34 @@ import UIKit
 import Shared
 
 final class RequestCellButton: UIControl {
-    let titleLabel = UILabel()
-    let imageView = UIImageView()
-
-    init() {
-        super.init(frame: .zero)
-        titleLabel.numberOfLines = 0
-        titleLabel.textAlignment = .right
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
-
-        addSubview(imageView)
-        addSubview(titleLabel)
-
-        imageView.snp.makeConstraints {
-            $0.top.greaterThanOrEqualToSuperview()
-            $0.left.equalToSuperview()
-            $0.centerY.equalToSuperview()
-            $0.bottom.lessThanOrEqualToSuperview()
-        }
-
-        titleLabel.snp.makeConstraints {
-            $0.top.greaterThanOrEqualToSuperview()
-            $0.left.equalTo(imageView.snp.right).offset(5)
-            $0.centerY.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.width.equalTo(60)
-            $0.bottom.lessThanOrEqualToSuperview()
-        }
+  let titleLabel = UILabel()
+  let imageView = UIImageView()
+  
+  init() {
+    super.init(frame: .zero)
+    titleLabel.numberOfLines = 0
+    titleLabel.textAlignment = .right
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
+    
+    addSubview(imageView)
+    addSubview(titleLabel)
+    
+    imageView.snp.makeConstraints {
+      $0.top.greaterThanOrEqualToSuperview()
+      $0.left.equalToSuperview()
+      $0.centerY.equalToSuperview()
+      $0.bottom.lessThanOrEqualToSuperview()
     }
-
-    required init?(coder: NSCoder) { nil }
+    
+    titleLabel.snp.makeConstraints {
+      $0.top.greaterThanOrEqualToSuperview()
+      $0.left.equalTo(imageView.snp.right).offset(5)
+      $0.centerY.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.width.equalTo(60)
+      $0.bottom.lessThanOrEqualToSuperview()
+    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/RequestsFeature/Views/RequestReceivedEmptyCell.swift b/Sources/RequestsFeature/Views/RequestReceivedEmptyCell.swift
index bf706b39c5eded757bcb02eeac4c0092c9f409e1..574d63b624404285a5c1310706453bbd2f0b8d63 100644
--- a/Sources/RequestsFeature/Views/RequestReceivedEmptyCell.swift
+++ b/Sources/RequestsFeature/Views/RequestReceivedEmptyCell.swift
@@ -2,33 +2,33 @@ import UIKit
 import Shared
 
 final class RequestReceivedEmptyCell: UICollectionViewCell {
-    private let titleLabel = UILabel()
-
-    override init(frame: CGRect) {
-        super.init(frame: frame)
-        titleLabel.textAlignment = .center
-        titleLabel.textColor = Asset.neutralWeak.color
-        titleLabel.font = Fonts.Mulish.regular.font(size: 14.0)
-        titleLabel.text = Localized.Requests.Received.placeholder
-
-        contentView.addSubview(titleLabel)
-
-        titleLabel.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(50)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview().offset(-50)
-        }
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    override func prepareForReuse() {
-        super.prepareForReuse()
-        titleLabel.text = nil
-    }
-
-    func setup(title: String) {
-        titleLabel.text = title
+  private let titleLabel = UILabel()
+  
+  override init(frame: CGRect) {
+    super.init(frame: frame)
+    titleLabel.textAlignment = .center
+    titleLabel.textColor = Asset.neutralWeak.color
+    titleLabel.font = Fonts.Mulish.regular.font(size: 14.0)
+    titleLabel.text = Localized.Requests.Received.placeholder
+    
+    contentView.addSubview(titleLabel)
+    
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(50)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview().offset(-50)
     }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  override func prepareForReuse() {
+    super.prepareForReuse()
+    titleLabel.text = nil
+  }
+  
+  func setup(title: String) {
+    titleLabel.text = title
+  }
 }
diff --git a/Sources/RequestsFeature/Views/RequestSegmentedButton.swift b/Sources/RequestsFeature/Views/RequestSegmentedButton.swift
index 22bd81e2da7387b54c70f93f8c8528cb4d0dc031..36077491610b6f25bddebd8bc5801058c4d634ca 100644
--- a/Sources/RequestsFeature/Views/RequestSegmentedButton.swift
+++ b/Sources/RequestsFeature/Views/RequestSegmentedButton.swift
@@ -2,31 +2,31 @@ import UIKit
 import Shared
 
 final class RequestSegmentedButton: UIControl {
-    let titleLabel = UILabel()
-    let imageView = UIImageView()
-
-    init() {
-        super.init(frame: .zero)
-
-        titleLabel.textAlignment = .center
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
-        imageView.setContentCompressionResistancePriority(.required, for: .vertical)
-        titleLabel.setContentCompressionResistancePriority(.required, for: .vertical)
-
-        addSubview(titleLabel)
-        addSubview(imageView)
-
-        imageView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(7.5)
-            $0.centerX.equalTo(titleLabel)
-        }
-
-        titleLabel.snp.makeConstraints {
-            $0.top.equalTo(imageView.snp.bottom).offset(2)
-            $0.centerX.equalToSuperview()
-            $0.bottom.equalToSuperview().offset(-7.5)
-        }
+  let titleLabel = UILabel()
+  let imageView = UIImageView()
+  
+  init() {
+    super.init(frame: .zero)
+    
+    titleLabel.textAlignment = .center
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    imageView.setContentCompressionResistancePriority(.required, for: .vertical)
+    titleLabel.setContentCompressionResistancePriority(.required, for: .vertical)
+    
+    addSubview(titleLabel)
+    addSubview(imageView)
+    
+    imageView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(7.5)
+      $0.centerX.equalTo(titleLabel)
     }
-
-    required init?(coder: NSCoder) { nil }
+    
+    titleLabel.snp.makeConstraints {
+      $0.top.equalTo(imageView.snp.bottom).offset(2)
+      $0.centerX.equalToSuperview()
+      $0.bottom.equalToSuperview().offset(-7.5)
+    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/RequestsFeature/Views/RequestsContainerView.swift b/Sources/RequestsFeature/Views/RequestsContainerView.swift
index 80cd844a803dd38d4cce568d5d077bb0b2e1a66d..a5188d080d1773a256ffb06cc6b8f7376c243f2b 100644
--- a/Sources/RequestsFeature/Views/RequestsContainerView.swift
+++ b/Sources/RequestsFeature/Views/RequestsContainerView.swift
@@ -2,57 +2,57 @@ import UIKit
 import Shared
 
 final class RequestsContainerView: UIView {
-    let scrollView = UIScrollView()
-    let sentController = RequestsSentController()
-    let failedController = RequestsFailedController()
-    let receivedController = RequestsReceivedController()
-    let segmentedControl = RequestsSegmentedControl()
-
-    init() {
-        super.init(frame: .zero)
-        scrollView.bounces = false
-        scrollView.isScrollEnabled = false
-        backgroundColor = Asset.neutralWhite.color
-
-        scrollView.addSubview(sentController.view)
-        scrollView.addSubview(failedController.view)
-        scrollView.addSubview(receivedController.view)
-        addSubview(segmentedControl)
-        addSubview(scrollView)
-
-        scrollView.snp.makeConstraints {
-            $0.edges.equalToSuperview()
-        }
-
-        segmentedControl.snp.makeConstraints {
-            $0.top.equalTo(safeAreaLayoutGuide).offset(10)
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.height.equalTo(60)
-        }
-
-        receivedController.view.snp.makeConstraints {
-            $0.top.equalTo(segmentedControl.snp.bottom)
-            $0.left.equalToSuperview()
-            $0.right.equalTo(sentController.view.snp.left)
-            $0.bottom.equalTo(self)
-            $0.width.equalTo(self)
-        }
-
-        sentController.view.snp.makeConstraints {
-            $0.top.equalTo(segmentedControl.snp.bottom)
-            $0.right.equalTo(failedController.view.snp.left)
-            $0.bottom.equalTo(self)
-            $0.width.equalTo(self)
-        }
-
-        failedController.view.snp.makeConstraints {
-            $0.top.equalTo(segmentedControl.snp.bottom)
-            $0.right.equalToSuperview()
-            $0.bottom.equalTo(self)
-            $0.width.equalTo(self)
-        }
+  let scrollView = UIScrollView()
+  let sentController = RequestsSentController()
+  let failedController = RequestsFailedController()
+  let receivedController = RequestsReceivedController()
+  let segmentedControl = RequestsSegmentedControl()
+  
+  init() {
+    super.init(frame: .zero)
+    scrollView.bounces = false
+    scrollView.isScrollEnabled = false
+    backgroundColor = Asset.neutralWhite.color
+    
+    scrollView.addSubview(sentController.view)
+    scrollView.addSubview(failedController.view)
+    scrollView.addSubview(receivedController.view)
+    addSubview(segmentedControl)
+    addSubview(scrollView)
+    
+    scrollView.snp.makeConstraints {
+      $0.edges.equalToSuperview()
     }
-
-    required init?(coder: NSCoder) { nil }
+    
+    segmentedControl.snp.makeConstraints {
+      $0.top.equalTo(safeAreaLayoutGuide).offset(10)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.height.equalTo(60)
+    }
+    
+    receivedController.view.snp.makeConstraints {
+      $0.top.equalTo(segmentedControl.snp.bottom)
+      $0.left.equalToSuperview()
+      $0.right.equalTo(sentController.view.snp.left)
+      $0.bottom.equalTo(self)
+      $0.width.equalTo(self)
+    }
+    
+    sentController.view.snp.makeConstraints {
+      $0.top.equalTo(segmentedControl.snp.bottom)
+      $0.right.equalTo(failedController.view.snp.left)
+      $0.bottom.equalTo(self)
+      $0.width.equalTo(self)
+    }
+    
+    failedController.view.snp.makeConstraints {
+      $0.top.equalTo(segmentedControl.snp.bottom)
+      $0.right.equalToSuperview()
+      $0.bottom.equalTo(self)
+      $0.width.equalTo(self)
+    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/RequestsFeature/Views/RequestsFailedView.swift b/Sources/RequestsFeature/Views/RequestsFailedView.swift
index 76f4adadd7e15d27781e944bd957427629c74379..86d76dc764f89478da0c6b4df19b02c95b02ebd4 100644
--- a/Sources/RequestsFeature/Views/RequestsFailedView.swift
+++ b/Sources/RequestsFeature/Views/RequestsFailedView.swift
@@ -2,39 +2,39 @@ import UIKit
 import Shared
 
 final class RequestsFailedView: UIView {
-    let titleLabel = UILabel()
-
-    lazy var collectionView: UICollectionView = {
-        var config = UICollectionLayoutListConfiguration(appearance: .plain)
-        config.backgroundColor = Asset.neutralWhite.color
-        config.showsSeparators = false
-        let layout = UICollectionViewCompositionalLayout.list(using: config)
-        let collectionView = UICollectionView(frame: bounds, collectionViewLayout: layout)
-        collectionView.contentInset = .init(top: 15, left: 0, bottom: 0, right: 0)
-        return collectionView
-    }()
-
-    init() {
-        super.init(frame: .zero)
-
-        titleLabel.textAlignment = .center
-        titleLabel.text = Localized.Requests.Failed.empty
-        titleLabel.textColor = Asset.neutralWeak.color
-        titleLabel.font = Fonts.Mulish.regular.font(size: 14.0)
-
-        addSubview(titleLabel)
-        addSubview(collectionView)
-
-        titleLabel.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(48.5)
-            $0.left.equalToSuperview().offset(24)
-            $0.right.equalToSuperview().offset(-24)
-        }
-
-        collectionView.snp.makeConstraints {
-            $0.edges.equalToSuperview()
-        }
+  let titleLabel = UILabel()
+  
+  lazy var collectionView: UICollectionView = {
+    var config = UICollectionLayoutListConfiguration(appearance: .plain)
+    config.backgroundColor = Asset.neutralWhite.color
+    config.showsSeparators = false
+    let layout = UICollectionViewCompositionalLayout.list(using: config)
+    let collectionView = UICollectionView(frame: bounds, collectionViewLayout: layout)
+    collectionView.contentInset = .init(top: 15, left: 0, bottom: 0, right: 0)
+    return collectionView
+  }()
+  
+  init() {
+    super.init(frame: .zero)
+    
+    titleLabel.textAlignment = .center
+    titleLabel.text = Localized.Requests.Failed.empty
+    titleLabel.textColor = Asset.neutralWeak.color
+    titleLabel.font = Fonts.Mulish.regular.font(size: 14.0)
+    
+    addSubview(titleLabel)
+    addSubview(collectionView)
+    
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(48.5)
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
     }
-
-    required init?(coder: NSCoder) { nil }
+    
+    collectionView.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/RequestsFeature/Views/RequestsHiddenSectionHeader.swift b/Sources/RequestsFeature/Views/RequestsHiddenSectionHeader.swift
index f6fab012ee3b934ae1adbd31dd54c10857fe9e7d..7a8aed798d0c459ce1dd48c028ff12a23dab195f 100644
--- a/Sources/RequestsFeature/Views/RequestsHiddenSectionHeader.swift
+++ b/Sources/RequestsFeature/Views/RequestsHiddenSectionHeader.swift
@@ -3,62 +3,62 @@ import Shared
 import Combine
 
 final class RequestsHiddenSectionHeader: UICollectionReusableView {
-    let titleLabel = UILabel()
-    let separatorView = UIView()
-    let switcherView = UISwitch()
-    var cancellables = Set<AnyCancellable>()
-
-    override func prepareForReuse() {
-        super.prepareForReuse()
-        cancellables.removeAll()
+  let titleLabel = UILabel()
+  let separatorView = UIView()
+  let switcherView = UISwitch()
+  var cancellables = Set<AnyCancellable>()
+  
+  override func prepareForReuse() {
+    super.prepareForReuse()
+    cancellables.removeAll()
+  }
+  
+  override init(frame: CGRect) {
+    super.init(frame: frame)
+    
+    titleLabel.text = Localized.Requests.Received.hidden
+    titleLabel.textColor = Asset.neutralActive.color
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
+    separatorView.backgroundColor = Asset.neutralLine.color
+    switcherView.onTintColor = Asset.brandPrimary.color
+    
+    addSubview(titleLabel)
+    addSubview(switcherView)
+    addSubview(separatorView)
+    
+    separatorView.snp.makeConstraints {
+      $0.height.equalTo(1)
+      $0.top.equalToSuperview().offset(10)
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
     }
-
-    override init(frame: CGRect) {
-        super.init(frame: frame)
-
-        titleLabel.text = Localized.Requests.Received.hidden
-        titleLabel.textColor = Asset.neutralActive.color
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
-        separatorView.backgroundColor = Asset.neutralLine.color
-        switcherView.onTintColor = Asset.brandPrimary.color
-
-        addSubview(titleLabel)
-        addSubview(switcherView)
-        addSubview(separatorView)
-
-        separatorView.snp.makeConstraints {
-            $0.height.equalTo(1)
-            $0.top.equalToSuperview().offset(10)
-            $0.left.equalToSuperview().offset(24)
-            $0.right.equalToSuperview().offset(-24)
-        }
-
-        titleLabel.snp.makeConstraints {
-            $0.top.equalTo(separatorView.snp.bottom).offset(30)
-            $0.left.equalToSuperview().offset(24)
-            $0.bottom.equalToSuperview().offset(-20)
-        }
-
-        switcherView.snp.makeConstraints {
-            $0.centerY.equalTo(titleLabel)
-            $0.right.equalToSuperview().offset(-24)
-        }
+    
+    titleLabel.snp.makeConstraints {
+      $0.top.equalTo(separatorView.snp.bottom).offset(30)
+      $0.left.equalToSuperview().offset(24)
+      $0.bottom.equalToSuperview().offset(-20)
     }
-
-    required init?(coder: NSCoder) { nil }
+    
+    switcherView.snp.makeConstraints {
+      $0.centerY.equalTo(titleLabel)
+      $0.right.equalToSuperview().offset(-24)
+    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
 
 final class RequestsBlankSectionHeader: UICollectionReusableView {
-    private let view = UIView()
-
-    override init(frame: CGRect) {
-        super.init(frame: frame)
-        addSubview(view)
-        view.snp.makeConstraints {
-            $0.edges.equalToSuperview()
-            $0.height.equalTo(1)
-        }
+  private let view = UIView()
+  
+  override init(frame: CGRect) {
+    super.init(frame: frame)
+    addSubview(view)
+    view.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+      $0.height.equalTo(1)
     }
-
-    required init?(coder: NSCoder) { nil }
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/RequestsFeature/Views/RequestsReceivedView.swift b/Sources/RequestsFeature/Views/RequestsReceivedView.swift
index d4df66fea6dae47ee46dac61451f45a05fa2b4e7..f8c55b664deabb2c5bc0cff54e2246d048907f6b 100644
--- a/Sources/RequestsFeature/Views/RequestsReceivedView.swift
+++ b/Sources/RequestsFeature/Views/RequestsReceivedView.swift
@@ -2,51 +2,51 @@ import UIKit
 import Shared
 
 final class RequestsReceivedView: UIView {
-    lazy var collectionView: UICollectionView = {
-        let itemSize = NSCollectionLayoutSize(
-            widthDimension: .fractionalWidth(1),
-            heightDimension: .estimated(1)
-        )
-
-        let item = NSCollectionLayoutItem(layoutSize: itemSize)
-
-        let groupSize = NSCollectionLayoutSize(
-            widthDimension: .fractionalWidth(1),
-            heightDimension: .estimated(1)
-        )
-
-        let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
-
-        let section = NSCollectionLayoutSection(group: group)
-        section.interGroupSpacing = 5
-        section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10)
-
-        let headerFooterSize = NSCollectionLayoutSize(
-            widthDimension: .fractionalWidth(1.0),
-            heightDimension: .estimated(44)
-        )
-
-        let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem(
-            layoutSize: headerFooterSize,
-            elementKind: UICollectionView.elementKindSectionHeader,
-            alignment: .top
-        )
-
-        section.boundarySupplementaryItems = [sectionHeader]
-        let layout = UICollectionViewCompositionalLayout(section: section)
-
-        let collectionView = UICollectionView(frame: bounds, collectionViewLayout: layout)
-        collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
-        collectionView.backgroundColor = Asset.neutralWhite.color
-        collectionView.contentInset = .init(top: 15, left: 0, bottom: 0, right: 0)
-        return collectionView
-    }()
-
-    init() {
-        super.init(frame: .zero)
-        addSubview(collectionView)
-    }
-
-    required init?(coder: NSCoder) { nil }
+  lazy var collectionView: UICollectionView = {
+    let itemSize = NSCollectionLayoutSize(
+      widthDimension: .fractionalWidth(1),
+      heightDimension: .estimated(1)
+    )
+    
+    let item = NSCollectionLayoutItem(layoutSize: itemSize)
+    
+    let groupSize = NSCollectionLayoutSize(
+      widthDimension: .fractionalWidth(1),
+      heightDimension: .estimated(1)
+    )
+    
+    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
+    
+    let section = NSCollectionLayoutSection(group: group)
+    section.interGroupSpacing = 5
+    section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 10, bottom: 0, trailing: 10)
+    
+    let headerFooterSize = NSCollectionLayoutSize(
+      widthDimension: .fractionalWidth(1.0),
+      heightDimension: .estimated(44)
+    )
+    
+    let sectionHeader = NSCollectionLayoutBoundarySupplementaryItem(
+      layoutSize: headerFooterSize,
+      elementKind: UICollectionView.elementKindSectionHeader,
+      alignment: .top
+    )
+    
+    section.boundarySupplementaryItems = [sectionHeader]
+    let layout = UICollectionViewCompositionalLayout(section: section)
+    
+    let collectionView = UICollectionView(frame: bounds, collectionViewLayout: layout)
+    collectionView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
+    collectionView.backgroundColor = Asset.neutralWhite.color
+    collectionView.contentInset = .init(top: 15, left: 0, bottom: 0, right: 0)
+    return collectionView
+  }()
+  
+  init() {
+    super.init(frame: .zero)
+    addSubview(collectionView)
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
 
diff --git a/Sources/RequestsFeature/Views/RequestsSegmentedControl.swift b/Sources/RequestsFeature/Views/RequestsSegmentedControl.swift
index 0bdea739207c2b2a73cba676d40df85eac85d946..d58fbf874ba461f7ee112732fd88c8fed8075a30 100644
--- a/Sources/RequestsFeature/Views/RequestsSegmentedControl.swift
+++ b/Sources/RequestsFeature/Views/RequestsSegmentedControl.swift
@@ -3,92 +3,92 @@ import Shared
 import SnapKit
 
 final class RequestsSegmentedControl: UIView {
-    private let trackView = UIView()
-    private let stackView = UIStackView()
-    private var leftConstraint: Constraint?
-    private let trackIndicatorView = UIView()
-    private(set) var sentRequestsButton = RequestSegmentedButton()
-    private(set) var failedRequestsButton = RequestSegmentedButton()
-    private(set) var receivedRequestsButton = RequestSegmentedButton()
-
-    init() {
-        super.init(frame: .zero)
-        trackView.backgroundColor = Asset.neutralLine.color
-        trackIndicatorView.backgroundColor = Asset.brandPrimary.color
-
-        sentRequestsButton.titleLabel.text = Localized.Requests.Sent.title
-        failedRequestsButton.titleLabel.text = Localized.Requests.Failed.title
-        receivedRequestsButton.titleLabel.text = Localized.Requests.Received.title
-
-        sentRequestsButton.titleLabel.textColor = Asset.neutralDisabled.color
-        failedRequestsButton.titleLabel.textColor = Asset.neutralDisabled.color
-        receivedRequestsButton.titleLabel.textColor = Asset.brandPrimary.color
-
-        sentRequestsButton.imageView.tintColor = Asset.neutralDisabled.color
-        failedRequestsButton.imageView.tintColor = Asset.neutralDisabled.color
-        receivedRequestsButton.imageView.tintColor = Asset.brandPrimary.color
-
-        sentRequestsButton.imageView.image = Asset.requestsTabSent.image
-        failedRequestsButton.imageView.image = Asset.requestsTabFailed.image
-        receivedRequestsButton.imageView.image = Asset.requestsTabReceived.image
-        
-        stackView.addArrangedSubview(receivedRequestsButton)
-        stackView.addArrangedSubview(sentRequestsButton)
-        stackView.addArrangedSubview(failedRequestsButton)
-        stackView.distribution = .fillEqually
-        stackView.backgroundColor = Asset.neutralWhite.color
-
-        addSubview(stackView)
-        addSubview(trackView)
-        trackView.addSubview(trackIndicatorView)
-
-        stackView.snp.makeConstraints {
-            $0.edges.equalToSuperview()
-        }
-
-        trackView.snp.makeConstraints {
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-            $0.height.equalTo(2)
-        }
-
-        trackIndicatorView.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            leftConstraint = $0.left.equalToSuperview().constraint
-            $0.width.equalToSuperview().dividedBy(3)
-            $0.bottom.equalToSuperview()
-        }
-
-        sentRequestsButton.accessibilityIdentifier = Localized.Accessibility.Requests.Sent.tab
-        failedRequestsButton.accessibilityIdentifier = Localized.Accessibility.Requests.Failed.tab
-        receivedRequestsButton.accessibilityIdentifier = Localized.Accessibility.Requests.Received.tab
+  private let trackView = UIView()
+  private let stackView = UIStackView()
+  private var leftConstraint: Constraint?
+  private let trackIndicatorView = UIView()
+  private(set) var sentRequestsButton = RequestSegmentedButton()
+  private(set) var failedRequestsButton = RequestSegmentedButton()
+  private(set) var receivedRequestsButton = RequestSegmentedButton()
+  
+  init() {
+    super.init(frame: .zero)
+    trackView.backgroundColor = Asset.neutralLine.color
+    trackIndicatorView.backgroundColor = Asset.brandPrimary.color
+    
+    sentRequestsButton.titleLabel.text = Localized.Requests.Sent.title
+    failedRequestsButton.titleLabel.text = Localized.Requests.Failed.title
+    receivedRequestsButton.titleLabel.text = Localized.Requests.Received.title
+    
+    sentRequestsButton.titleLabel.textColor = Asset.neutralDisabled.color
+    failedRequestsButton.titleLabel.textColor = Asset.neutralDisabled.color
+    receivedRequestsButton.titleLabel.textColor = Asset.brandPrimary.color
+    
+    sentRequestsButton.imageView.tintColor = Asset.neutralDisabled.color
+    failedRequestsButton.imageView.tintColor = Asset.neutralDisabled.color
+    receivedRequestsButton.imageView.tintColor = Asset.brandPrimary.color
+    
+    sentRequestsButton.imageView.image = Asset.requestsTabSent.image
+    failedRequestsButton.imageView.image = Asset.requestsTabFailed.image
+    receivedRequestsButton.imageView.image = Asset.requestsTabReceived.image
+    
+    stackView.addArrangedSubview(receivedRequestsButton)
+    stackView.addArrangedSubview(sentRequestsButton)
+    stackView.addArrangedSubview(failedRequestsButton)
+    stackView.distribution = .fillEqually
+    stackView.backgroundColor = Asset.neutralWhite.color
+    
+    addSubview(stackView)
+    addSubview(trackView)
+    trackView.addSubview(trackIndicatorView)
+    
+    stackView.snp.makeConstraints {
+      $0.edges.equalToSuperview()
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    func updateSwipePercentage(_ percentageScrolled: CGFloat) {
-        let amountOfTabs = 3.0
-        let tabWidth = bounds.width / amountOfTabs
-        let leftOffset = percentageScrolled * tabWidth
-
-        leftConstraint?.update(offset: leftOffset)
-
-        let receivedPercentage = percentageScrolled > 1 ? 1 : percentageScrolled
-        let failedPercentage = percentageScrolled <= 1 ? 0 : percentageScrolled - 1
-        let sentPercentage = percentageScrolled > 1 ? 1 - (percentageScrolled-1) : percentageScrolled
-
-        let sentColor = UIColor.fade(from: Asset.neutralDisabled.color, to: Asset.brandPrimary.color, pcent: sentPercentage)
-        let failedColor = UIColor.fade(from: Asset.neutralDisabled.color, to: Asset.brandPrimary.color, pcent: failedPercentage)
-        let receivedColor = UIColor.fade(from: Asset.brandPrimary.color, to: Asset.neutralDisabled.color, pcent: receivedPercentage)
-
-        sentRequestsButton.imageView.tintColor = sentColor
-        sentRequestsButton.titleLabel.textColor = sentColor
-
-        failedRequestsButton.imageView.tintColor = failedColor
-        failedRequestsButton.titleLabel.textColor = failedColor
-
-        receivedRequestsButton.imageView.tintColor = receivedColor
-        receivedRequestsButton.titleLabel.textColor = receivedColor
+    
+    trackView.snp.makeConstraints {
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+      $0.height.equalTo(2)
+    }
+    
+    trackIndicatorView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      leftConstraint = $0.left.equalToSuperview().constraint
+      $0.width.equalToSuperview().dividedBy(3)
+      $0.bottom.equalToSuperview()
     }
+    
+    sentRequestsButton.accessibilityIdentifier = Localized.Accessibility.Requests.Sent.tab
+    failedRequestsButton.accessibilityIdentifier = Localized.Accessibility.Requests.Failed.tab
+    receivedRequestsButton.accessibilityIdentifier = Localized.Accessibility.Requests.Received.tab
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  func updateSwipePercentage(_ percentageScrolled: CGFloat) {
+    let amountOfTabs = 3.0
+    let tabWidth = bounds.width / amountOfTabs
+    let leftOffset = percentageScrolled * tabWidth
+    
+    leftConstraint?.update(offset: leftOffset)
+    
+    let receivedPercentage = percentageScrolled > 1 ? 1 : percentageScrolled
+    let failedPercentage = percentageScrolled <= 1 ? 0 : percentageScrolled - 1
+    let sentPercentage = percentageScrolled > 1 ? 1 - (percentageScrolled-1) : percentageScrolled
+    
+    let sentColor = UIColor.fade(from: Asset.neutralDisabled.color, to: Asset.brandPrimary.color, pcent: sentPercentage)
+    let failedColor = UIColor.fade(from: Asset.neutralDisabled.color, to: Asset.brandPrimary.color, pcent: failedPercentage)
+    let receivedColor = UIColor.fade(from: Asset.brandPrimary.color, to: Asset.neutralDisabled.color, pcent: receivedPercentage)
+    
+    sentRequestsButton.imageView.tintColor = sentColor
+    sentRequestsButton.titleLabel.textColor = sentColor
+    
+    failedRequestsButton.imageView.tintColor = failedColor
+    failedRequestsButton.titleLabel.textColor = failedColor
+    
+    receivedRequestsButton.imageView.tintColor = receivedColor
+    receivedRequestsButton.titleLabel.textColor = receivedColor
+  }
 }
diff --git a/Sources/RequestsFeature/Views/RequestsSentView.swift b/Sources/RequestsFeature/Views/RequestsSentView.swift
index 9150c06bcb745e56036ff809568a4a4fbd2f351e..6c65a92b91b99464a4a1d7e3210ff655465987ba 100644
--- a/Sources/RequestsFeature/Views/RequestsSentView.swift
+++ b/Sources/RequestsFeature/Views/RequestsSentView.swift
@@ -2,52 +2,52 @@ import UIKit
 import Shared
 
 final class RequestsSentView: UIView {
-    let titleLabel = UILabel()
-    let connectionsButton = CapsuleButton()
-
-    lazy var collectionView: UICollectionView = {
-        var config = UICollectionLayoutListConfiguration(appearance: .plain)
-        config.backgroundColor = Asset.neutralWhite.color
-        config.showsSeparators = false
-        let layout = UICollectionViewCompositionalLayout.list(using: config)
-        let collectionView = UICollectionView(frame: bounds, collectionViewLayout: layout)
-        collectionView.contentInset = .init(top: 15, left: 0, bottom: 0, right: 0)
-        return collectionView
-    }()
-
-    init() {
-        super.init(frame: .zero)
-
-        titleLabel.textAlignment = .center
-        titleLabel.text = Localized.Requests.Sent.empty
-        titleLabel.textColor = Asset.neutralWeak.color
-        titleLabel.font = Fonts.Mulish.regular.font(size: 14.0)
-
-        connectionsButton.set(
-            style: .brandColored,
-            title: Localized.Requests.Sent.action
-        )
-
-        addSubview(titleLabel)
-        addSubview(connectionsButton)
-        addSubview(collectionView)
-
-        titleLabel.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(48.5)
-            $0.left.equalToSuperview().offset(24)
-            $0.right.equalToSuperview().offset(-24)
-        }
-
-        connectionsButton.snp.makeConstraints {
-            $0.left.equalToSuperview().offset(24)
-            $0.right.equalToSuperview().offset(-24)
-            $0.bottom.equalTo(safeAreaLayoutGuide).offset(-16)
-        }
-
-        collectionView.snp.makeConstraints {
-            $0.edges.equalToSuperview()
-        }
+  let titleLabel = UILabel()
+  let connectionsButton = CapsuleButton()
+
+  lazy var collectionView: UICollectionView = {
+    var config = UICollectionLayoutListConfiguration(appearance: .plain)
+    config.backgroundColor = Asset.neutralWhite.color
+    config.showsSeparators = false
+    let layout = UICollectionViewCompositionalLayout.list(using: config)
+    let collectionView = UICollectionView(frame: bounds, collectionViewLayout: layout)
+    collectionView.contentInset = .init(top: 15, left: 0, bottom: 0, right: 0)
+    return collectionView
+  }()
+
+  init() {
+    super.init(frame: .zero)
+
+    titleLabel.textAlignment = .center
+    titleLabel.text = Localized.Requests.Sent.empty
+    titleLabel.textColor = Asset.neutralWeak.color
+    titleLabel.font = Fonts.Mulish.regular.font(size: 14.0)
+
+    connectionsButton.set(
+      style: .brandColored,
+      title: Localized.Requests.Sent.action
+    )
+
+    addSubview(titleLabel)
+    addSubview(connectionsButton)
+    addSubview(collectionView)
+
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(48.5)
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
     }
 
-    required init?(coder: NSCoder) { nil }
+    connectionsButton.snp.makeConstraints {
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
+      $0.bottom.equalTo(safeAreaLayoutGuide).offset(-16)
+    }
+
+    collectionView.snp.makeConstraints {
+      $0.edges.equalToSuperview()
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/RestoreFeature/Controllers/RestoreController.swift b/Sources/RestoreFeature/Controllers/RestoreController.swift
index 5e4c555b7cdd389f7d977c02ec64bdcd0c1e4d7f..a58bdd1f8200c759660ec8398337dcf50c6a42fb 100644
--- a/Sources/RestoreFeature/Controllers/RestoreController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreController.swift
@@ -1,9 +1,10 @@
+import DI
 import UIKit
 import Shared
 import Combine
 import Navigation
+import AppResources
 import DrawerFeature
-import DI
 
 public final class RestoreController: UIViewController {
   @Dependency var navigator: Navigator
@@ -130,6 +131,6 @@ extension RestoreController {
         spacingAfter: 37
       ),
       actionButton
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/RestoreFeature/Controllers/RestoreListController.swift b/Sources/RestoreFeature/Controllers/RestoreListController.swift
index 4d138ba3944c0c86ac5876cfabff5a65c9ce1a0a..14fdc78eb0ec8ba4dc1787ac002a3c799f38ba99 100644
--- a/Sources/RestoreFeature/Controllers/RestoreListController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreListController.swift
@@ -32,10 +32,10 @@ public final class RestoreListController: UIViewController {
       .sftpPublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] _ in
-        navigator.perform(PresentSFTP { [weak self] host, username, password in
+        navigator.perform(PresentSFTP(completion: { [weak self] host, username, password in
           guard let self else { return }
           self.viewModel.setupSFTP(host: host, username: username, password: password)
-        })
+        }, on: navigationController!))
       }.store(in: &cancellables)
 
     viewModel.detailsPublisher
@@ -116,6 +116,6 @@ extension RestoreListController {
         spacingAfter: 37
       ),
       actionButton
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift b/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
index a1eec1bb1b4974f7a038ea833892304907540e3a..c413c18a7cca79e3a144310f8923b669137d18e9 100644
--- a/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
+++ b/Sources/RestoreFeature/Controllers/RestoreSuccessController.swift
@@ -49,7 +49,7 @@ public final class RestoreSuccessController: UIViewController {
       .nextButton
       .publisher(for: .touchUpInside)
       .sink { [unowned self] in
-        navigator.perform(PresentChatList())
+        navigator.perform(PresentChatList(on: navigationController!))
       }.store(in: &cancellables)
   }
 }
diff --git a/Sources/ScanFeature/Controllers/ScanContainerController.swift b/Sources/ScanFeature/Controllers/ScanContainerController.swift
index 806d852e4732e95457692d11c7c40f8da9533090..68f78d7a6b6e0b64340ded20b05ae4f2dd06f197 100644
--- a/Sources/ScanFeature/Controllers/ScanContainerController.swift
+++ b/Sources/ScanFeature/Controllers/ScanContainerController.swift
@@ -58,11 +58,11 @@ public final class ScanContainerController: UIViewController {
     }
     displayController.didTapAddEmail = { [weak self] in
       guard let self else { return }
-      self.navigator.perform(PresentProfileEmail())
+      self.navigator.perform(PresentProfileEmail(on: self.navigationController!))
     }
     displayController.didTapAddPhone = { [weak self] in
       guard let self else { return }
-      self.navigator.perform(PresentProfilePhone())
+      self.navigator.perform(PresentProfilePhone(on: self.navigationController!))
     }
   }
 
@@ -106,7 +106,7 @@ public final class ScanContainerController: UIViewController {
   }
 
   @objc private func didTapMenu() {
-    navigator.perform(PresentMenu(currentItem: .scan))
+    navigator.perform(PresentMenu(currentItem: .scan, from: self))
   }
 
   private func presentInfo(title: String, subtitle: String) {
@@ -146,7 +146,7 @@ public final class ScanContainerController: UIViewController {
         actionButton,
         FlexibleSpace()
       ])
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
 
diff --git a/Sources/ScanFeature/Controllers/ScanController.swift b/Sources/ScanFeature/Controllers/ScanController.swift
index 52369e7514853a6e87348e9afb84ea085225888b..bf8875099a7ba127269d1b03e693015542c093bf 100644
--- a/Sources/ScanFeature/Controllers/ScanController.swift
+++ b/Sources/ScanFeature/Controllers/ScanController.swift
@@ -83,7 +83,7 @@ final class ScanController: UIViewController {
       .receive(on: DispatchQueue.main)
       .delay(for: 1, scheduler: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentContact(contact: $0))
+        navigator.perform(PresentContact(contact: $0, on: navigationController!))
       }.store(in: &cancellables)
     
     viewModel
@@ -105,9 +105,9 @@ final class ScanController: UIViewController {
           guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
           UIApplication.shared.open(url, options: [:])
         case .failed(.requestOpened):
-          navigator.perform(PresentRequests())
+          navigator.perform(PresentRequests(on: navigationController!))
         case .failed(.alreadyFriends):
-          navigator.perform(PresentContactList())
+          navigator.perform(PresentContactList(on: navigationController!))
         default:
           break
         }
diff --git a/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift b/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift
index 17b985d80312b589d31f7640682fb00fa052aeef..5c20f1e3f9111ed699790503ffce76774f02cfe4 100644
--- a/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift
+++ b/Sources/ScanFeature/ViewModels/ScanDisplayViewModel.swift
@@ -2,7 +2,6 @@ import UIKit
 import Shared
 import Combine
 import Defaults
-import Countries
 import XXClient
 import DI
 import XXMessengerClient
diff --git a/Sources/SearchFeature/Controllers/SearchContainerController.swift b/Sources/SearchFeature/Controllers/SearchContainerController.swift
index 70f063ba28c834c86f2da92bad93cf978c65fa26..8090af4f689290756de3a67082641cb099c37794 100644
--- a/Sources/SearchFeature/Controllers/SearchContainerController.swift
+++ b/Sources/SearchFeature/Controllers/SearchContainerController.swift
@@ -180,6 +180,6 @@ extension SearchContainerController {
         distribution: .fillEqually,
         views: [enableButton, dismissButton]
       )
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/SearchFeature/Controllers/SearchLeftController.swift b/Sources/SearchFeature/Controllers/SearchLeftController.swift
index a1a2b3c8661cff08b69be4c35d45ec5ee6936396..5570d6c5d349b6d0140e8290189e19f6aae5a017 100644
--- a/Sources/SearchFeature/Controllers/SearchLeftController.swift
+++ b/Sources/SearchFeature/Controllers/SearchLeftController.swift
@@ -3,9 +3,9 @@ import Shared
 import Combine
 import XXModels
 import Defaults
-import Countries
 import Navigation
 import DrawerFeature
+import CountryListFeature
 import DI
 
 final class SearchLeftController: UIViewController {
@@ -161,7 +161,7 @@ final class SearchLeftController: UIViewController {
         navigator.perform(PresentCountryList(completion: { [weak self] in
           guard let self else { return }
           self.viewModel.didPick(country: $0 as! Country)
-        }))
+        }, from: self))
       }.store(in: &cancellables)
 
     screenView
@@ -233,7 +233,7 @@ final class SearchLeftController: UIViewController {
         actionButton,
         FlexibleSpace()
       ])
-    ]))
+    ], isDismissable: true, from: self))
   }
 
   private func presentSucessDrawerFor(contact: Contact) {
@@ -423,7 +423,11 @@ final class SearchLeftController: UIViewController {
         }
       }.store(in: &drawerCancellables)
 
-    navigator.perform(PresentDrawer(items: items))
+    navigator.perform(PresentDrawer(
+      items: items,
+      isDismissable: true,
+      from: self
+    ))
   }
 }
 
@@ -445,7 +449,7 @@ extension SearchLeftController: UITableViewDelegate {
 
   private func didTap(contact: Contact) {
     guard contact.authStatus == .stranger else {
-      navigator.perform(PresentContact(contact: contact))
+      navigator.perform(PresentContact(contact: contact, on: navigationController!))
       return
     }
 
diff --git a/Sources/SearchFeature/Controllers/SearchRightController.swift b/Sources/SearchFeature/Controllers/SearchRightController.swift
index d8cc22ecaceac630d68468329463bd7db94d3995..9f4a7f796111c96667da875b9a63baaedfffa116 100644
--- a/Sources/SearchFeature/Controllers/SearchRightController.swift
+++ b/Sources/SearchFeature/Controllers/SearchRightController.swift
@@ -56,7 +56,7 @@ final class SearchRightController: UIViewController {
       .receive(on: DispatchQueue.main)
       .delay(for: 1, scheduler: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentContact(contact: $0))
+        navigator.perform(PresentContact(contact: $0, on: navigationController!))
       }.store(in: &cancellables)
 
     viewModel
@@ -77,9 +77,9 @@ final class SearchRightController: UIViewController {
           guard let url = URL(string: UIApplication.openSettingsURLString) else { return }
           UIApplication.shared.open(url, options: [:])
         case .failed(.requestOpened):
-          navigator.perform(PresentRequests())
+          navigator.perform(PresentRequests(on: navigationController!))
         case .failed(.alreadyFriends):
-          navigator.perform(PresentContactList())
+          navigator.perform(PresentContactList(on: navigationController!))
         default:
           break
         }
diff --git a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
index 3ade6d3f5c1ece4aaa581ab61da99c9d8373f902..f2c1c947e68275031b2a0d3c561d6fa6f662bd59 100644
--- a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
+++ b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
@@ -5,12 +5,11 @@ import Combine
 import XXModels
 import XXClient
 import Defaults
-import Countries
 import CustomDump
-import NetworkMonitor
 import ReportingFeature
 import CombineSchedulers
 import XXMessengerClient
+import CountryListFeature
 import DI
 
 typealias SearchSnapshot = NSDiffableDataSourceSnapshot<SearchSection, SearchItem>
diff --git a/Sources/SettingsFeature/Controllers/AccountDeleteController.swift b/Sources/SettingsFeature/Controllers/AccountDeleteController.swift
index f3bde0baafec9100e8adbf2a26b1bb208e4639f4..41fe4cacffab08c5fb743a4214493a5909b15e0f 100644
--- a/Sources/SettingsFeature/Controllers/AccountDeleteController.swift
+++ b/Sources/SettingsFeature/Controllers/AccountDeleteController.swift
@@ -119,6 +119,6 @@ public final class AccountDeleteController: UIViewController {
         actionButton,
         FlexibleSpace()
       ])
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift b/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift
index 0ca63236e03dc3281c4c46297c84c705d0823e3f..c4b434cda7e72f62b278ee82ac05da178f69ad92 100644
--- a/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift
+++ b/Sources/SettingsFeature/Controllers/SettingsAdvancedController.swift
@@ -87,7 +87,7 @@ public final class SettingsAdvancedController: UIViewController {
       .sharePublisher
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentActivitySheet(items: [$0]))
+        navigator.perform(PresentActivitySheet(items: [$0], from: self))
       }.store(in: &cancellables)
 
     viewModel
diff --git a/Sources/SettingsFeature/Controllers/SettingsController.swift b/Sources/SettingsFeature/Controllers/SettingsController.swift
index c2d74e694d87e82af662ce8c919b204a0a633837..9186199140e0a55b37b2b48fd611cdd7b9afc795 100644
--- a/Sources/SettingsFeature/Controllers/SettingsController.swift
+++ b/Sources/SettingsFeature/Controllers/SettingsController.swift
@@ -172,7 +172,7 @@ public final class SettingsController: UIViewController {
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentSettingsAccountDelete())
+        navigator.perform(PresentSettingsAccountDelete(on: navigationController!))
       }.store(in: &cancellables)
 
     screenView
@@ -180,7 +180,7 @@ public final class SettingsController: UIViewController {
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentSettingsBackup())
+        navigator.perform(PresentSettingsBackup(on: navigationController!))
       }.store(in: &cancellables)
 
     screenView
@@ -188,7 +188,7 @@ public final class SettingsController: UIViewController {
       .publisher(for: .touchUpInside)
       .receive(on: DispatchQueue.main)
       .sink { [unowned self] in
-        navigator.perform(PresentSettingsAdvanced())
+        navigator.perform(PresentSettingsAdvanced(on: navigationController!))
       }.store(in: &cancellables)
 
     viewModel
@@ -268,11 +268,11 @@ public final class SettingsController: UIViewController {
         spacing: 20.0,
         views: [actionButton, cancelButton]
       )
-    ]))
+    ], isDismissable: true, from: self))
   }
 
   @objc private func didTapMenu() {
-    navigator.perform(PresentMenu(currentItem: .settings))
+    navigator.perform(PresentMenu(currentItem: .settings, from: self))
   }
 }
 
@@ -314,6 +314,6 @@ extension SettingsController {
         actionButton,
         FlexibleSpace()
       ])
-    ]))
+    ], isDismissable: true, from: self))
   }
 }
diff --git a/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift b/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift
index 48b97ddc0c5136d087fb67d2179e78a05105478e..f2fa2b54acb06a3836cdbc0021f6ce7423df5691 100644
--- a/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift
+++ b/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift
@@ -1,10 +1,10 @@
 import UIKit
 import Shared
 import Combine
+import XXClient
 import Defaults
 import Permissions
 import PushFeature
-import XXClient
 import XXMessengerClient
 import UserNotifications
 import CombineSchedulers
diff --git a/Sources/Shared/Controllers/DiffEditableDataSource.swift b/Sources/Shared/Controllers/DiffEditableDataSource.swift
index 9103733b120a2f7ff7a3a25be34c9ce6c2f3a6eb..b964b3492790b3c1aee7608aaa3c4b08d039c0ef 100644
--- a/Sources/Shared/Controllers/DiffEditableDataSource.swift
+++ b/Sources/Shared/Controllers/DiffEditableDataSource.swift
@@ -1,13 +1,13 @@
 import UIKit
 
 public struct SectionId: Hashable {
-    public init() {}
+  public init() {}
 }
 
 public final class DiffEditableDataSource<SectionIdentifierType, ItemIdentifierType>
 : UITableViewDiffableDataSource<SectionIdentifierType, ItemIdentifierType>
 where SectionIdentifierType : Hashable, ItemIdentifierType : Hashable {
-
-    public override func tableView(_ tableView: UITableView,
-                                   canEditRowAt indexPath: IndexPath) -> Bool { true }
+  
+  public override func tableView(_ tableView: UITableView,
+                                 canEditRowAt indexPath: IndexPath) -> Bool { true }
 }
diff --git a/Sources/Shared/Controllers/HUDController.swift b/Sources/Shared/Controllers/HUDController.swift
deleted file mode 100644
index 7606cd7fd85f4255d6990c804baeed7b8b20d3b0..0000000000000000000000000000000000000000
--- a/Sources/Shared/Controllers/HUDController.swift
+++ /dev/null
@@ -1,34 +0,0 @@
-import Combine
-import Foundation
-
-public final class HUDController {
-  private var timer: Timer?
-
-  var modelPublisher: AnyPublisher<HUDModel?, Never> {
-    modelSubject.eraseToAnyPublisher()
-  }
-
-  private let modelSubject = PassthroughSubject<HUDModel?, Never>()
-
-  public init() {}
-
-  public func dismiss() {
-    modelSubject.send(nil)
-  }
-
-  public func show(_ model: HUDModel? = nil) {
-    guard let model else {
-      modelSubject.send(.init(hasDotAnimation: true))
-      return
-    }
-
-    if model.isAutoDismissable {
-      DispatchQueue.main.asyncAfter(deadline: .now() + 2) { [weak self] in
-        guard let self else { return }
-        self.modelSubject.send(nil)
-      }
-    }
-
-    modelSubject.send(model)
-  }
-}
diff --git a/Sources/Shared/Controllers/StatusBarStyling.swift b/Sources/Shared/Controllers/StatusBarStyling.swift
deleted file mode 100644
index 07941553057aa151e0f9e7b5dd5eee84ed580eed..0000000000000000000000000000000000000000
--- a/Sources/Shared/Controllers/StatusBarStyling.swift
+++ /dev/null
@@ -1,7 +0,0 @@
-import UIKit
-import Combine
-
-public struct StatusBarStylist {
-  public init() {}
-  public let styleSubject = CurrentValueSubject<UIStatusBarStyle, Never>(.lightContent)
-}
diff --git a/Sources/Shared/Controllers/ToastController.swift b/Sources/Shared/Controllers/ToastController.swift
deleted file mode 100644
index 1b0fd60e66297ace82beb3a6c1e877185d5ad066..0000000000000000000000000000000000000000
--- a/Sources/Shared/Controllers/ToastController.swift
+++ /dev/null
@@ -1,22 +0,0 @@
-import Combine
-
-public final class ToastController {
-    private let queue = CurrentValueSubject<[ToastModel], Never>([])
-
-    var currentToast: AnyPublisher<ToastModel, Never> {
-        queue.compactMap(\.first)
-            .removeDuplicates(by: { $0.id == $1.id })
-            .eraseToAnyPublisher()
-    }
-
-    public init() {}
-
-    public func enqueueToast(model: ToastModel) {
-        queue.value.append(model)
-    }
-
-    public func dismissCurrentToast() {
-        guard queue.value.isEmpty == false else { return }
-        _ = queue.value.removeFirst()
-    }
-}
diff --git a/Sources/Shared/EditStateHandler.swift b/Sources/Shared/EditStateHandler.swift
index 1a8d4c7e89edb3449118679c03e87fc4c1afcc08..ca1fd06b2259b0cb3eafa4508cb0d8fab9ff9521 100644
--- a/Sources/Shared/EditStateHandler.swift
+++ b/Sources/Shared/EditStateHandler.swift
@@ -1,18 +1,12 @@
 import Combine
 
 public final class EditStateHandler {
-    // MARK: Properties
+  public var isEditing: AnyPublisher<Bool, Never> { stateRelay.eraseToAnyPublisher() }
+  private let stateRelay = CurrentValueSubject<Bool, Never>(false)
 
-    public var isEditing: AnyPublisher<Bool, Never> { stateRelay.eraseToAnyPublisher() }
-    private let stateRelay = CurrentValueSubject<Bool, Never>(false)
+  public init() {}
 
-    // MARK: Lifecycle
-
-    public init() {}
-
-    // MARK: Public
-
-    public func didSwitchEditing() {
-        stateRelay.value.toggle()
-    }
+  public func didSwitchEditing() {
+    stateRelay.value.toggle()
+  }
 }
diff --git a/Sources/Shared/Extensions/BezierPath.swift b/Sources/Shared/Extensions/BezierPath.swift
index 5238360a7ef06eb0ecf089d30f8a3ab869aa445c..7994776acf2e3894587f5e6cceffc7e286297a2f 100644
--- a/Sources/Shared/Extensions/BezierPath.swift
+++ b/Sources/Shared/Extensions/BezierPath.swift
@@ -1,7 +1,7 @@
 import UIKit
 
 public extension UIBezierPath {
-    convenience init(_ size: CGSize, rad: CGFloat) {
-        self.init(roundedRect: CGRect(origin: .zero, size: size), cornerRadius: rad)
-    }
+  convenience init(_ size: CGSize, rad: CGFloat) {
+    self.init(roundedRect: CGRect(origin: .zero, size: size), cornerRadius: rad)
+  }
 }
diff --git a/Sources/Shared/Extensions/Button.swift b/Sources/Shared/Extensions/Button.swift
index 3148a0cdee30fa987dc5e1d3d0e0c08db0f90fa2..5c3c3e86833defd4d357eb2da52d6e0b983959ad 100644
--- a/Sources/Shared/Extensions/Button.swift
+++ b/Sources/Shared/Extensions/Button.swift
@@ -1,12 +1,13 @@
 import UIKit
+import AppResources
 
 public extension UIButton {
-    static func back(color: UIColor = Asset.neutralActive.color) -> UIButton {
-        let back = UIButton()
-        back.setImage(Asset.navigationBarBack.image, for: .normal)
-        back.tintColor = color
-        back.imageView?.contentMode = .center
-        back.snp.makeConstraints { $0.width.equalTo(50) }
-        return back
-    }
+  static func back(color: UIColor = Asset.neutralActive.color) -> UIButton {
+    let back = UIButton()
+    back.setImage(Asset.navigationBarBack.image, for: .normal)
+    back.tintColor = color
+    back.imageView?.contentMode = .center
+    back.snp.makeConstraints { $0.width.equalTo(50) }
+    return back
+  }
 }
diff --git a/Sources/Shared/Extensions/CollectionView.swift b/Sources/Shared/Extensions/CollectionView.swift
index ad5b3bf7ea0d77d43c664b22ea90271d9f96a63f..e2fcafa0a3e18368b6c8ce12cf92232ae51335d7 100644
--- a/Sources/Shared/Extensions/CollectionView.swift
+++ b/Sources/Shared/Extensions/CollectionView.swift
@@ -1,151 +1,152 @@
 import UIKit
 import ChatLayout
+import AppResources
 import DifferenceKit
 
 extension UICollectionReusableView: ReusableView {}
 
 public extension UICollectionView {
-    func register<T: UICollectionViewCell>(_: T.Type) {
-        register(T.self, forCellWithReuseIdentifier: T.reuseIdentifier)
+  func register<T: UICollectionViewCell>(_: T.Type) {
+    register(T.self, forCellWithReuseIdentifier: T.reuseIdentifier)
+  }
+  
+  func registerSectionHeader<T: UICollectionReusableView>(_: T.Type) {
+    register(
+      T.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
+      withReuseIdentifier: T.reuseIdentifier
+    )
+  }
+  
+  func dequeueReusableCell<T: UICollectionViewCell>(forIndexPath indexPath: IndexPath) -> T {
+    guard let cell = dequeueReusableCell(withReuseIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
+      fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
     }
-
-    func registerSectionHeader<T: UICollectionReusableView>(_: T.Type) {
-        register(
-            T.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader,
-            withReuseIdentifier: T.reuseIdentifier
-        )
-    }
-
-    func dequeueReusableCell<T: UICollectionViewCell>(forIndexPath indexPath: IndexPath) -> T {
-        guard let cell = dequeueReusableCell(withReuseIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
-            fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
-        }
-
-        return cell
+    
+    return cell
+  }
+  
+  func dequeueSupplementaryView<T: UICollectionReusableView>(forIndexPath indexPath: IndexPath) -> T {
+    dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader,
+                                     withReuseIdentifier: T.reuseIdentifier, for: indexPath) as! T
+  }
+  
+  convenience init(on view: UIView, with layout: CollectionViewChatLayout) {
+    self.init(frame: view.frame, collectionViewLayout: layout)
+    view.addSubview(self)
+    
+    frame = view.bounds
+    translatesAutoresizingMaskIntoConstraints = false
+    topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
+    bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
+    leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
+    trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
+    
+    alwaysBounceVertical = true
+    isPrefetchingEnabled = false
+    keyboardDismissMode = .interactive
+    showsHorizontalScrollIndicator = false
+    contentInsetAdjustmentBehavior = .always
+    backgroundColor = Asset.neutralSecondary.color
+    automaticallyAdjustsScrollIndicatorInsets = true
+  }
+  
+  func reload<C>(
+    using stagedChangeset: StagedChangeset<C>,
+    interrupt: ((Changeset<C>) -> Bool)? = nil,
+    onInterruptedReload: (() -> Void)? = nil,
+    completion: ((Bool) -> Void)? = nil,
+    setData: (C) -> Void
+  ) {
+    if case .none = window, let data = stagedChangeset.last?.data {
+      setData(data)
+      if let onInterruptedReload = onInterruptedReload {
+        onInterruptedReload()
+      } else {
+        reloadData()
+      }
+      completion?(false)
+      return
     }
-
-    func dequeueSupplementaryView<T: UICollectionReusableView>(forIndexPath indexPath: IndexPath) -> T {
-        dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader,
-                                         withReuseIdentifier: T.reuseIdentifier, for: indexPath) as! T
+    
+    let dispatchGroup: DispatchGroup? = completion != nil
+    ? DispatchGroup()
+    : nil
+    let completionHandler: ((Bool) -> Void)? = completion != nil
+    ? { _ in
+      dispatchGroup!.leave()
     }
-
-    convenience init(on view: UIView, with layout: CollectionViewChatLayout) {
-        self.init(frame: view.frame, collectionViewLayout: layout)
-        view.addSubview(self)
-
-        frame = view.bounds
-        translatesAutoresizingMaskIntoConstraints = false
-        topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
-        bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
-        leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
-        trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
-
-        alwaysBounceVertical = true
-        isPrefetchingEnabled = false
-        keyboardDismissMode = .interactive
-        showsHorizontalScrollIndicator = false
-        contentInsetAdjustmentBehavior = .always
-        backgroundColor = Asset.neutralSecondary.color
-        automaticallyAdjustsScrollIndicatorInsets = true
-    }
-
-    func reload<C>(
-        using stagedChangeset: StagedChangeset<C>,
-        interrupt: ((Changeset<C>) -> Bool)? = nil,
-        onInterruptedReload: (() -> Void)? = nil,
-        completion: ((Bool) -> Void)? = nil,
-        setData: (C) -> Void
-    ) {
-        if case .none = window, let data = stagedChangeset.last?.data {
-            setData(data)
-            if let onInterruptedReload = onInterruptedReload {
-                onInterruptedReload()
-            } else {
-                reloadData()
-            }
-            completion?(false)
-            return
+    : nil
+    
+    for changeset in stagedChangeset {
+      if let interrupt = interrupt, interrupt(changeset), let data = stagedChangeset.last?.data {
+        setData(data)
+        if let onInterruptedReload = onInterruptedReload {
+          onInterruptedReload()
+        } else {
+          reloadData()
         }
-
-        let dispatchGroup: DispatchGroup? = completion != nil
-            ? DispatchGroup()
-            : nil
-        let completionHandler: ((Bool) -> Void)? = completion != nil
-            ? { _ in
-                dispatchGroup!.leave()
-            }
-            : nil
-
-        for changeset in stagedChangeset {
-            if let interrupt = interrupt, interrupt(changeset), let data = stagedChangeset.last?.data {
-                setData(data)
-                if let onInterruptedReload = onInterruptedReload {
-                    onInterruptedReload()
-                } else {
-                    reloadData()
-                }
-                completion?(false)
-                return
-            }
-
-            performBatchUpdates({
-                setData(changeset.data)
-                dispatchGroup?.enter()
-
-                if !changeset.sectionDeleted.isEmpty {
-                    deleteSections(IndexSet(changeset.sectionDeleted))
-                }
-
-                if !changeset.sectionInserted.isEmpty {
-                    insertSections(IndexSet(changeset.sectionInserted))
-                }
-
-                if !changeset.sectionUpdated.isEmpty {
-                    reloadSections(IndexSet(changeset.sectionUpdated))
-                }
-
-                for (source, target) in changeset.sectionMoved {
-                    moveSection(source, toSection: target)
-                }
-
-                if !changeset.elementDeleted.isEmpty {
-                    deleteItems(at: changeset.elementDeleted.map {
-                        IndexPath(item: $0.element, section: $0.section)
-                    })
-                }
-
-                if !changeset.elementInserted.isEmpty {
-                    insertItems(at: changeset.elementInserted.map {
-                        IndexPath(item: $0.element, section: $0.section)
-                    })
-                }
-
-                if !changeset.elementUpdated.isEmpty {
-                    reloadItems(at: changeset.elementUpdated.map {
-                        IndexPath(item: $0.element, section: $0.section)
-                    })
-                }
-
-                for (source, target) in changeset.elementMoved {
-                    moveItem(at: IndexPath(item: source.element, section: source.section), to: IndexPath(item: target.element, section: target.section))
-                }
-            }, completion: completionHandler)
+        completion?(false)
+        return
+      }
+      
+      performBatchUpdates({
+        setData(changeset.data)
+        dispatchGroup?.enter()
+        
+        if !changeset.sectionDeleted.isEmpty {
+          deleteSections(IndexSet(changeset.sectionDeleted))
+        }
+        
+        if !changeset.sectionInserted.isEmpty {
+          insertSections(IndexSet(changeset.sectionInserted))
         }
-        dispatchGroup?.notify(queue: .main) {
-            completion!(true)
+        
+        if !changeset.sectionUpdated.isEmpty {
+          reloadSections(IndexSet(changeset.sectionUpdated))
         }
+        
+        for (source, target) in changeset.sectionMoved {
+          moveSection(source, toSection: target)
+        }
+        
+        if !changeset.elementDeleted.isEmpty {
+          deleteItems(at: changeset.elementDeleted.map {
+            IndexPath(item: $0.element, section: $0.section)
+          })
+        }
+        
+        if !changeset.elementInserted.isEmpty {
+          insertItems(at: changeset.elementInserted.map {
+            IndexPath(item: $0.element, section: $0.section)
+          })
+        }
+        
+        if !changeset.elementUpdated.isEmpty {
+          reloadItems(at: changeset.elementUpdated.map {
+            IndexPath(item: $0.element, section: $0.section)
+          })
+        }
+        
+        for (source, target) in changeset.elementMoved {
+          moveItem(at: IndexPath(item: source.element, section: source.section), to: IndexPath(item: target.element, section: target.section))
+        }
+      }, completion: completionHandler)
+    }
+    dispatchGroup?.notify(queue: .main) {
+      completion!(true)
     }
+  }
 }
 
 public extension StagedChangeset {
-    func flattenIfPossible() -> StagedChangeset {
-        if count == 2,
-           self[0].sectionChangeCount == 0,
-           self[1].sectionChangeCount == 0,
-           self[0].elementDeleted.count == self[0].elementChangeCount,
-           self[1].elementInserted.count == self[1].elementChangeCount {
-            return StagedChangeset(arrayLiteral: Changeset(data: self[1].data, elementDeleted: self[0].elementDeleted, elementInserted: self[1].elementInserted))
-        }
-        return self
+  func flattenIfPossible() -> StagedChangeset {
+    if count == 2,
+       self[0].sectionChangeCount == 0,
+       self[1].sectionChangeCount == 0,
+       self[0].elementDeleted.count == self[0].elementChangeCount,
+       self[1].elementInserted.count == self[1].elementChangeCount {
+      return StagedChangeset(arrayLiteral: Changeset(data: self[1].data, elementDeleted: self[0].elementDeleted, elementInserted: self[1].elementInserted))
     }
+    return self
+  }
 }
diff --git a/Sources/Shared/Extensions/Colors.swift b/Sources/Shared/Extensions/Colors.swift
index 568f515724619f20a78636309adef24dcd506a51..28a21c17e94c28e043335ea6714c75af5289e0f5 100644
--- a/Sources/Shared/Extensions/Colors.swift
+++ b/Sources/Shared/Extensions/Colors.swift
@@ -1,18 +1,18 @@
 import UIKit
 
 public extension UIColor {
-    static func fade(from color: UIColor, to: UIColor, pcent: CGFloat) -> UIColor {
-        var fromRed: CGFloat = 0, fromGreen: CGFloat = 0, fromBlue: CGFloat = 0, fromAlpha: CGFloat = 0
-        color.getRed(&fromRed, green: &fromGreen, blue: &fromBlue, alpha: &fromAlpha)
-
-        var toRed: CGFloat = 0, toGreen: CGFloat = 0, toBlue: CGFloat = 0, toAlpha: CGFloat = 0
-        to.getRed(&toRed, green: &toGreen, blue: &toBlue, alpha: &toAlpha)
-
-        let red = (toRed - fromRed) * pcent + fromRed
-        let green = (toGreen - fromGreen) * pcent + fromGreen
-        let blue = (toBlue - fromBlue) * pcent + fromBlue
-        let alpha = (toAlpha - fromAlpha) * pcent + fromAlpha
-
-        return UIColor(red: red, green: green, blue: blue, alpha: alpha)
-    }
+  static func fade(from color: UIColor, to: UIColor, pcent: CGFloat) -> UIColor {
+    var fromRed: CGFloat = 0, fromGreen: CGFloat = 0, fromBlue: CGFloat = 0, fromAlpha: CGFloat = 0
+    color.getRed(&fromRed, green: &fromGreen, blue: &fromBlue, alpha: &fromAlpha)
+    
+    var toRed: CGFloat = 0, toGreen: CGFloat = 0, toBlue: CGFloat = 0, toAlpha: CGFloat = 0
+    to.getRed(&toRed, green: &toGreen, blue: &toBlue, alpha: &toAlpha)
+    
+    let red = (toRed - fromRed) * pcent + fromRed
+    let green = (toGreen - fromGreen) * pcent + fromGreen
+    let blue = (toBlue - fromBlue) * pcent + fromBlue
+    let alpha = (toAlpha - fromAlpha) * pcent + fromAlpha
+    
+    return UIColor(red: red, green: green, blue: blue, alpha: alpha)
+  }
 }
diff --git a/Sources/Shared/Extensions/Date.swift b/Sources/Shared/Extensions/Date.swift
index b88b81b5afcaa830c153f6be4d6af2bf67e74bec..93d9058f05357fc02caae4ee5a0889bc5bcba43b 100644
--- a/Sources/Shared/Extensions/Date.swift
+++ b/Sources/Shared/Extensions/Date.swift
@@ -1,60 +1,60 @@
 import Foundation
 
 public extension Date {
-    func asDayOfMonth() -> String {
-        let formatter = DateFormatter()
-        formatter.dateFormat = DateFormatter.dateFormat(
-            fromTemplate: "d MMMM",
-            options: 0,
-            locale: Locale(identifier: "en_US")
-        )
-
-        return formatter.string(from: self)
-    }
-
-    func asHoursAndMinutes() -> String {
-        let formatter = DateFormatter()
-        formatter.dateStyle = .none
-        formatter.timeStyle = .short
-        return formatter.string(from: self)
-    }
-
-    func asRelativeFromNow() -> String {
-        let formatter = RelativeDateTimeFormatter()
-        formatter.dateTimeStyle = .named
-        return formatter.string(for: self) ?? ""
-    }
-
-    func backupStyle() -> String {
-        let formatter = DateFormatter()
-        formatter.dateFormat = DateFormatter.dateFormat(
-            fromTemplate: "MMM d, YYYY - h:mm",
-            options: 0,
-            locale: Locale(identifier: "en_US")
-        )
-
-        return formatter.string(from: self)
-    }
-
-    static var asTimestamp: Int {
-        Int(Date().timeIntervalSince1970).toNano()
-    }
-
-    static func fromTimestamp(_ timestamp: Int) -> Date {
-        Date(timeIntervalSince1970: TimeInterval(timestamp.nanoToSeconds()))
-    }
-
-    static func fromMSTimestamp(_ timestampMS: Int64) -> Date {
-        Date(timeIntervalSince1970: TimeInterval(timestampMS) / 1000)
-    }
+  func asDayOfMonth() -> String {
+    let formatter = DateFormatter()
+    formatter.dateFormat = DateFormatter.dateFormat(
+      fromTemplate: "d MMMM",
+      options: 0,
+      locale: Locale(identifier: "en_US")
+    )
+    
+    return formatter.string(from: self)
+  }
+  
+  func asHoursAndMinutes() -> String {
+    let formatter = DateFormatter()
+    formatter.dateStyle = .none
+    formatter.timeStyle = .short
+    return formatter.string(from: self)
+  }
+  
+  func asRelativeFromNow() -> String {
+    let formatter = RelativeDateTimeFormatter()
+    formatter.dateTimeStyle = .named
+    return formatter.string(for: self) ?? ""
+  }
+  
+  func backupStyle() -> String {
+    let formatter = DateFormatter()
+    formatter.dateFormat = DateFormatter.dateFormat(
+      fromTemplate: "MMM d, YYYY - h:mm",
+      options: 0,
+      locale: Locale(identifier: "en_US")
+    )
+    
+    return formatter.string(from: self)
+  }
+  
+  static var asTimestamp: Int {
+    Int(Date().timeIntervalSince1970).toNano()
+  }
+  
+  static func fromTimestamp(_ timestamp: Int) -> Date {
+    Date(timeIntervalSince1970: TimeInterval(timestamp.nanoToSeconds()))
+  }
+  
+  static func fromMSTimestamp(_ timestampMS: Int64) -> Date {
+    Date(timeIntervalSince1970: TimeInterval(timestampMS) / 1000)
+  }
 }
 
 private extension Int {
-    func nanoToSeconds() -> Int {
-        self / 1000000000
-    }
-
-    func toNano() -> Int {
-        self * 1000000000
-    }
+  func nanoToSeconds() -> Int {
+    self / 1000000000
+  }
+  
+  func toNano() -> Int {
+    self * 1000000000
+  }
 }
diff --git a/Sources/Shared/Extensions/Error.swift b/Sources/Shared/Extensions/Error.swift
index 8ed7cb7677d80c088cdb3329c1d0d5f1274eb843..fc728460f381ad54294a2a211664b341c1b73c66 100644
--- a/Sources/Shared/Extensions/Error.swift
+++ b/Sources/Shared/Extensions/Error.swift
@@ -1,11 +1,11 @@
 import Foundation
 
 public extension NSError {
-    static func create(_ string: String) -> NSError {
-        NSError(
-            domain: "Internal error",
-            code: 0,
-            userInfo: [NSLocalizedDescriptionKey: NSLocalizedString(string, comment: "")]
-        )
-    }
+  static func create(_ string: String) -> NSError {
+    NSError(
+      domain: "Internal error",
+      code: 0,
+      userInfo: [NSLocalizedDescriptionKey: NSLocalizedString(string, comment: "")]
+    )
+  }
 }
diff --git a/Sources/Shared/Extensions/FileManager.swift b/Sources/Shared/Extensions/FileManager.swift
index c8639b5f82820335b584fc77d9d4887d07b7cda4..3834f2451c77c94270bc20311dc303af2a836c7a 100644
--- a/Sources/Shared/Extensions/FileManager.swift
+++ b/Sources/Shared/Extensions/FileManager.swift
@@ -2,71 +2,71 @@ import UIKit
 import Foundation
 
 public extension FileManager {
-    static var root: URL {
-        self.default.urls(for: .documentDirectory, in: .userDomainMask)
-            .first!.appendingPathComponent("xxm/")
+  static var root: URL {
+    self.default.urls(for: .documentDirectory, in: .userDomainMask)
+      .first!.appendingPathComponent("xxm/")
+  }
+  
+  static var xxContents: [String]? {
+    try? self.default.contentsOfDirectory(atPath: root.path)
+  }
+  
+  static var xxPath: String {
+    if xxContents == nil {
+      do {
+        try self.default.createDirectory(
+          at: root,
+          withIntermediateDirectories: false,
+          attributes: nil
+        )
+      } catch {
+        fatalError(error.localizedDescription)
+      }
     }
-
-    static var xxContents: [String]? {
-        try? self.default.contentsOfDirectory(atPath: root.path)
-    }
-
-    static var xxPath: String {
-        if xxContents == nil {
-            do {
-                try self.default.createDirectory(
-                    at: root,
-                    withIntermediateDirectories: false,
-                    attributes: nil
-                )
-            } catch {
-                fatalError(error.localizedDescription)
-            }
-        }
-
-        return root.path
-    }
-
-    static func xxCleanup() {
-        guard let files = xxContents else { return }
-        files.forEach { try? FileManager.default.removeItem(at: root.appendingPathComponent($0)) }
-    }
-
-    static func url(for fileName: String) -> URL? {
-        root.appendingPathComponent("\(fileName)")
-    }
-
-    static func store(data: Data, name: String, type: String) throws -> URL {
-        guard let url = Self.url(for: "\(name).\(type)") else {
-            throw NSError.create("The file path could not be retrieved")
-        }
-
-        try data.write(to: url)
-        return url
+    
+    return root.path
+  }
+  
+  static func xxCleanup() {
+    guard let files = xxContents else { return }
+    files.forEach { try? FileManager.default.removeItem(at: root.appendingPathComponent($0)) }
+  }
+  
+  static func url(for fileName: String) -> URL? {
+    root.appendingPathComponent("\(fileName)")
+  }
+  
+  static func store(data: Data, name: String, type: String) throws -> URL {
+    guard let url = Self.url(for: "\(name).\(type)") else {
+      throw NSError.create("The file path could not be retrieved")
     }
-
-    static func delete(name: String, type: String) {
-        if let url = Self.url(for: "\(name).\(type)") {
-            do {
-                try FileManager.default.removeItem(at: url)
-            } catch {
-                print(error.localizedDescription)
-            }
-        }
-    }
-
-    static func dummyAudio() -> Data {
-        let url = Bundle.module.url(forResource: "dummy_audio", withExtension: "m4a")
-        return try! Data(contentsOf: url!)
-    }
-
-    static func retrieve(name: String, type: String) -> Data? {
-        guard let url = Self.url(for: "\(name).\(type)") else { return nil }
-        return try? Data(contentsOf: url)
-    }
-
-    static func retrieve(imageNamed name: String) -> UIImage? {
-        guard let url = Self.url(for: name) else { return nil }
-        return UIImage(contentsOfFile: url.path)
+    
+    try data.write(to: url)
+    return url
+  }
+  
+  static func delete(name: String, type: String) {
+    if let url = Self.url(for: "\(name).\(type)") {
+      do {
+        try FileManager.default.removeItem(at: url)
+      } catch {
+        print(error.localizedDescription)
+      }
     }
+  }
+  
+  static func dummyAudio() -> Data {
+    let url = Bundle.module.url(forResource: "dummy_audio", withExtension: "m4a")
+    return try! Data(contentsOf: url!)
+  }
+  
+  static func retrieve(name: String, type: String) -> Data? {
+    guard let url = Self.url(for: "\(name).\(type)") else { return nil }
+    return try? Data(contentsOf: url)
+  }
+  
+  static func retrieve(imageNamed name: String) -> UIImage? {
+    guard let url = Self.url(for: name) else { return nil }
+    return UIImage(contentsOfFile: url.path)
+  }
 }
diff --git a/Sources/Shared/Extensions/Image.swift b/Sources/Shared/Extensions/Image.swift
index 442f8ff735f6fe3ef9bcb5b640e97a82080d9d8d..d69873ca9375e4677e8aff70831fc58026fd6a08 100644
--- a/Sources/Shared/Extensions/Image.swift
+++ b/Sources/Shared/Extensions/Image.swift
@@ -1,56 +1,56 @@
 import UIKit
 
 public extension UIImage {
-    static func fromBase64(_ base64String: String?) -> UIImage? {
-        guard let base64 = base64String,
-              let imageData = Data(base64Encoded: base64, options: .ignoreUnknownCharacters) else { return nil }
-        
-        return UIImage(data: imageData)
-    }
+  static func fromBase64(_ base64String: String?) -> UIImage? {
+    guard let base64 = base64String,
+          let imageData = Data(base64Encoded: base64, options: .ignoreUnknownCharacters) else { return nil }
     
-    static func color(_ color: UIColor, size: CGSize = .init(width: 1, height: 1)) -> UIImage {
-        UIGraphicsImageRenderer(size: size).image { context in
-            color.setFill()
-            context.fill(CGRect(origin: .zero, size: size))
-        }
+    return UIImage(data: imageData)
+  }
+  
+  static func color(_ color: UIColor, size: CGSize = .init(width: 1, height: 1)) -> UIImage {
+    UIGraphicsImageRenderer(size: size).image { context in
+      color.setFill()
+      context.fill(CGRect(origin: .zero, size: size))
     }
-
-    func orientedUp() -> UIImage {
-        if imageOrientation == .up { return self }
-        let format = imageRendererFormat
-        return UIGraphicsImageRenderer(size: size, format: format).image { _ in draw(at: .zero) }
+  }
+  
+  func orientedUp() -> UIImage {
+    if imageOrientation == .up { return self }
+    let format = imageRendererFormat
+    return UIGraphicsImageRenderer(size: size, format: format).image { _ in draw(at: .zero) }
+  }
+  
+  func resized(withPercentage percentage: CGFloat, isOpaque: Bool = true) -> UIImage? {
+    let canvas = CGSize(width: size.width * percentage, height: size.height * percentage)
+    let format = imageRendererFormat
+    format.opaque = isOpaque
+    return UIGraphicsImageRenderer(size: canvas, format: format).image {
+      _ in draw(in: CGRect(origin: .zero, size: canvas))
     }
-
-    func resized(withPercentage percentage: CGFloat, isOpaque: Bool = true) -> UIImage? {
-        let canvas = CGSize(width: size.width * percentage, height: size.height * percentage)
-        let format = imageRendererFormat
-        format.opaque = isOpaque
-        return UIGraphicsImageRenderer(size: canvas, format: format).image {
-            _ in draw(in: CGRect(origin: .zero, size: canvas))
-        }
-    }
-
-    func compress(to kb: Int) -> Data {
-        let bytes = kb * 1024
-        var compression: CGFloat = 1.0
-        let step: CGFloat = 0.05
-        var holderImage = self
-        var complete = false
-
-        while(!complete) {
-            if let data = holderImage.jpegData(compressionQuality: 1.0) {
-                let ratio = data.count / bytes
-                if data.count < bytes {
-                    complete = true
-                    return data
-                } else {
-                    let multiplier: CGFloat = CGFloat((ratio / 5) + 1)
-                    compression -= (step * multiplier)
-                }
-            }
-            guard let newImage = holderImage.resized(withPercentage: compression) else { break }
-            holderImage = newImage
+  }
+  
+  func compress(to kb: Int) -> Data {
+    let bytes = kb * 1024
+    var compression: CGFloat = 1.0
+    let step: CGFloat = 0.05
+    var holderImage = self
+    var complete = false
+    
+    while(!complete) {
+      if let data = holderImage.jpegData(compressionQuality: 1.0) {
+        let ratio = data.count / bytes
+        if data.count < bytes {
+          complete = true
+          return data
+        } else {
+          let multiplier: CGFloat = CGFloat((ratio / 5) + 1)
+          compression -= (step * multiplier)
         }
-        return Data()
+      }
+      guard let newImage = holderImage.resized(withPercentage: compression) else { break }
+      holderImage = newImage
     }
+    return Data()
+  }
 }
diff --git a/Sources/Shared/Extensions/ItemProvider.swift b/Sources/Shared/Extensions/ItemProvider.swift
index b0c6e48a2584ae174f86691bd28d9431577bc0db..1bad223d6127e41b0a96750309389d5e5fc8c828 100644
--- a/Sources/Shared/Extensions/ItemProvider.swift
+++ b/Sources/Shared/Extensions/ItemProvider.swift
@@ -2,27 +2,27 @@ import UIKit
 import Combine
 
 public extension NSItemProvider {
-    func loadImageObjectPublisher() -> AnyPublisher<UIImage, Error> {
-        Deferred {
-            Future { promise in
-                self.loadObject(ofClass: UIImage.self) { image, error in
-                    if let error = error {
-                        promise(.failure(error))
-                        return
-                    }
-
-                    guard let safeImage = image as? UIImage else {
-                        struct InvalidImageError: Error {
-                            let image: NSItemProviderReading?
-                        }
-
-                        promise(.failure(InvalidImageError(image: image)))
-                        return
-                    }
-
-                    promise(.success(safeImage))
-                }
+  func loadImageObjectPublisher() -> AnyPublisher<UIImage, Error> {
+    Deferred {
+      Future { promise in
+        self.loadObject(ofClass: UIImage.self) { image, error in
+          if let error = error {
+            promise(.failure(error))
+            return
+          }
+          
+          guard let safeImage = image as? UIImage else {
+            struct InvalidImageError: Error {
+              let image: NSItemProviderReading?
             }
-        }.eraseToAnyPublisher()
-    }
+            
+            promise(.failure(InvalidImageError(image: image)))
+            return
+          }
+          
+          promise(.success(safeImage))
+        }
+      }
+    }.eraseToAnyPublisher()
+  }
 }
diff --git a/Sources/Shared/Extensions/MutableAttributedString.swift b/Sources/Shared/Extensions/MutableAttributedString.swift
index f963a1d5e53d3eb058dfdccfcd169c66d0bf90c6..badcd31c78aada923438ebc5189058c081bc72fc 100644
--- a/Sources/Shared/Extensions/MutableAttributedString.swift
+++ b/Sources/Shared/Extensions/MutableAttributedString.swift
@@ -1,75 +1,75 @@
 import Foundation
 
 public extension NSMutableAttributedString {
-    func addAttribute(_ name: NSAttributedString.Key, value: Any) {
-        addAttribute(name, value: value, range: NSRange(string.startIndex..., in: string))
+  func addAttribute(_ name: NSAttributedString.Key, value: Any) {
+    addAttribute(name, value: value, range: NSRange(string.startIndex..., in: string))
+  }
+  
+  func addAttributes(_ attrs: [NSAttributedString.Key: Any]) {
+    addAttributes(attrs, range: NSRange(string.startIndex..., in: string))
+  }
+  
+  func setAttributes(attributes: [NSAttributedString.Key: Any], betweenCharacters: String) {
+    let ranges: Array = findRangesWithCharaters(charactersToFind: betweenCharacters)
+    for obj in ranges {
+      let thisValue: NSValue = obj
+      let range: NSRange = thisValue.rangeValue
+      setAttributes(attributes, range: range)
     }
-
-    func addAttributes(_ attrs: [NSAttributedString.Key: Any]) {
-        addAttributes(attrs, range: NSRange(string.startIndex..., in: string))
-    }
-
-    func setAttributes(attributes: [NSAttributedString.Key: Any], betweenCharacters: String) {
-        let ranges: Array = findRangesWithCharaters(charactersToFind: betweenCharacters)
-        for obj in ranges {
-            let thisValue: NSValue = obj
-            let range: NSRange = thisValue.rangeValue
-            setAttributes(attributes, range: range)
-        }
+  }
+  
+  func addAttribute(name: NSAttributedString.Key, value: Any, betweenCharacters: String) {
+    let ranges: Array = findRangesWithCharaters(charactersToFind: betweenCharacters)
+    for obj in ranges {
+      let thisValue: NSValue = obj
+      let range: NSRange = thisValue.rangeValue
+      addAttribute(name, value: value, range: range)
     }
-
-    func addAttribute(name: NSAttributedString.Key, value: Any, betweenCharacters: String) {
-        let ranges: Array = findRangesWithCharaters(charactersToFind: betweenCharacters)
-        for obj in ranges {
-            let thisValue: NSValue = obj
-            let range: NSRange = thisValue.rangeValue
-            addAttribute(name, value: value, range: range)
-        }
+  }
+  
+  func addAttributes(attributes: [NSAttributedString.Key: Any], betweenCharacters: String) {
+    let ranges: Array = findRangesWithCharaters(charactersToFind: betweenCharacters)
+    for obj in ranges {
+      let thisValue: NSValue = obj
+      let range: NSRange = thisValue.rangeValue
+      addAttributes(attributes, range: range)
     }
-
-    func addAttributes(attributes: [NSAttributedString.Key: Any], betweenCharacters: String) {
-        let ranges: Array = findRangesWithCharaters(charactersToFind: betweenCharacters)
-        for obj in ranges {
-            let thisValue: NSValue = obj
-            let range: NSRange = thisValue.rangeValue
-            addAttributes(attributes, range: range)
-        }
-    }
-
-    func removeAttribute(name: NSAttributedString.Key, betweenCharacters: String) {
-        let ranges: Array = findRangesWithCharaters(charactersToFind: betweenCharacters)
-        for obj in ranges {
-            let thisValue: NSValue = obj
-            let range: NSRange = thisValue.rangeValue
-            removeAttribute(name, range: range)
-        }
+  }
+  
+  func removeAttribute(name: NSAttributedString.Key, betweenCharacters: String) {
+    let ranges: Array = findRangesWithCharaters(charactersToFind: betweenCharacters)
+    for obj in ranges {
+      let thisValue: NSValue = obj
+      let range: NSRange = thisValue.rangeValue
+      removeAttribute(name, range: range)
     }
-
-    func findRangesWithCharaters(charactersToFind: String) -> [NSValue] {
-        let resultArray = NSMutableArray()
-        var insideTheRange = false
-        var startingRangeLocation: Int = 0
-
-        while self.mutableString.range(of: charactersToFind).location != NSNotFound {
-            let charactersLocation: NSRange = self.mutableString.range(of: charactersToFind)
-
-            if !insideTheRange {
-                startingRangeLocation = charactersLocation.location
-                insideTheRange = true
-
-                self.mutableString.deleteCharacters(in: charactersLocation)
-            } else {
-                let range: NSRange = NSRange(location: startingRangeLocation,
-                                             length: charactersLocation.location - startingRangeLocation)
-                insideTheRange = false
-
-                resultArray.add(NSValue(range: range))
-                self.mutableString.deleteCharacters(in: charactersLocation)
-            }
-        }
-
-        guard let result = resultArray.copy() as? [NSValue] else { return [] }
-
-        return result
+  }
+  
+  func findRangesWithCharaters(charactersToFind: String) -> [NSValue] {
+    let resultArray = NSMutableArray()
+    var insideTheRange = false
+    var startingRangeLocation: Int = 0
+    
+    while self.mutableString.range(of: charactersToFind).location != NSNotFound {
+      let charactersLocation: NSRange = self.mutableString.range(of: charactersToFind)
+      
+      if !insideTheRange {
+        startingRangeLocation = charactersLocation.location
+        insideTheRange = true
+        
+        self.mutableString.deleteCharacters(in: charactersLocation)
+      } else {
+        let range: NSRange = NSRange(location: startingRangeLocation,
+                                     length: charactersLocation.location - startingRangeLocation)
+        insideTheRange = false
+        
+        resultArray.add(NSValue(range: range))
+        self.mutableString.deleteCharacters(in: charactersLocation)
+      }
     }
+    
+    guard let result = resultArray.copy() as? [NSValue] else { return [] }
+    
+    return result
+  }
 }
diff --git a/Sources/Shared/Extensions/NavigationBar.swift b/Sources/Shared/Extensions/NavigationBar.swift
index b7efcb698321a974752e5c07cab1542ca0d26d80..db3d7e5c32a0c9040a5ef05c7cf6569f7251e5b1 100644
--- a/Sources/Shared/Extensions/NavigationBar.swift
+++ b/Sources/Shared/Extensions/NavigationBar.swift
@@ -1,21 +1,22 @@
 import UIKit
+import AppResources
 
 public extension UINavigationBar {
-    func customize(
-        translucent: Bool = false,
-        backgroundColor: UIColor = .clear,
-        shadowColor: UIColor? = nil,
-        tint: UIColor = Asset.neutralActive.color
-    ) {
-        isTranslucent = translucent
-        let barAppearance = UINavigationBarAppearance()
-        barAppearance.backgroundColor = backgroundColor
-        barAppearance.backgroundEffect = .none
-        barAppearance.shadowColor = shadowColor
-
-        tintColor = tint
-        compactAppearance = barAppearance
-        standardAppearance = barAppearance
-        scrollEdgeAppearance = barAppearance
-    }
+  func customize(
+    translucent: Bool = false,
+    backgroundColor: UIColor = .clear,
+    shadowColor: UIColor? = nil,
+    tint: UIColor = Asset.neutralActive.color
+  ) {
+    isTranslucent = translucent
+    let barAppearance = UINavigationBarAppearance()
+    barAppearance.backgroundColor = backgroundColor
+    barAppearance.backgroundEffect = .none
+    barAppearance.shadowColor = shadowColor
+    
+    tintColor = tint
+    compactAppearance = barAppearance
+    standardAppearance = barAppearance
+    scrollEdgeAppearance = barAppearance
+  }
 }
diff --git a/Sources/Shared/Extensions/Publishers.swift b/Sources/Shared/Extensions/Publishers.swift
deleted file mode 100644
index f7394821dd2b3d8d5ddefc707e204caa76d70199..0000000000000000000000000000000000000000
--- a/Sources/Shared/Extensions/Publishers.swift
+++ /dev/null
@@ -1,113 +0,0 @@
-import UIKit
-import Combine
-
-public extension UIControl {
-    func publisher(for event: Event) -> EventPublisher {
-        EventPublisher(
-            control: self,
-            event: event
-        )
-    }
-
-    struct EventPublisher: Publisher {
-        public typealias Output = Void
-        public typealias Failure = Never
-
-        fileprivate var control: UIControl
-        fileprivate var event: Event
-
-        public func receive<S: Subscriber>(
-            subscriber: S
-        ) where S.Input == Output, S.Failure == Failure {
-            let subscription = EventSubscription<S>()
-            subscription.target = subscriber
-            subscriber.receive(subscription: subscription)
-
-            control.addTarget(subscription,
-                action: #selector(subscription.trigger),
-                for: event
-            )
-        }
-    }
-}
-
-private extension UIControl {
-    class EventSubscription<Target: Subscriber>: Subscription
-        where Target.Input == Void {
-
-        var target: Target?
-
-        func request(_ demand: Subscribers.Demand) {}
-
-        func cancel() {
-            target = nil
-        }
-
-        @objc func trigger() {
-            _ = target?.receive(())
-        }
-    }
-}
-
-public extension UITextField {
-    var textPublisher: AnyPublisher<String, Never> {
-        publisher(for: .editingChanged)
-            .map { self.text ?? "" }
-            .eraseToAnyPublisher()
-    }
-
-    var returnPublisher: AnyPublisher<Void, Never> {
-        publisher(for: .editingDidEndOnExit)
-            .eraseToAnyPublisher()
-    }
-}
-
-public extension UITextView {
-    var textPublisher: Publishers.TextFieldPublisher {
-        Publishers.TextFieldPublisher(textField: self)
-    }
-}
-
-public extension Publishers {
-    struct TextFieldPublisher: Publisher {
-        public typealias Output = String
-        public typealias Failure = Never
-
-        private let textField: UITextView
-
-        init(textField: UITextView) { self.textField = textField }
-
-        public func receive<S>(subscriber: S) where S : Subscriber, Publishers.TextFieldPublisher.Failure == S.Failure, Publishers.TextFieldPublisher.Output == S.Input {
-            let subscription = TextFieldSubscription(subscriber: subscriber, textField: textField)
-            subscriber.receive(subscription: subscription)
-        }
-    }
-
-    class TextFieldSubscription<S: Subscriber>: NSObject, Subscription, UITextViewDelegate where S.Input == String, S.Failure == Never  {
-
-        private var subscriber: S?
-        private weak var textField: UITextView?
-
-        init(subscriber: S, textField: UITextView) {
-            super.init()
-            self.subscriber = subscriber
-            self.textField = textField
-            subscribe()
-        }
-
-        public func request(_ demand: Subscribers.Demand) { }
-
-        public func cancel() {
-            subscriber = nil
-            textField = nil
-        }
-
-        private func subscribe() {
-            textField?.delegate = self
-        }
-
-        public func textViewDidChange(_ textView: UITextView) {
-            _ = subscriber?.receive(textView.text)
-        }
-    }
-}
diff --git a/Sources/Shared/Extensions/StackView.swift b/Sources/Shared/Extensions/StackView.swift
index 93cf61339a5d119c455fe82e43daff240d5f621d..4997ad49716673064d898cf144e3ecff0d6bf830 100644
--- a/Sources/Shared/Extensions/StackView.swift
+++ b/Sources/Shared/Extensions/StackView.swift
@@ -1,7 +1,7 @@
 import UIKit
 
 public extension UIStackView {
-    func addArrangedSubviews(_ subviews: [UIView]) {
-        subviews.forEach(addArrangedSubview(_:))
-    }
+  func addArrangedSubviews(_ subviews: [UIView]) {
+    subviews.forEach(addArrangedSubview(_:))
+  }
 }
diff --git a/Sources/Shared/Extensions/TableView.swift b/Sources/Shared/Extensions/TableView.swift
index c05ccd74d2193cfdd01cc8c0fdd442e8d979a66a..973feeff2cf30d2f915d5f0fb76d9b654c1e26ba 100644
--- a/Sources/Shared/Extensions/TableView.swift
+++ b/Sources/Shared/Extensions/TableView.swift
@@ -4,34 +4,34 @@ extension UITableViewCell: ReusableView {}
 extension UITableViewHeaderFooterView: ReusableView {}
 
 public extension UITableView {
-    func register(cells: [AnyClass]) {
-        cells.forEach { cell in
-            register(cell, forCellReuseIdentifier: String(describing: cell))
-        }
+  func register(cells: [AnyClass]) {
+    cells.forEach { cell in
+      register(cell, forCellReuseIdentifier: String(describing: cell))
     }
-
-    func registerHeaderFooter<T: UITableViewHeaderFooterView>(type: T.Type) {
-        register(T.self, forHeaderFooterViewReuseIdentifier: T.reuseIdentifier)
-    }
-
-    func register<T: UITableViewCell>(_: T.Type) {
-        register(T.self, forCellReuseIdentifier: T.reuseIdentifier)
-    }
-
-    func dequeueReusableCell<T: UITableViewCell>(forIndexPath indexPath: IndexPath,
-                                                 ofType type: T.Type? = nil) -> T {
-        guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
-            fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
-        }
-
-        return cell
+  }
+  
+  func registerHeaderFooter<T: UITableViewHeaderFooterView>(type: T.Type) {
+    register(T.self, forHeaderFooterViewReuseIdentifier: T.reuseIdentifier)
+  }
+  
+  func register<T: UITableViewCell>(_: T.Type) {
+    register(T.self, forCellReuseIdentifier: T.reuseIdentifier)
+  }
+  
+  func dequeueReusableCell<T: UITableViewCell>(forIndexPath indexPath: IndexPath,
+                                               ofType type: T.Type? = nil) -> T {
+    guard let cell = dequeueReusableCell(withIdentifier: T.reuseIdentifier, for: indexPath) as? T else {
+      fatalError("Could not dequeue cell with identifier: \(T.reuseIdentifier)")
     }
-
-    func dequeueReusableHeaderFooter<T: UITableViewHeaderFooterView>(ofType type: T.Type? = nil) -> T {
-        guard let view = dequeueReusableHeaderFooterView(withIdentifier: T.reuseIdentifier) as? T else {
-            fatalError("Could not dequeue header footer with identifier: \(T.reuseIdentifier)")
-        }
-
-        return view
+    
+    return cell
+  }
+  
+  func dequeueReusableHeaderFooter<T: UITableViewHeaderFooterView>(ofType type: T.Type? = nil) -> T {
+    guard let view = dequeueReusableHeaderFooterView(withIdentifier: T.reuseIdentifier) as? T else {
+      fatalError("Could not dequeue header footer with identifier: \(T.reuseIdentifier)")
     }
+    
+    return view
+  }
 }
diff --git a/Sources/Shared/Extensions/View.swift b/Sources/Shared/Extensions/View.swift
index cdbc4f591dd6bbe26c08c47a2ec655f91528e954..0636e0d300e590d0082d847bfb161d83d5b908d2 100644
--- a/Sources/Shared/Extensions/View.swift
+++ b/Sources/Shared/Extensions/View.swift
@@ -4,78 +4,78 @@ import SnapKit
 protocol ReusableView {}
 
 extension ReusableView where Self: UIView {
-    static var reuseIdentifier: String {
-        return String(describing: self)
-    }
+  static var reuseIdentifier: String {
+    return String(describing: self)
+  }
 }
 
 public extension UIView {
-    enum PinningPosition {
-        case hCenter
-        case top(CGFloat)
-        case left(CGFloat)
-        case right(CGFloat)
-        case bottom(CGFloat)
-        case center(CGFloat)
-    }
-
-    func pinning(at position: PinningPosition) -> UIView {
-        let container = UIView()
-        container.addSubview(self)
-
-        self.snp.makeConstraints { make in
-            switch position {
-            case let .top(padding):
-                let flex = FlexibleSpace()
-                container.addSubview(flex)
-                flex.snp.makeConstraints { $0.bottom.equalToSuperview() }
-
-                make.top.equalToSuperview().offset(padding)
-                make.left.right.equalToSuperview()
-                make.bottom.lessThanOrEqualTo(flex.snp.top)
-
-            case let .left(padding):
-                let flex = FlexibleSpace()
-                container.addSubview(flex)
-                flex.snp.makeConstraints { $0.right.equalToSuperview() }
-
-                make.top.bottom.equalToSuperview()
-                make.left.equalToSuperview().offset(padding)
-                make.right.lessThanOrEqualTo(flex.snp.left)
-
-            case let .right(padding):
-                let flex = FlexibleSpace()
-                container.addSubview(flex)
-                flex.snp.makeConstraints { $0.bottom.equalToSuperview() }
-
-                make.top.bottom.equalToSuperview()
-                make.right.equalToSuperview().offset(padding)
-                make.left.greaterThanOrEqualTo(flex.snp.right)
-
-            case let .bottom(padding):
-                let flex = FlexibleSpace()
-                container.addSubview(flex)
-                flex.snp.makeConstraints { $0.top.equalToSuperview() }
-
-                make.bottom.equalToSuperview().offset(padding)
-                make.left.right.equalToSuperview()
-                make.top.greaterThanOrEqualTo(flex.snp.bottom)
-
-            case let .center(inset):
-                make.top.greaterThanOrEqualToSuperview().offset(inset)
-                make.left.greaterThanOrEqualToSuperview().offset(inset)
-                make.center.equalToSuperview()
-                make.right.lessThanOrEqualToSuperview().offset(-inset)
-                make.bottom.lessThanOrEqualToSuperview().offset(-inset)
-            case .hCenter:
-                make.top.equalToSuperview()
-                make.centerX.equalToSuperview()
-                make.left.greaterThanOrEqualToSuperview()
-                make.right.lessThanOrEqualToSuperview()
-                make.bottom.equalToSuperview()
-            }
-        }
-
-        return container
+  enum PinningPosition {
+    case hCenter
+    case top(CGFloat)
+    case left(CGFloat)
+    case right(CGFloat)
+    case bottom(CGFloat)
+    case center(CGFloat)
+  }
+  
+  func pinning(at position: PinningPosition) -> UIView {
+    let container = UIView()
+    container.addSubview(self)
+    
+    self.snp.makeConstraints { make in
+      switch position {
+      case let .top(padding):
+        let flex = FlexibleSpace()
+        container.addSubview(flex)
+        flex.snp.makeConstraints { $0.bottom.equalToSuperview() }
+        
+        make.top.equalToSuperview().offset(padding)
+        make.left.right.equalToSuperview()
+        make.bottom.lessThanOrEqualTo(flex.snp.top)
+        
+      case let .left(padding):
+        let flex = FlexibleSpace()
+        container.addSubview(flex)
+        flex.snp.makeConstraints { $0.right.equalToSuperview() }
+        
+        make.top.bottom.equalToSuperview()
+        make.left.equalToSuperview().offset(padding)
+        make.right.lessThanOrEqualTo(flex.snp.left)
+        
+      case let .right(padding):
+        let flex = FlexibleSpace()
+        container.addSubview(flex)
+        flex.snp.makeConstraints { $0.bottom.equalToSuperview() }
+        
+        make.top.bottom.equalToSuperview()
+        make.right.equalToSuperview().offset(padding)
+        make.left.greaterThanOrEqualTo(flex.snp.right)
+        
+      case let .bottom(padding):
+        let flex = FlexibleSpace()
+        container.addSubview(flex)
+        flex.snp.makeConstraints { $0.top.equalToSuperview() }
+        
+        make.bottom.equalToSuperview().offset(padding)
+        make.left.right.equalToSuperview()
+        make.top.greaterThanOrEqualTo(flex.snp.bottom)
+        
+      case let .center(inset):
+        make.top.greaterThanOrEqualToSuperview().offset(inset)
+        make.left.greaterThanOrEqualToSuperview().offset(inset)
+        make.center.equalToSuperview()
+        make.right.lessThanOrEqualToSuperview().offset(-inset)
+        make.bottom.lessThanOrEqualToSuperview().offset(-inset)
+      case .hCenter:
+        make.top.equalToSuperview()
+        make.centerX.equalToSuperview()
+        make.left.greaterThanOrEqualToSuperview()
+        make.right.lessThanOrEqualToSuperview()
+        make.bottom.equalToSuperview()
+      }
     }
+    
+    return container
+  }
 }
diff --git a/Sources/Shared/FeedbackPlayer.swift b/Sources/Shared/FeedbackPlayer.swift
index 09d4773d68576b4fd625bdc741e9e086c9a5d7ff..6c2bf25ef593f3a54ced36b4b9aea53cdb602a0f 100644
--- a/Sources/Shared/FeedbackPlayer.swift
+++ b/Sources/Shared/FeedbackPlayer.swift
@@ -2,37 +2,33 @@ import AVFoundation
 import AudioToolbox
 
 struct DeviceFeedback {
-    enum Haptic: UInt32 {
-        case impact = 1520
-        case notification = 1521
-        case selection = 1519
-    }
-
-    enum Alert: UInt32 {
-        case smsSent = 1004
-        case smsReceived = 1003
-        case contactAdded = 1117
-    }
-
-    // MARK: Lifecycle
-
-    private init() {}
-
-    // MARK: Static
-
-    static func sound(_ alert: Alert) {
-        try? AVAudioSession
-            .sharedInstance()
-            .setCategory(.ambient, mode: .default, options: .mixWithOthers)
-
-        AudioServicesPlaySystemSound(alert.rawValue)
-    }
-
-    static func shake(_ haptic: Haptic) {
-        try? AVAudioSession
-            .sharedInstance()
-            .setCategory(.ambient, mode: .default, options: .mixWithOthers)
-
-        AudioServicesPlaySystemSound(haptic.rawValue)
-    }
+  enum Haptic: UInt32 {
+    case impact = 1520
+    case notification = 1521
+    case selection = 1519
+  }
+
+  enum Alert: UInt32 {
+    case smsSent = 1004
+    case smsReceived = 1003
+    case contactAdded = 1117
+  }
+
+  private init() {}
+
+  static func sound(_ alert: Alert) {
+    try? AVAudioSession
+      .sharedInstance()
+      .setCategory(.ambient, mode: .default, options: .mixWithOthers)
+
+    AudioServicesPlaySystemSound(alert.rawValue)
+  }
+
+  static func shake(_ haptic: Haptic) {
+    try? AVAudioSession
+      .sharedInstance()
+      .setCategory(.ambient, mode: .default, options: .mixWithOthers)
+
+    AudioServicesPlaySystemSound(haptic.rawValue)
+  }
 }
diff --git a/Sources/Shared/Models/Country.swift b/Sources/Shared/Models/Country.swift
index 8d25ca75aba8358d5fe18265a7febd7e4887e6f9..ba2ba1f76c889cd9d35a7a8b012b07ca6125b410 100644
--- a/Sources/Shared/Models/Country.swift
+++ b/Sources/Shared/Models/Country.swift
@@ -8,32 +8,32 @@ public struct Country {
   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])
     }!
   }
diff --git a/Sources/Shared/Models/Payload.swift b/Sources/Shared/Models/Payload.swift
index 8e6f519b5ca09531b97961d1616a63477325d002..eb7e67e3731adfcb6eb277fea1ede8554ed1cb60 100644
--- a/Sources/Shared/Models/Payload.swift
+++ b/Sources/Shared/Models/Payload.swift
@@ -1,37 +1,37 @@
 import Foundation
 
 public struct Payload: Codable, Equatable, Hashable {
-    public var text: String
-    public var reply: Reply?
-
-    public init(text: String, reply: Reply?) {
-        self.text = text
-        self.reply = reply
+  public var text: String
+  public var reply: Reply?
+  
+  public init(text: String, reply: Reply?) {
+    self.text = text
+    self.reply = reply
+  }
+  
+  public init(with marshaled: Data) throws {
+    let proto = try CMIXText(serializedData: marshaled)
+    
+    var reply: Reply?
+    
+    if proto.hasReply {
+      reply = Reply(
+        messageId: proto.reply.messageID,
+        senderId: proto.reply.senderID
+      )
     }
-
-    public init(with marshaled: Data) throws {
-        let proto = try CMIXText(serializedData: marshaled)
-
-        var reply: Reply?
-
-        if proto.hasReply {
-            reply = Reply(
-                messageId: proto.reply.messageID,
-                senderId: proto.reply.senderID
-            )
-        }
-
-        self.init(text: proto.text, reply: reply)
-    }
-
-    public func asData() -> Data {
-        var protoModel = CMIXText()
-        protoModel.text = text
-
-        if let reply = reply {
-            protoModel.reply = reply.asTextReply()
-        }
-
-        return try! protoModel.serializedData()
+    
+    self.init(text: proto.text, reply: reply)
+  }
+  
+  public func asData() -> Data {
+    var protoModel = CMIXText()
+    protoModel.text = text
+    
+    if let reply = reply {
+      protoModel.reply = reply.asTextReply()
     }
+    
+    return try! protoModel.serializedData()
+  }
 }
diff --git a/Sources/Shared/Models/Reply.swift b/Sources/Shared/Models/Reply.swift
index 22fcf55aaa3c0b7f6c93618efe21531b1e4e36e6..edc61b01db652a5c57c93a4b893959655c7b37da 100644
--- a/Sources/Shared/Models/Reply.swift
+++ b/Sources/Shared/Models/Reply.swift
@@ -1,19 +1,19 @@
 import Foundation
 
 public struct Reply: Codable, Equatable, Hashable {
-    public let messageId: Data
-    public let senderId: Data
-
-    public init(messageId: Data, senderId: Data) {
-        self.messageId = messageId
-        self.senderId = senderId
-    }
-
-    func asTextReply() -> TextReply {
-        var reply = TextReply()
-        reply.messageID = messageId
-        reply.senderID = senderId
-
-        return reply
-    }
+  public let messageId: Data
+  public let senderId: Data
+  
+  public init(messageId: Data, senderId: Data) {
+    self.messageId = messageId
+    self.senderId = senderId
+  }
+  
+  func asTextReply() -> TextReply {
+    var reply = TextReply()
+    reply.messageID = messageId
+    reply.senderID = senderId
+    
+    return reply
+  }
 }
diff --git a/Sources/Shared/Models/ToastModel.swift b/Sources/Shared/Models/ToastModel.swift
deleted file mode 100644
index 001539d4dc907791e154a6c66ff8bf1b56e0c8c2..0000000000000000000000000000000000000000
--- a/Sources/Shared/Models/ToastModel.swift
+++ /dev/null
@@ -1,35 +0,0 @@
-import UIKit
-
-public struct ToastModel {
-    let id: UUID
-    let title: String
-    let color: UIColor
-    let subtitle: String?
-    let leftImage: UIImage
-    let timeToLive: Int
-    let buttonTitle: String?
-    let autodismissable: Bool
-    let onTapClosure: (() -> Void)?
-
-    public init(
-        id: UUID = UUID(),
-        title: String,
-        color: UIColor = Asset.neutralOverlay.color,
-        subtitle: String? = nil,
-        leftImage: UIImage,
-        timeToLive: Int = 4,
-        buttonTitle: String? = nil,
-        onTapClosure: (() -> Void)? = nil,
-        autodismissable: Bool = true
-    ) {
-        self.id = id
-        self.title = title
-        self.color = color
-        self.subtitle = subtitle
-        self.leftImage = leftImage
-        self.timeToLive = timeToLive
-        self.buttonTitle = buttonTitle
-        self.onTapClosure = onTapClosure
-        self.autodismissable = autodismissable
-    }
-}
diff --git a/Sources/Shared/Publishers.swift b/Sources/Shared/Publishers.swift
new file mode 100644
index 0000000000000000000000000000000000000000..cc837b449f284df069edc8e28c0c76860b6b7ee0
--- /dev/null
+++ b/Sources/Shared/Publishers.swift
@@ -0,0 +1,113 @@
+import UIKit
+import Combine
+
+public extension UIControl {
+  func publisher(for event: Event) -> EventPublisher {
+    EventPublisher(
+      control: self,
+      event: event
+    )
+  }
+
+  struct EventPublisher: Publisher {
+    public typealias Output = Void
+    public typealias Failure = Never
+
+    fileprivate var control: UIControl
+    fileprivate var event: Event
+
+    public func receive<S: Subscriber>(
+      subscriber: S
+    ) where S.Input == Output, S.Failure == Failure {
+      let subscription = EventSubscription<S>()
+      subscription.target = subscriber
+      subscriber.receive(subscription: subscription)
+
+      control.addTarget(subscription,
+                        action: #selector(subscription.trigger),
+                        for: event
+      )
+    }
+  }
+}
+
+private extension UIControl {
+  class EventSubscription<Target: Subscriber>: Subscription
+  where Target.Input == Void {
+
+    var target: Target?
+
+    func request(_ demand: Subscribers.Demand) {}
+
+    func cancel() {
+      target = nil
+    }
+
+    @objc func trigger() {
+      _ = target?.receive(())
+    }
+  }
+}
+
+public extension UITextField {
+  var textPublisher: AnyPublisher<String, Never> {
+    publisher(for: .editingChanged)
+      .map { self.text ?? "" }
+      .eraseToAnyPublisher()
+  }
+
+  var returnPublisher: AnyPublisher<Void, Never> {
+    publisher(for: .editingDidEndOnExit)
+      .eraseToAnyPublisher()
+  }
+}
+
+public extension UITextView {
+  var textPublisher: Publishers.TextFieldPublisher {
+    Publishers.TextFieldPublisher(textField: self)
+  }
+}
+
+public extension Publishers {
+  struct TextFieldPublisher: Publisher {
+    public typealias Output = String
+    public typealias Failure = Never
+
+    private let textField: UITextView
+
+    init(textField: UITextView) { self.textField = textField }
+
+    public func receive<S>(subscriber: S) where S : Subscriber, Publishers.TextFieldPublisher.Failure == S.Failure, Publishers.TextFieldPublisher.Output == S.Input {
+      let subscription = TextFieldSubscription(subscriber: subscriber, textField: textField)
+      subscriber.receive(subscription: subscription)
+    }
+  }
+
+  class TextFieldSubscription<S: Subscriber>: NSObject, Subscription, UITextViewDelegate where S.Input == String, S.Failure == Never  {
+
+    private var subscriber: S?
+    private weak var textField: UITextView?
+
+    init(subscriber: S, textField: UITextView) {
+      super.init()
+      self.subscriber = subscriber
+      self.textField = textField
+      subscribe()
+    }
+
+    public func request(_ demand: Subscribers.Demand) { }
+
+    public func cancel() {
+      subscriber = nil
+      textField = nil
+    }
+
+    private func subscribe() {
+      textField?.delegate = self
+    }
+
+    public func textViewDidChange(_ textView: UITextView) {
+      _ = subscriber?.receive(textView.text)
+    }
+  }
+}
diff --git a/Sources/Shared/Views/AttributeComponent.swift b/Sources/Shared/Views/AttributeComponent.swift
index eefa73c5c6f6ab3f0b18a21fe099bf163cb534a7..b7ed4ede8177df01963b36e44f54baa51d1ce5eb 100644
--- a/Sources/Shared/Views/AttributeComponent.swift
+++ b/Sources/Shared/Views/AttributeComponent.swift
@@ -1,81 +1,82 @@
 import UIKit
+import AppResources
 
 public final class AttributeComponent: UIView {
-    public enum Style {
-        case steady
-        case interactive
-        case requiredEditable
+  public enum Style {
+    case steady
+    case interactive
+    case requiredEditable
+  }
+  
+  public let titleLabel = UILabel()
+  public let actionButton = UIButton()
+  public let contentLabel = UILabel()
+  
+  let placeholder = "None provided"
+  var buttonStyle: Style = .steady
+  
+  public private(set) var currentValue: String? {
+    didSet { contentLabel.text = currentValue ?? placeholder }
+  }
+  
+  public init() {
+    super.init(frame: .zero)
+    
+    titleLabel.textColor = Asset.neutralWeak.color
+    contentLabel.textColor = Asset.neutralActive.color
+    titleLabel.font =  Fonts.Mulish.bold.font(size: 12.0)
+    contentLabel.font = Fonts.Mulish.regular.font(size: 16.0)
+    
+    addSubview(titleLabel)
+    addSubview(actionButton)
+    addSubview(contentLabel)
+    
+    titleLabel.snp.makeConstraints { make in
+      make.top.left.equalToSuperview()
+      make.bottom.equalToSuperview().offset(-25)
     }
-
-    public let titleLabel = UILabel()
-    public let actionButton = UIButton()
-    public let contentLabel = UILabel()
-
-    let placeholder = "None provided"
-    var buttonStyle: Style = .steady
-
-    public private(set) var currentValue: String? {
-        didSet { contentLabel.text = currentValue ?? placeholder }
+    
+    contentLabel.snp.makeConstraints { make in
+      make.top.equalTo(titleLabel.snp.bottom).offset(6)
+      make.left.equalToSuperview()
     }
-
-    public init() {
-        super.init(frame: .zero)
-
-        titleLabel.textColor = Asset.neutralWeak.color
-        contentLabel.textColor = Asset.neutralActive.color
-        titleLabel.font =  Fonts.Mulish.bold.font(size: 12.0)
-        contentLabel.font = Fonts.Mulish.regular.font(size: 16.0)
-
-        addSubview(titleLabel)
-        addSubview(actionButton)
-        addSubview(contentLabel)
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.left.equalToSuperview()
-            make.bottom.equalToSuperview().offset(-25)
-        }
-
-        contentLabel.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(6)
-            make.left.equalToSuperview()
-        }
-
-        actionButton.snp.makeConstraints { $0.right.centerY.equalToSuperview() }
+    
+    actionButton.snp.makeConstraints { $0.right.centerY.equalToSuperview() }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  public func set(
+    title: String,
+    value: String? = nil,
+    icon: UIImage? = nil,
+    style: Style = .steady
+  ) {
+    titleLabel.text = title.uppercased()
+    actionButton.setImage(icon, for: .normal)
+    buttonStyle = style
+    
+    set(value: value)
+  }
+  
+  public func set(value: String?) {
+    currentValue = value
+    
+    if buttonStyle == .requiredEditable {
+      actionButton.setImage(Asset.contactNicknameEdit.image, for: .normal)
+      return
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    public func set(
-        title: String,
-        value: String? = nil,
-        icon: UIImage? = nil,
-        style: Style = .steady
-    ) {
-        titleLabel.text = title.uppercased()
-        actionButton.setImage(icon, for: .normal)
-        buttonStyle = style
-
-        set(value: value)
+    
+    guard let _ = value else {
+      if buttonStyle == .interactive {
+        actionButton.setImage(Asset.profileAdd.image, for: .normal)
+      }
+      
+      return
     }
-
-    public func set(value: String?) {
-        currentValue = value
-
-        if buttonStyle == .requiredEditable {
-            actionButton.setImage(Asset.contactNicknameEdit.image, for: .normal)
-            return
-        }
-
-        guard let _ = value else {
-            if buttonStyle == .interactive {
-                actionButton.setImage(Asset.profileAdd.image, for: .normal)
-            }
-
-            return
-        }
-
-        if buttonStyle == .interactive {
-            actionButton.setImage(Asset.profileDelete.image, for: .normal)
-        }
+    
+    if buttonStyle == .interactive {
+      actionButton.setImage(Asset.profileDelete.image, for: .normal)
     }
+  }
 }
diff --git a/Sources/Shared/Views/AvatarCardComponent.swift b/Sources/Shared/Views/AvatarCardComponent.swift
index c34a8650696b991a8677d10b1a99deaec7c44fa8..fcbe72787d87f9a13579a6b51b0f5d88c4b682b4 100644
--- a/Sources/Shared/Views/AvatarCardComponent.swift
+++ b/Sources/Shared/Views/AvatarCardComponent.swift
@@ -1,164 +1,165 @@
 import UIKit
+import AppResources
 
 public final class AvatarCardComponent: UIView {
-    public let nameLabel = UILabel()
-    public let stackView = UIStackView()
-    public let avatarView = EditableAvatarView()
-    public var nameContainer: UIView?
-    private let sendMessageView = AvatarSendMessageView()
-
-    public var image: UIImage? {
-        didSet {
-            avatarView.imageView.image = nil
-            avatarView.imageView.image = image
-            avatarView.imageView.setNeedsDisplay()
-            avatarView.placeholderImageView.image = nil
-        }
+  public let nameLabel = UILabel()
+  public let stackView = UIStackView()
+  public let avatarView = EditableAvatarView()
+  public var nameContainer: UIView?
+  private let sendMessageView = AvatarSendMessageView()
+  
+  public var image: UIImage? {
+    didSet {
+      avatarView.imageView.image = nil
+      avatarView.imageView.image = image
+      avatarView.imageView.setNeedsDisplay()
+      avatarView.placeholderImageView.image = nil
     }
-
-    public init() {
-        super.init(frame: .zero)
-
-        backgroundColor = Asset.neutralBody.color
-
-        nameLabel.textColor = Asset.neutralWhite.color
-        nameLabel.numberOfLines = 2
-        nameLabel.textAlignment = .center
-        nameLabel.font = Fonts.Mulish.bold.font(size: 24.0)
-
-        nameContainer = nameLabel.pinning(at: .center(0))
-        let imageContainer = avatarView.pinning(at: .hCenter)
-
-        stackView.axis = .vertical
-        stackView.addArrangedSubview(imageContainer)
-        stackView.addArrangedSubview(nameContainer ?? UIView())
-        stackView.setCustomSpacing(24, after: imageContainer)
-
-        addSubview(stackView)
-
-        nameLabel.snp.makeConstraints { make in
-            make.top.bottom.centerX.equalToSuperview()
-            make.left.greaterThanOrEqualToSuperview().offset(10)
-            make.right.lessThanOrEqualToSuperview().offset(-10)
-        }
-
-        stackView.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(40)
-            make.left.equalToSuperview().offset(16)
-            make.right.equalToSuperview().offset(-16)
-            make.bottom.equalToSuperview().offset(-30)
-        }
+  }
+  
+  public init() {
+    super.init(frame: .zero)
+    
+    backgroundColor = Asset.neutralBody.color
+    
+    nameLabel.textColor = Asset.neutralWhite.color
+    nameLabel.numberOfLines = 2
+    nameLabel.textAlignment = .center
+    nameLabel.font = Fonts.Mulish.bold.font(size: 24.0)
+    
+    nameContainer = nameLabel.pinning(at: .center(0))
+    let imageContainer = avatarView.pinning(at: .hCenter)
+    
+    stackView.axis = .vertical
+    stackView.addArrangedSubview(imageContainer)
+    stackView.addArrangedSubview(nameContainer ?? UIView())
+    stackView.setCustomSpacing(24, after: imageContainer)
+    
+    addSubview(stackView)
+    
+    nameLabel.snp.makeConstraints { make in
+      make.top.bottom.centerX.equalToSuperview()
+      make.left.greaterThanOrEqualToSuperview().offset(10)
+      make.right.lessThanOrEqualToSuperview().offset(-10)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    public func setupButtons(
-        info: @escaping () -> Void,
-        send: @escaping () -> Void
-    ) {
-        let container = UIView()
-        container.addSubview(sendMessageView)
-
-        sendMessageView.didTapInfo = info
-        sendMessageView.didTapSend = send
-
-        sendMessageView.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.greaterThanOrEqualToSuperview()
-            make.centerX.equalToSuperview()
-            make.right.lessThanOrEqualToSuperview()
-            make.bottom.equalToSuperview()
-        }
-
-        if let nameContainer = nameContainer {
-            stackView.addArrangedSubview(container)
-            stackView.setCustomSpacing(48, after: nameContainer)
-        }
+    
+    stackView.snp.makeConstraints { make in
+      make.top.equalToSuperview().offset(40)
+      make.left.equalToSuperview().offset(16)
+      make.right.equalToSuperview().offset(-16)
+      make.bottom.equalToSuperview().offset(-30)
     }
-}
-
-private final class AvatarSendMessageView: UIView {
-    let stackView = UIStackView()
-    let iconImageView = UIImageView()
-    let sendButton = UIButton()
-    let infoButton = UIButton()
-
-    var didTapInfo: (() -> Void)?
-    var didTapSend: (() -> Void)?
-
-    init() {
-        super.init(frame: .zero)
-
-        iconImageView.contentMode = .center
-        iconImageView.image = Asset.contactSendMessage.image
-
-        sendButton.setTitle("Send Message", for: .normal)
-        sendButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
-        sendButton.titleLabel?.font = Fonts.Mulish.regular.font(size: 13.0)
-
-        infoButton.setImage(Asset.infoIconGrey.image, for: .normal)
-
-        sendButton.addTarget(self, action: #selector(didTapSendButton), for: .touchUpInside)
-        infoButton.addTarget(self, action: #selector(didTapInfoButton), for: .touchUpInside)
-
-        stackView.spacing = 8
-        stackView.distribution = .equalSpacing
-        stackView.addArrangedSubview(iconImageView)
-        stackView.addArrangedSubview(sendButton)
-        stackView.addArrangedSubview(infoButton)
-
-        addSubview(stackView)
-        stackView.snp.makeConstraints { $0.edges.equalToSuperview() }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  public func setupButtons(
+    info: @escaping () -> Void,
+    send: @escaping () -> Void
+  ) {
+    let container = UIView()
+    container.addSubview(sendMessageView)
+    
+    sendMessageView.didTapInfo = info
+    sendMessageView.didTapSend = send
+    
+    sendMessageView.snp.makeConstraints { make in
+      make.top.equalToSuperview()
+      make.left.greaterThanOrEqualToSuperview()
+      make.centerX.equalToSuperview()
+      make.right.lessThanOrEqualToSuperview()
+      make.bottom.equalToSuperview()
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    @objc private func didTapSendButton() {
-        didTapSend?()
+    
+    if let nameContainer = nameContainer {
+      stackView.addArrangedSubview(container)
+      stackView.setCustomSpacing(48, after: nameContainer)
     }
+  }
+}
 
-    @objc private func didTapInfoButton() {
-        didTapInfo?()
-    }
+private final class AvatarSendMessageView: UIView {
+  let stackView = UIStackView()
+  let iconImageView = UIImageView()
+  let sendButton = UIButton()
+  let infoButton = UIButton()
+  
+  var didTapInfo: (() -> Void)?
+  var didTapSend: (() -> Void)?
+  
+  init() {
+    super.init(frame: .zero)
+    
+    iconImageView.contentMode = .center
+    iconImageView.image = Asset.contactSendMessage.image
+    
+    sendButton.setTitle("Send Message", for: .normal)
+    sendButton.setTitleColor(Asset.brandPrimary.color, for: .normal)
+    sendButton.titleLabel?.font = Fonts.Mulish.regular.font(size: 13.0)
+    
+    infoButton.setImage(Asset.infoIconGrey.image, for: .normal)
+    
+    sendButton.addTarget(self, action: #selector(didTapSendButton), for: .touchUpInside)
+    infoButton.addTarget(self, action: #selector(didTapInfoButton), for: .touchUpInside)
+    
+    stackView.spacing = 8
+    stackView.distribution = .equalSpacing
+    stackView.addArrangedSubview(iconImageView)
+    stackView.addArrangedSubview(sendButton)
+    stackView.addArrangedSubview(infoButton)
+    
+    addSubview(stackView)
+    stackView.snp.makeConstraints { $0.edges.equalToSuperview() }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  @objc private func didTapSendButton() {
+    didTapSend?()
+  }
+  
+  @objc private func didTapInfoButton() {
+    didTapInfo?()
+  }
 }
 
 public final class EditableAvatarView: UIView {
-    public let editButton = UIButton()
-    public let imageView = UIImageView()
-    public let placeholderImageView = UIImageView()
-
-    init() {
-        super.init(frame: .zero)
-
-        imageView.layer.cornerRadius = 38
-        imageView.layer.masksToBounds = true
-        imageView.contentMode = .scaleAspectFill
-        imageView.backgroundColor = Asset.brandPrimary.color
-
-        placeholderImageView.contentMode = .center
-        placeholderImageView.image = Asset.profileImagePlaceholder.image
-
-        editButton.setImage(Asset.profileImageButton.image, for: .normal)
-
-        addSubview(imageView)
-        addSubview(editButton)
-        imageView.addSubview(placeholderImageView)
-
-        editButton.snp.makeConstraints { make in
-            make.bottom.equalTo(imageView)
-            make.right.equalTo(imageView).offset(9)
-        }
-
-        imageView.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.equalToSuperview()
-            make.width.height.equalTo(100)
-        }
-
-        placeholderImageView.snp.makeConstraints { $0.center.equalToSuperview() }
+  public let editButton = UIButton()
+  public let imageView = UIImageView()
+  public let placeholderImageView = UIImageView()
+  
+  init() {
+    super.init(frame: .zero)
+    
+    imageView.layer.cornerRadius = 38
+    imageView.layer.masksToBounds = true
+    imageView.contentMode = .scaleAspectFill
+    imageView.backgroundColor = Asset.brandPrimary.color
+    
+    placeholderImageView.contentMode = .center
+    placeholderImageView.image = Asset.profileImagePlaceholder.image
+    
+    editButton.setImage(Asset.profileImageButton.image, for: .normal)
+    
+    addSubview(imageView)
+    addSubview(editButton)
+    imageView.addSubview(placeholderImageView)
+    
+    editButton.snp.makeConstraints { make in
+      make.bottom.equalTo(imageView)
+      make.right.equalTo(imageView).offset(9)
     }
-
-    required init?(coder: NSCoder) { nil }
+    
+    imageView.snp.makeConstraints { make in
+      make.top.equalToSuperview()
+      make.left.equalToSuperview()
+      make.right.equalToSuperview()
+      make.bottom.equalToSuperview()
+      make.width.height.equalTo(100)
+    }
+    
+    placeholderImageView.snp.makeConstraints { $0.center.equalToSuperview() }
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/Shared/Views/AvatarCell.swift b/Sources/Shared/Views/AvatarCell.swift
index 43f0e3fd6686464b6d66c31770627134e9c075c0..d37bbb35cb2ef214140498d77b16800e512793b0 100644
--- a/Sources/Shared/Views/AvatarCell.swift
+++ b/Sources/Shared/Views/AvatarCell.swift
@@ -1,187 +1,188 @@
 import UIKit
 import Combine
+import AppResources
 
 final class AvatarCellButton: UIControl {
-    let titleLabel = UILabel()
-    let imageView = UIImageView()
-
-    init() {
-        super.init(frame: .zero)
-        titleLabel.numberOfLines = 0
-        titleLabel.textAlignment = .right
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
-
-        addSubview(imageView)
-        addSubview(titleLabel)
-
-        imageView.snp.makeConstraints {
-            $0.top.greaterThanOrEqualToSuperview()
-            $0.left.equalToSuperview()
-            $0.centerY.equalToSuperview()
-            $0.bottom.lessThanOrEqualToSuperview()
-        }
-
-        titleLabel.snp.makeConstraints {
-            $0.top.greaterThanOrEqualToSuperview()
-            $0.left.equalTo(imageView.snp.right).offset(5)
-            $0.centerY.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.width.equalTo(60)
-            $0.bottom.lessThanOrEqualToSuperview()
-        }
+  let titleLabel = UILabel()
+  let imageView = UIImageView()
+  
+  init() {
+    super.init(frame: .zero)
+    titleLabel.numberOfLines = 0
+    titleLabel.textAlignment = .right
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
+    
+    addSubview(imageView)
+    addSubview(titleLabel)
+    
+    imageView.snp.makeConstraints {
+      $0.top.greaterThanOrEqualToSuperview()
+      $0.left.equalToSuperview()
+      $0.centerY.equalToSuperview()
+      $0.bottom.lessThanOrEqualToSuperview()
     }
-
-    required init?(coder: NSCoder) { nil }
+    
+    titleLabel.snp.makeConstraints {
+      $0.top.greaterThanOrEqualToSuperview()
+      $0.left.equalTo(imageView.snp.right).offset(5)
+      $0.centerY.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.width.equalTo(60)
+      $0.bottom.lessThanOrEqualToSuperview()
+    }
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
 
 public final class AvatarCell: UITableViewCell {
-    let h1Label = UILabel()
-    let h2Label = UILabel()
-    let h3Label = UILabel()
-    let h4Label = UILabel()
-    let separatorView = UIView()
-    let avatarView = AvatarView()
-    let stackView = UIStackView()
-    let stateButton = AvatarCellButton()
-
-    var cancellables = Set<AnyCancellable>()
-    public var didTapStateButton: (() -> Void)!
-
-    public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
-        super.init(style: style, reuseIdentifier: reuseIdentifier)
-
-        selectedBackgroundView = UIView()
-        multipleSelectionBackgroundView = UIView()
-        backgroundColor = Asset.neutralWhite.color
-
-        h1Label.textColor = Asset.neutralActive.color
-        h2Label.textColor = Asset.neutralSecondaryAlternative.color
-        h3Label.textColor = Asset.neutralSecondaryAlternative.color
-        h4Label.textColor = Asset.neutralSecondaryAlternative.color
-
-        h1Label.font = Fonts.Mulish.semiBold.font(size: 14.0)
-        h2Label.font = Fonts.Mulish.regular.font(size: 14.0)
-        h3Label.font = Fonts.Mulish.regular.font(size: 14.0)
-        h4Label.font = Fonts.Mulish.regular.font(size: 14.0)
-
-        stackView.spacing = 4
-        stackView.axis = .vertical
-        
-        stackView.addArrangedSubview(h1Label)
-        stackView.addArrangedSubview(h2Label)
-        stackView.addArrangedSubview(h3Label)
-        stackView.addArrangedSubview(h4Label)
-
-        separatorView.backgroundColor = Asset.neutralLine.color
-
-        contentView.addSubview(stackView)
-        contentView.addSubview(avatarView)
-        contentView.addSubview(stateButton)
-        contentView.addSubview(separatorView)
-
-        setupConstraints()
+  let h1Label = UILabel()
+  let h2Label = UILabel()
+  let h3Label = UILabel()
+  let h4Label = UILabel()
+  let separatorView = UIView()
+  let avatarView = AvatarView()
+  let stackView = UIStackView()
+  let stateButton = AvatarCellButton()
+  
+  var cancellables = Set<AnyCancellable>()
+  public var didTapStateButton: (() -> Void)!
+  
+  public override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
+    super.init(style: style, reuseIdentifier: reuseIdentifier)
+    
+    selectedBackgroundView = UIView()
+    multipleSelectionBackgroundView = UIView()
+    backgroundColor = Asset.neutralWhite.color
+    
+    h1Label.textColor = Asset.neutralActive.color
+    h2Label.textColor = Asset.neutralSecondaryAlternative.color
+    h3Label.textColor = Asset.neutralSecondaryAlternative.color
+    h4Label.textColor = Asset.neutralSecondaryAlternative.color
+    
+    h1Label.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    h2Label.font = Fonts.Mulish.regular.font(size: 14.0)
+    h3Label.font = Fonts.Mulish.regular.font(size: 14.0)
+    h4Label.font = Fonts.Mulish.regular.font(size: 14.0)
+    
+    stackView.spacing = 4
+    stackView.axis = .vertical
+    
+    stackView.addArrangedSubview(h1Label)
+    stackView.addArrangedSubview(h2Label)
+    stackView.addArrangedSubview(h3Label)
+    stackView.addArrangedSubview(h4Label)
+    
+    separatorView.backgroundColor = Asset.neutralLine.color
+    
+    contentView.addSubview(stackView)
+    contentView.addSubview(avatarView)
+    contentView.addSubview(stateButton)
+    contentView.addSubview(separatorView)
+    
+    setupConstraints()
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  public override func prepareForReuse() {
+    super.prepareForReuse()
+    h1Label.text = nil
+    h2Label.text = nil
+    h3Label.text = nil
+    h4Label.text = nil
+    
+    stateButton.imageView.image = nil
+    stateButton.titleLabel.text = nil
+    
+    avatarView.prepareForReuse()
+    cancellables.removeAll()
+  }
+  
+  public func setup(
+    title: String,
+    image: Data?,
+    firstSubtitle: String? = nil,
+    secondSubtitle: String? = nil,
+    thirdSubtitle: String? = nil,
+    showSeparator: Bool = true,
+    sent: Bool = false
+  ) {
+    h1Label.text = title
+    
+    if let firstSubtitle = firstSubtitle {
+      h2Label.isHidden = false
+      h2Label.text = firstSubtitle
+    } else {
+      h2Label.isHidden = true
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    public override func prepareForReuse() {
-        super.prepareForReuse()
-        h1Label.text = nil
-        h2Label.text = nil
-        h3Label.text = nil
-        h4Label.text = nil
-
-        stateButton.imageView.image = nil
-        stateButton.titleLabel.text = nil
-
-        avatarView.prepareForReuse()
-        cancellables.removeAll()
+    
+    if let secondSubtitle = secondSubtitle {
+      h3Label.isHidden = false
+      h3Label.text = secondSubtitle
+    } else {
+      h3Label.isHidden = true
     }
-
-    public func setup(
-        title: String,
-        image: Data?,
-        firstSubtitle: String? = nil,
-        secondSubtitle: String? = nil,
-        thirdSubtitle: String? = nil,
-        showSeparator: Bool = true,
-        sent: Bool = false
-    ) {
-        h1Label.text = title
-
-        if let firstSubtitle = firstSubtitle {
-            h2Label.isHidden = false
-            h2Label.text = firstSubtitle
-        } else {
-            h2Label.isHidden = true
-        }
-
-        if let secondSubtitle = secondSubtitle {
-            h3Label.isHidden = false
-            h3Label.text = secondSubtitle
-        } else {
-            h3Label.isHidden = true
-        }
-
-        if let thirdSubtitle = thirdSubtitle {
-            h4Label.isHidden = false
-            h4Label.text = thirdSubtitle
-        } else {
-            h4Label.isHidden = true
-        }
-
-        avatarView.setupProfile(title: title, image: image, size: .medium)
-        separatorView.alpha = showSeparator ? 1.0 : 0.0
-
-        cancellables.removeAll()
-
-        if sent {
-            stateButton.imageView.image = Asset.requestsResend.image
-            stateButton.titleLabel.text = Localized.Requests.Cell.requested
-            stateButton.titleLabel.textColor = Asset.brandPrimary.color
-
-            stateButton
-                .publisher(for: .touchUpInside)
-                .sink { [unowned self] in didTapStateButton() }
-                .store(in: &cancellables)
-        }
+    
+    if let thirdSubtitle = thirdSubtitle {
+      h4Label.isHidden = false
+      h4Label.text = thirdSubtitle
+    } else {
+      h4Label.isHidden = true
     }
-
-    public func updateToResent() {
-        stateButton.imageView.image = Asset.requestsResent.image
-        stateButton.titleLabel.text = Localized.Requests.Cell.resent
-        stateButton.titleLabel.textColor = Asset.neutralWeak.color
-
-        cancellables.forEach { $0.cancel() }
-        cancellables.removeAll()
+    
+    avatarView.setupProfile(title: title, image: image, size: .medium)
+    separatorView.alpha = showSeparator ? 1.0 : 0.0
+    
+    cancellables.removeAll()
+    
+    if sent {
+      stateButton.imageView.image = Asset.requestsResend.image
+      stateButton.titleLabel.text = Localized.Requests.Cell.requested
+      stateButton.titleLabel.textColor = Asset.brandPrimary.color
+      
+      stateButton
+        .publisher(for: .touchUpInside)
+        .sink { [unowned self] in didTapStateButton() }
+        .store(in: &cancellables)
     }
-
-    private func setupConstraints() {
-        avatarView.snp.makeConstraints {
-            $0.width.height.equalTo(36)
-            $0.left.equalToSuperview().offset(27)
-            $0.centerY.equalToSuperview()
-        }
-
-        stackView.snp.makeConstraints {
-            $0.top.equalTo(avatarView)
-            $0.left.equalTo(avatarView.snp.right).offset(14)
-            $0.right.lessThanOrEqualToSuperview().offset(-10)
-            $0.bottom.greaterThanOrEqualTo(avatarView)
-            $0.bottom.lessThanOrEqualToSuperview()
-        }
-
-        separatorView.snp.makeConstraints {
-            $0.height.equalTo(1)
-            $0.top.greaterThanOrEqualTo(stackView.snp.bottom).offset(10)
-            $0.left.equalToSuperview().offset(25)
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-        }
-
-        stateButton.snp.makeConstraints {
-            $0.centerY.equalTo(stackView)
-            $0.right.equalToSuperview().offset(-24)
-        }
+  }
+  
+  public func updateToResent() {
+    stateButton.imageView.image = Asset.requestsResent.image
+    stateButton.titleLabel.text = Localized.Requests.Cell.resent
+    stateButton.titleLabel.textColor = Asset.neutralWeak.color
+    
+    cancellables.forEach { $0.cancel() }
+    cancellables.removeAll()
+  }
+  
+  private func setupConstraints() {
+    avatarView.snp.makeConstraints {
+      $0.width.height.equalTo(36)
+      $0.left.equalToSuperview().offset(27)
+      $0.centerY.equalToSuperview()
+    }
+    
+    stackView.snp.makeConstraints {
+      $0.top.equalTo(avatarView)
+      $0.left.equalTo(avatarView.snp.right).offset(14)
+      $0.right.lessThanOrEqualToSuperview().offset(-10)
+      $0.bottom.greaterThanOrEqualTo(avatarView)
+      $0.bottom.lessThanOrEqualToSuperview()
+    }
+    
+    separatorView.snp.makeConstraints {
+      $0.height.equalTo(1)
+      $0.top.greaterThanOrEqualTo(stackView.snp.bottom).offset(10)
+      $0.left.equalToSuperview().offset(25)
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
+    
+    stateButton.snp.makeConstraints {
+      $0.centerY.equalTo(stackView)
+      $0.right.equalToSuperview().offset(-24)
     }
+  }
 }
diff --git a/Sources/Shared/Views/AvatarView.swift b/Sources/Shared/Views/AvatarView.swift
index a1104edb680c869092a0017ef5e8c87310ae7bd5..cacce36f254322f1bcf58141d62852ec3ca6e57b 100644
--- a/Sources/Shared/Views/AvatarView.swift
+++ b/Sources/Shared/Views/AvatarView.swift
@@ -1,95 +1,96 @@
 import UIKit
+import AppResources
 
 public final class AvatarView: UIView {
-    public enum Size {
-        case small
-        case medium
-        case large
-    }
-
-    let imageView = UIImageView()
-    let monogramLabel = UILabel()
-    let iconImageView = UIImageView()
-
-    public init() {
-        super.init(frame: .zero)
+  public enum Size {
+    case small
+    case medium
+    case large
+  }
 
-        layer.masksToBounds = true
-        backgroundColor = Asset.brandPrimary.color
+  let imageView = UIImageView()
+  let monogramLabel = UILabel()
+  let iconImageView = UIImageView()
 
-        iconImageView.contentMode = .center
-        imageView.contentMode = .scaleAspectFill
-        monogramLabel.textColor = Asset.neutralWhite.color
+  public init() {
+    super.init(frame: .zero)
 
-        addSubview(monogramLabel)
-        addSubview(iconImageView)
-        addSubview(imageView)
+    layer.masksToBounds = true
+    backgroundColor = Asset.brandPrimary.color
 
-        imageView.snp.makeConstraints {
-            $0.edges.equalToSuperview()
-        }
+    iconImageView.contentMode = .center
+    imageView.contentMode = .scaleAspectFill
+    monogramLabel.textColor = Asset.neutralWhite.color
 
-        monogramLabel.snp.makeConstraints {
-            $0.center.equalToSuperview()
-        }
+    addSubview(monogramLabel)
+    addSubview(iconImageView)
+    addSubview(imageView)
 
-        iconImageView.snp.makeConstraints {
-            $0.center.equalToSuperview()
-        }
+    imageView.snp.makeConstraints {
+      $0.edges.equalToSuperview()
     }
 
-    required init?(coder: NSCoder) { nil }
+    monogramLabel.snp.makeConstraints {
+      $0.center.equalToSuperview()
+    }
 
-    public func prepareForReuse() {
-        imageView.image = nil
-        monogramLabel.text = nil
-        iconImageView.image = nil
+    iconImageView.snp.makeConstraints {
+      $0.center.equalToSuperview()
+    }
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  public func prepareForReuse() {
+    imageView.image = nil
+    monogramLabel.text = nil
+    iconImageView.image = nil
+  }
+
+  public func setupProfile(title: String, image: Data?, size: AvatarView.Size) {
+    iconImageView.image = nil
+    monogramLabel.text = title
+      .trimmingCharacters(in: .whitespacesAndNewlines)
+      .replacingOccurrences(of: " ", with: "")
+      .prefix(2)
+      .uppercased()
+
+    monogramLabel.text = "\(title.prefix(2))".uppercased()
+
+    // TODO: What are the font sizes and corner radius for small/medium avatars?
+
+    switch size {
+    case .small:
+      layer.cornerRadius = 13.0
+      monogramLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    case .medium:
+      layer.cornerRadius = 13.0
+      monogramLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    case .large:
+      layer.cornerRadius = 18.0
+      monogramLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
     }
 
-    public func setupProfile(title: String, image: Data?, size: AvatarView.Size) {
-        iconImageView.image = nil
-        monogramLabel.text = title
-            .trimmingCharacters(in: .whitespacesAndNewlines)
-            .replacingOccurrences(of: " ", with: "")
-            .prefix(2)
-            .uppercased()
-
-        monogramLabel.text = "\(title.prefix(2))".uppercased()
-
-        // TODO: What are the font sizes and corner radius for small/medium avatars?
-
-        switch size {
-        case .small:
-            layer.cornerRadius = 13.0
-            monogramLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
-        case .medium:
-            layer.cornerRadius = 13.0
-            monogramLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
-        case .large:
-            layer.cornerRadius = 18.0
-            monogramLabel.font = Fonts.Mulish.semiBold.font(size: 16.0)
-        }
-
-        guard let image = image else {
-            imageView.image = nil
-            return
-        }
-
-        imageView.image = UIImage(data: image)
+    guard let image = image else {
+      imageView.image = nil
+      return
     }
 
-    public func setupGroup(size: AvatarView.Size) {
-        switch size {
-        case .small:
-            layer.cornerRadius = 13.0
-        case .medium:
-            layer.cornerRadius = 13.0
-        case .large:
-            layer.cornerRadius = 18.0
-        }
-
-        imageView.image = nil
-        monogramLabel.text = nil
-        iconImageView.image = Asset.sharedGroup.image
+    imageView.image = UIImage(data: image)
+  }
+
+  public func setupGroup(size: AvatarView.Size) {
+    switch size {
+    case .small:
+      layer.cornerRadius = 13.0
+    case .medium:
+      layer.cornerRadius = 13.0
+    case .large:
+      layer.cornerRadius = 18.0
     }
+
+    imageView.image = nil
+    monogramLabel.text = nil
+    iconImageView.image = Asset.sharedGroup.image
+  }
 }
diff --git a/Sources/Shared/Views/BottomFeedbackComponent.swift b/Sources/Shared/Views/BottomFeedbackComponent.swift
index aedff2e8003a07590bb41c9e7acbed0830986a41..dd5e583c7e0fe8e1563cae05c68379cb225ef981 100644
--- a/Sources/Shared/Views/BottomFeedbackComponent.swift
+++ b/Sources/Shared/Views/BottomFeedbackComponent.swift
@@ -1,83 +1,76 @@
 import UIKit
+import AppResources
 
 public struct BottomFeedbackStyle {
-    var color: UIColor
-    var iconColor: UIColor
-    var titleColor: UIColor
-    var actionColor: UIColor?
+  var color: UIColor
+  var iconColor: UIColor
+  var titleColor: UIColor
+  var actionColor: UIColor?
 }
 
 public extension BottomFeedbackStyle {
-    static let danger = BottomFeedbackStyle(
-        color: Asset.accentDanger.color,
-        iconColor: Asset.neutralWhite.color,
-        titleColor: Asset.neutralWhite.color
-    )
-
-    static let chill = BottomFeedbackStyle(
-        color: Asset.neutralSecondary.color,
-        iconColor: Asset.neutralDisabled.color,
-        titleColor: Asset.neutralBody.color
-    )
+  static let danger = BottomFeedbackStyle(
+    color: Asset.accentDanger.color,
+    iconColor: Asset.neutralWhite.color,
+    titleColor: Asset.neutralWhite.color
+  )
+  
+  static let chill = BottomFeedbackStyle(
+    color: Asset.neutralSecondary.color,
+    iconColor: Asset.neutralDisabled.color,
+    titleColor: Asset.neutralBody.color
+  )
 }
 
 public final class BottomFeedbackComponent: UIView {
-    // MARK: UI
-
-    public let title = UILabel()
-    public let icon = UIImageView()
-    public let stack = UIStackView()
-    public let button = CapsuleButton(height: 50.0, minimumWidth: 100.0)
-
-    // MARK: Lifecycle
-
-    public init() {
-        super.init(frame: .zero)
-        setup()
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    // MARK: Public
-
-    public func set(
-        icon: UIImage,
-        title: String,
-        style: BottomFeedbackStyle,
-        actionTitle: String? = nil,
-        actionStyle: CapsuleButtonStyle = .seeThroughWhite
-    ) {
-        backgroundColor = style.color
-        self.icon.tintColor = style.iconColor
-        self.title.textColor = style.titleColor
-
-        self.title.text = title
-        self.icon.image = icon.withRenderingMode(.alwaysTemplate)
-
-        guard let actionTitle = actionTitle else { return }
-
-        button.setStyle(actionStyle)
-        button.setTitle(actionTitle, for: .normal)
-        stack.addArrangedSubview(button.pinning(at: .center(0)))
-    }
-
-    // MARK: Private
-
-    private func setup() {
-        layer.cornerRadius = 15
-        icon.contentMode = .center
-        title.font = Fonts.Mulish.semiBold.font(size: 14.0)
-
-        stack.spacing = 10
-        stack.addArrangedSubview(icon)
-        stack.addArrangedSubview(title.pinning(at: .left(0)))
-        addSubview(stack)
-
-        stack.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(20)
-            make.left.equalToSuperview().offset(20)
-            make.right.equalToSuperview().offset(-20)
-            make.bottom.equalToSuperview().offset(-40)
-        }
+  public let title = UILabel()
+  public let icon = UIImageView()
+  public let stack = UIStackView()
+  public let button = CapsuleButton(height: 50.0, minimumWidth: 100.0)
+  
+  public init() {
+    super.init(frame: .zero)
+    setup()
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  public func set(
+    icon: UIImage,
+    title: String,
+    style: BottomFeedbackStyle,
+    actionTitle: String? = nil,
+    actionStyle: CapsuleButtonStyle = .seeThroughWhite
+  ) {
+    backgroundColor = style.color
+    self.icon.tintColor = style.iconColor
+    self.title.textColor = style.titleColor
+    
+    self.title.text = title
+    self.icon.image = icon.withRenderingMode(.alwaysTemplate)
+    
+    guard let actionTitle = actionTitle else { return }
+    
+    button.setStyle(actionStyle)
+    button.setTitle(actionTitle, for: .normal)
+    stack.addArrangedSubview(button.pinning(at: .center(0)))
+  }
+
+  private func setup() {
+    layer.cornerRadius = 15
+    icon.contentMode = .center
+    title.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    
+    stack.spacing = 10
+    stack.addArrangedSubview(icon)
+    stack.addArrangedSubview(title.pinning(at: .left(0)))
+    addSubview(stack)
+    
+    stack.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(20)
+      $0.left.equalToSuperview().offset(20)
+      $0.right.equalToSuperview().offset(-20)
+      $0.bottom.equalToSuperview().offset(-40)
     }
+  }
 }
diff --git a/Sources/Shared/Views/CapsuleButton.swift b/Sources/Shared/Views/CapsuleButton.swift
index 4d681dc36b0f5c8ca9d214ac2ce026c940eadf01..e3dfc57373b2b7562c4a1297ab78d8d543327605 100644
--- a/Sources/Shared/Views/CapsuleButton.swift
+++ b/Sources/Shared/Views/CapsuleButton.swift
@@ -1,153 +1,142 @@
 import UIKit
+import AppResources
 
 public struct CapsuleButtonModel {
-    public var title: String
-    public var accessibility: String?
-    public var style: CapsuleButtonStyle
-
-    public init(
-        title: String,
-        style: CapsuleButtonStyle,
-        accessibility: String? = nil
-    ) {
-        self.title = title
-        self.style = style
-        self.accessibility = accessibility
-    }
+  public var title: String
+  public var accessibility: String?
+  public var style: CapsuleButtonStyle
+  
+  public init(
+    title: String,
+    style: CapsuleButtonStyle,
+    accessibility: String? = nil
+  ) {
+    self.title = title
+    self.style = style
+    self.accessibility = accessibility
+  }
 }
 
 public struct CapsuleButtonStyle {
-    var fill: UIImage
-    var borderWidth: CGFloat
-    var borderColor: UIColor?
-    var titleColor: UIColor
-    var disabledTitleColor: UIColor
+  var fill: UIImage
+  var borderWidth: CGFloat
+  var borderColor: UIColor?
+  var titleColor: UIColor
+  var disabledTitleColor: UIColor
 }
 
 public extension CapsuleButtonStyle {
-    static let white = CapsuleButtonStyle(
-        fill: .color(Asset.neutralWhite.color),
-        borderWidth: 0,
-        borderColor: nil,
-        titleColor: Asset.brandPrimary.color,
-        disabledTitleColor: Asset.neutralWhite.color.withAlphaComponent(0.5)
-    )
-
-    static let brandColored = CapsuleButtonStyle(
-        fill: .color(Asset.brandPrimary.color),
-        borderWidth: 0,
-        borderColor: nil,
-        titleColor: Asset.neutralWhite.color,
-        disabledTitleColor: Asset.neutralWhite.color
-    )
-
-    static let red = CapsuleButtonStyle(
-        fill: .color(Asset.accentDanger.color),
-        borderWidth: 0,
-        borderColor: nil,
-        titleColor: Asset.neutralWhite.color,
-        disabledTitleColor: Asset.neutralWhite.color
-    )
-
-    static let seeThroughWhite = CapsuleButtonStyle(
-        fill: .color(UIColor.clear),
-        borderWidth: 2,
-        borderColor: Asset.neutralWhite.color,
-        titleColor: Asset.neutralWhite.color,
-        disabledTitleColor: Asset.neutralWhite.color.withAlphaComponent(0.5)
-    )
-
-    static let seeThrough = CapsuleButtonStyle(
-        fill: .color(UIColor.clear),
-        borderWidth: 2,
-        borderColor: Asset.brandPrimary.color,
-        titleColor: Asset.brandPrimary.color,
-        disabledTitleColor: Asset.brandPrimary.color.withAlphaComponent(0.5)
-    )
-
-    static let simplestColoredRed = CapsuleButtonStyle(
-        fill: .color(UIColor.clear),
-        borderWidth: 0,
-        borderColor: nil,
-        titleColor: Asset.accentDanger.color,
-        disabledTitleColor: Asset.brandDefault.color.withAlphaComponent(0.5)
-    )
-
-    static let simplestColoredBrand = CapsuleButtonStyle(
-        fill: .color(UIColor.clear),
-        borderWidth: 0,
-        borderColor: nil,
-        titleColor: Asset.brandPrimary.color,
-        disabledTitleColor: Asset.brandDefault.color.withAlphaComponent(0.5)
-    )
+  static let white = CapsuleButtonStyle(
+    fill: .color(Asset.neutralWhite.color),
+    borderWidth: 0,
+    borderColor: nil,
+    titleColor: Asset.brandPrimary.color,
+    disabledTitleColor: Asset.neutralWhite.color.withAlphaComponent(0.5)
+  )
+  
+  static let brandColored = CapsuleButtonStyle(
+    fill: .color(Asset.brandPrimary.color),
+    borderWidth: 0,
+    borderColor: nil,
+    titleColor: Asset.neutralWhite.color,
+    disabledTitleColor: Asset.neutralWhite.color
+  )
+  
+  static let red = CapsuleButtonStyle(
+    fill: .color(Asset.accentDanger.color),
+    borderWidth: 0,
+    borderColor: nil,
+    titleColor: Asset.neutralWhite.color,
+    disabledTitleColor: Asset.neutralWhite.color
+  )
+  
+  static let seeThroughWhite = CapsuleButtonStyle(
+    fill: .color(UIColor.clear),
+    borderWidth: 2,
+    borderColor: Asset.neutralWhite.color,
+    titleColor: Asset.neutralWhite.color,
+    disabledTitleColor: Asset.neutralWhite.color.withAlphaComponent(0.5)
+  )
+  
+  static let seeThrough = CapsuleButtonStyle(
+    fill: .color(UIColor.clear),
+    borderWidth: 2,
+    borderColor: Asset.brandPrimary.color,
+    titleColor: Asset.brandPrimary.color,
+    disabledTitleColor: Asset.brandPrimary.color.withAlphaComponent(0.5)
+  )
+  
+  static let simplestColoredRed = CapsuleButtonStyle(
+    fill: .color(UIColor.clear),
+    borderWidth: 0,
+    borderColor: nil,
+    titleColor: Asset.accentDanger.color,
+    disabledTitleColor: Asset.brandDefault.color.withAlphaComponent(0.5)
+  )
+  
+  static let simplestColoredBrand = CapsuleButtonStyle(
+    fill: .color(UIColor.clear),
+    borderWidth: 0,
+    borderColor: nil,
+    titleColor: Asset.brandPrimary.color,
+    disabledTitleColor: Asset.brandDefault.color.withAlphaComponent(0.5)
+  )
 }
 
 public final class CapsuleButton: UIButton {
-    // MARK: Properties
-
-    private let height: CGFloat
-    private let minimumWidth: CGFloat
-
-    // MARK: Lifecycle
-
-    public init(
-        height: CGFloat = 55.0,
-        minimumWidth: CGFloat = 200
-    ) {
-        self.height = height
-        self.minimumWidth = minimumWidth
-
-        super.init(frame: .zero)
-        setup()
+  private let height: CGFloat
+  private let minimumWidth: CGFloat
+
+  public init(
+    height: CGFloat = 55.0,
+    minimumWidth: CGFloat = 200
+  ) {
+    self.height = height
+    self.minimumWidth = minimumWidth
+    super.init(frame: .zero)
+
+    layer.cornerRadius = 55/2
+    layer.masksToBounds = true
+    titleLabel!.font = Fonts.Mulish.semiBold.font(size: 16.0)
+    adjustsImageWhenHighlighted = false
+
+    setBackgroundImage(.color(Asset.neutralDisabled.color), for: .disabled)
+
+    snp.makeConstraints {
+      $0.height.equalTo(height)
+      $0.width.greaterThanOrEqualTo(minimumWidth)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    // MARK: Public
-
-    public func set(
-        style: CapsuleButtonStyle,
-        title: String,
-        accessibility: String? = nil
-    ) {
-        setTitle(title, for: .normal)
-        accessibilityIdentifier = accessibility
-        layer.borderWidth = style.borderWidth
-
-        if let color = style.borderColor {
-            layer.borderColor = color.cgColor
-        }
-
-        setBackgroundImage(style.fill, for: .normal)
-        setTitleColor(style.titleColor, for: .normal)
-        setTitleColor(style.disabledTitleColor, for: .disabled)
-    }
-
-    public func setStyle(_ style: CapsuleButtonStyle) {
-        layer.borderWidth = style.borderWidth
-
-        if let color = style.borderColor {
-            layer.borderColor = color.cgColor
-        }
-
-        setBackgroundImage(style.fill, for: .normal)
-        setTitleColor(style.titleColor, for: .normal)
-        setTitleColor(style.disabledTitleColor, for: .disabled)
+  }
+  
+  required init?(coder: NSCoder) { nil }
+
+  public func set(
+    style: CapsuleButtonStyle,
+    title: String,
+    accessibility: String? = nil
+  ) {
+    setTitle(title, for: .normal)
+    accessibilityIdentifier = accessibility
+    layer.borderWidth = style.borderWidth
+    
+    if let color = style.borderColor {
+      layer.borderColor = color.cgColor
     }
-
-    // MARK: Private
-
-    private func setup() {
-        layer.cornerRadius = 55/2
-        layer.masksToBounds = true
-        titleLabel!.font = Fonts.Mulish.semiBold.font(size: 16.0)
-        adjustsImageWhenHighlighted = false
-
-        setBackgroundImage(.color(Asset.neutralDisabled.color), for: .disabled)
-
-        snp.makeConstraints { make in
-            make.height.equalTo(height)
-            make.width.greaterThanOrEqualTo(minimumWidth)
-        }
+    
+    setBackgroundImage(style.fill, for: .normal)
+    setTitleColor(style.titleColor, for: .normal)
+    setTitleColor(style.disabledTitleColor, for: .disabled)
+  }
+  
+  public func setStyle(_ style: CapsuleButtonStyle) {
+    layer.borderWidth = style.borderWidth
+    
+    if let color = style.borderColor {
+      layer.borderColor = color.cgColor
     }
+    
+    setBackgroundImage(style.fill, for: .normal)
+    setTitleColor(style.titleColor, for: .normal)
+    setTitleColor(style.disabledTitleColor, for: .disabled)
+  }
 }
diff --git a/Sources/Shared/Views/DetailRowButton.swift b/Sources/Shared/Views/DetailRowButton.swift
index 132d499ac0e0223be1f9333cbd6e1643cfff7157..fe0eea6ce263a6cffcc11e0872d3f2ed538c04ee 100644
--- a/Sources/Shared/Views/DetailRowButton.swift
+++ b/Sources/Shared/Views/DetailRowButton.swift
@@ -1,48 +1,47 @@
 import UIKit
+import AppResources
 
 public final class DetailRowButton: UIControl {
-    let titleLabel = UILabel()
-    let valueLabel = UILabel()
-    let rowIndicator = UIImageView()
-
-    public init() {
-        super.init(frame: .zero)
-
-        rowIndicator.contentMode = .center
-        rowIndicator.image = Asset.settingsDisclosure.image
-
-        titleLabel.font = Fonts.Mulish.bold.font(size: 12.0)
-        valueLabel.font = Fonts.Mulish.regular.font(size: 16.0)
-
-        titleLabel.textColor = Asset.neutralWeak.color
-        valueLabel.textColor = Asset.neutralActive.color
-
-        addSubview(titleLabel)
-        addSubview(valueLabel)
-        addSubview(rowIndicator)
-
-        titleLabel.snp.makeConstraints { make in
-            make.top.equalToSuperview()
-            make.left.equalToSuperview()
-        }
-
-        valueLabel.snp.makeConstraints { make in
-            make.top.equalTo(titleLabel.snp.bottom).offset(4)
-            make.left.equalToSuperview()
-            make.bottom.equalToSuperview()
-        }
-
-        rowIndicator.snp.makeConstraints { make in
-            make.centerY.equalToSuperview()
-            make.right.equalToSuperview()
-        }
+  let titleLabel = UILabel()
+  let valueLabel = UILabel()
+  let rowIndicator = UIImageView()
+  
+  public init() {
+    super.init(frame: .zero)
+    
+    rowIndicator.contentMode = .center
+    rowIndicator.image = Asset.settingsDisclosure.image
+    
+    titleLabel.font = Fonts.Mulish.bold.font(size: 12.0)
+    valueLabel.font = Fonts.Mulish.regular.font(size: 16.0)
+    
+    titleLabel.textColor = Asset.neutralWeak.color
+    valueLabel.textColor = Asset.neutralActive.color
+    
+    addSubview(titleLabel)
+    addSubview(valueLabel)
+    addSubview(rowIndicator)
+    
+    titleLabel.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    public func setup(title: String, value: String, hasArrow: Bool = true) {
-        titleLabel.text = title
-        valueLabel.text = value
-        rowIndicator.isHidden = !hasArrow
+    valueLabel.snp.makeConstraints {
+      $0.top.equalTo(titleLabel.snp.bottom).offset(4)
+      $0.left.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
+    rowIndicator.snp.makeConstraints {
+      $0.centerY.equalToSuperview()
+      $0.right.equalToSuperview()
     }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  public func setup(title: String, value: String, hasArrow: Bool = true) {
+    titleLabel.text = title
+    valueLabel.text = value
+    rowIndicator.isHidden = !hasArrow
+  }
 }
diff --git a/Sources/Shared/Views/DotAnimation.swift b/Sources/Shared/Views/DotAnimation.swift
index bcf182b9180b7d4cfc5ef4e511083ca97727a7e6..9cda32e30765b2220e40aa1aa41d7c68a7e9a044 100644
--- a/Sources/Shared/Views/DotAnimation.swift
+++ b/Sources/Shared/Views/DotAnimation.swift
@@ -1,4 +1,5 @@
 import UIKit
+import AppResources
 
 public final class DotAnimation: UIView {
   let leftDot = UIView()
@@ -48,7 +49,7 @@ public final class DotAnimation: UIView {
 
   required init?(coder: NSCoder) { nil }
 
-  func setColor(_ color: UIColor = Asset.brandPrimary.color) {
+  public func setColor(_ color: UIColor = Asset.brandPrimary.color) {
     leftDot.backgroundColor = color
     middleDot.backgroundColor = color
     rightDot.backgroundColor = color
diff --git a/Sources/Shared/Views/FlexibleSpace.swift b/Sources/Shared/Views/FlexibleSpace.swift
index c3b323ea8d352421b5e7247402047d982cf7d4c5..082a2cf95c9e5ef3f6f8766cfd5b8471f13a6309 100644
--- a/Sources/Shared/Views/FlexibleSpace.swift
+++ b/Sources/Shared/Views/FlexibleSpace.swift
@@ -1,17 +1,17 @@
 import UIKit
 
 public final class FlexibleSpace: UIView {
-    public override init(frame: CGRect) {
-        super.init(frame: frame)
-        setContentHuggingPriority(.defaultLow, for: .horizontal)
-        setContentHuggingPriority(.defaultLow, for: .vertical)
-        setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
-        setContentCompressionResistancePriority(.defaultLow, for: .vertical)
-    }
-
-    public convenience init() {
-        self.init(frame: .zero)
-    }
-
-    required init?(coder: NSCoder) { nil }
+  public override init(frame: CGRect) {
+    super.init(frame: frame)
+    setContentHuggingPriority(.defaultLow, for: .horizontal)
+    setContentHuggingPriority(.defaultLow, for: .vertical)
+    setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
+    setContentCompressionResistancePriority(.defaultLow, for: .vertical)
+  }
+  
+  public convenience init() {
+    self.init(frame: .zero)
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/Shared/Views/RowButton.swift b/Sources/Shared/Views/RowButton.swift
index 689a705af98ce2364251f7d1d654de6eea3bd799..574b4b0908b56ba13d6c4c55f7f20c26195d97e6 100644
--- a/Sources/Shared/Views/RowButton.swift
+++ b/Sources/Shared/Views/RowButton.swift
@@ -1,78 +1,79 @@
 import UIKit
+import AppResources
 
 public struct RowButtonStyle {
-    var color: UIColor
-    var accessory: UIImage?
+  var color: UIColor
+  var accessory: UIImage?
 }
 
 public extension RowButtonStyle {
-    static let clean = RowButtonStyle(
-        color: Asset.neutralActive.color,
-        accessory: Asset.settingsDisclosure.image
-    )
-
-    static let delete = RowButtonStyle(
-        color: Asset.accentDanger.color,
-        accessory: nil
-    )
+  static let clean = RowButtonStyle(
+    color: Asset.neutralActive.color,
+    accessory: Asset.settingsDisclosure.image
+  )
+  
+  static let delete = RowButtonStyle(
+    color: Asset.accentDanger.color,
+    accessory: nil
+  )
 }
 
 public final class RowButton: UIControl {
-    public let title = UILabel()
-    public let icon = UIImageView()
-    public let separator = UIView()
-    public let stack = UIStackView()
-    public let accessory = UIImageView()
-
-    public init() {
-        super.init(frame: .zero)
-
-        icon.contentMode = .center
-        title.font = Fonts.Mulish.semiBold.font(size: 14.0)
-        separator.backgroundColor = Asset.neutralLine.color
-        icon.setContentHuggingPriority(.required, for: .horizontal)
-
-        stack.spacing = 10
-        stack.addArrangedSubview(icon)
-        stack.addArrangedSubview(title.pinning(at: .left(0)))
-        stack.addArrangedSubview(accessory.pinning(at: .top(10)))
-
-        addSubview(stack)
-        addSubview(separator)
-
-        stack.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(16)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.equalToSuperview().offset(-20)
-        }
-
-        separator.snp.makeConstraints { make in
-            make.height.equalTo(1)
-            make.left.equalToSuperview()
-            make.right.equalToSuperview()
-            make.bottom.equalToSuperview()
-        }
-
-        subviews.forEach { $0.isUserInteractionEnabled = false }
+  public let title = UILabel()
+  public let icon = UIImageView()
+  public let separator = UIView()
+  public let stack = UIStackView()
+  public let accessory = UIImageView()
+  
+  public init() {
+    super.init(frame: .zero)
+    
+    icon.contentMode = .center
+    title.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    separator.backgroundColor = Asset.neutralLine.color
+    icon.setContentHuggingPriority(.required, for: .horizontal)
+    
+    stack.spacing = 10
+    stack.addArrangedSubview(icon)
+    stack.addArrangedSubview(title.pinning(at: .left(0)))
+    stack.addArrangedSubview(accessory.pinning(at: .top(10)))
+    
+    addSubview(stack)
+    addSubview(separator)
+    
+    stack.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(16)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview().offset(-20)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    public func setup(
-        title: String,
-        icon: UIImage,
-        style: RowButtonStyle = .clean,
-        separator: Bool = true
-    ) {
-        self.icon.image = icon
-        self.title.text = title
-        self.title.textColor = style.color
-        self.accessory.image = style.accessory
-
-        guard separator == true else {
-            self.separator.removeFromSuperview()
-            return
-        }
+    
+    separator.snp.makeConstraints {
+      $0.height.equalTo(1)
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+    }
+    
+    subviews.forEach { $0.isUserInteractionEnabled = false }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  public func setup(
+    title: String,
+    icon: UIImage,
+    style: RowButtonStyle = .clean,
+    separator: Bool = true
+  ) {
+    self.icon.image = icon
+    self.title.text = title
+    self.title.textColor = style.color
+    self.accessory.image = style.accessory
+    
+    guard separator == true else {
+      self.separator.removeFromSuperview()
+      return
     }
+  }
 }
diff --git a/Sources/Shared/Views/RowSwitchableButton.swift b/Sources/Shared/Views/RowSwitchableButton.swift
index 38136c3ef7f656e8df8907ef6b5a23d461b1adee..175d93878e7b372c907267764180879177768c39 100644
--- a/Sources/Shared/Views/RowSwitchableButton.swift
+++ b/Sources/Shared/Views/RowSwitchableButton.swift
@@ -1,88 +1,89 @@
 import UIKit
+import AppResources
 
 public enum RowSwitchableButtonState {
-    case disclosure
-    case switcher(Bool)
+  case disclosure
+  case switcher(Bool)
 }
 
 public final class RowSwitchableButton: UIControl {
-    public let title = UILabel()
-    public let icon = UIImageView()
-    public let separator = UIView()
-
-    public let switcher = UISwitch()
-    public let disclosureIcon = UIImageView()
-
-    public init() {
-        super.init(frame: .zero)
-
-        icon.contentMode = .center
-        title.font = Fonts.Mulish.semiBold.font(size: 14.0)
-        separator.backgroundColor = Asset.neutralLine.color
-        title.textColor = Asset.neutralActive.color
-        disclosureIcon.image = Asset.settingsDisclosure.image
-        switcher.onTintColor = Asset.brandLight.color
-
-        addSubview(icon)
-        addSubview(title)
-        addSubview(disclosureIcon)
-        addSubview(switcher)
-        addSubview(separator)
-
-        icon.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(20)
-            make.left.equalToSuperview().offset(36)
-            make.bottom.equalToSuperview().offset(-20)
-        }
-
-        title.snp.makeConstraints { make in
-            make.left.equalTo(icon.snp.right).offset(25)
-            make.centerY.equalTo(icon)
-        }
-
-        disclosureIcon.snp.makeConstraints { make in
-            make.centerY.equalTo(icon)
-            make.right.equalToSuperview().offset(-48)
-        }
-
-        switcher.snp.makeConstraints { make in
-            make.right.equalToSuperview().offset(-25)
-            make.centerY.equalTo(icon)
-        }
-
-        separator.snp.makeConstraints { make in
-            make.height.equalTo(1)
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-            make.bottom.equalToSuperview()
-        }
+  public let title = UILabel()
+  public let icon = UIImageView()
+  public let separator = UIView()
+  
+  public let switcher = UISwitch()
+  public let disclosureIcon = UIImageView()
+  
+  public init() {
+    super.init(frame: .zero)
+    
+    icon.contentMode = .center
+    title.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    separator.backgroundColor = Asset.neutralLine.color
+    title.textColor = Asset.neutralActive.color
+    disclosureIcon.image = Asset.settingsDisclosure.image
+    switcher.onTintColor = Asset.brandLight.color
+    
+    addSubview(icon)
+    addSubview(title)
+    addSubview(disclosureIcon)
+    addSubview(switcher)
+    addSubview(separator)
+    
+    icon.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(20)
+      $0.left.equalToSuperview().offset(36)
+      $0.bottom.equalToSuperview().offset(-20)
     }
-
-    public required init?(coder: NSCoder) { nil }
-
-    public func setup(
-        title: String,
-        icon: UIImage,
-        state: RowSwitchableButtonState = .disclosure,
-        separator: Bool = true
-    ) {
-        self.icon.image = icon
-        self.title.text = title
-
-        switch state {
-        case .disclosure:
-            switcher.isHidden = true
-            disclosureIcon.isHidden = false
-
-        case .switcher(let bool):
-            switcher.isOn = bool
-            switcher.isHidden = false
-            disclosureIcon.isHidden = true
-        }
-
-        guard separator == true else {
-            self.separator.removeFromSuperview()
-            return
-        }
+    
+    title.snp.makeConstraints {
+      $0.left.equalTo(icon.snp.right).offset(25)
+      $0.centerY.equalTo(icon)
+    }
+    
+    disclosureIcon.snp.makeConstraints {
+      $0.centerY.equalTo(icon)
+      $0.right.equalToSuperview().offset(-48)
+    }
+    
+    switcher.snp.makeConstraints {
+      $0.right.equalToSuperview().offset(-25)
+      $0.centerY.equalTo(icon)
+    }
+    
+    separator.snp.makeConstraints {
+      $0.height.equalTo(1)
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
+      $0.bottom.equalToSuperview()
+    }
+  }
+  
+  public required init?(coder: NSCoder) { nil }
+  
+  public func setup(
+    title: String,
+    icon: UIImage,
+    state: RowSwitchableButtonState = .disclosure,
+    separator: Bool = true
+  ) {
+    self.icon.image = icon
+    self.title.text = title
+    
+    switch state {
+    case .disclosure:
+      switcher.isHidden = true
+      disclosureIcon.isHidden = false
+      
+    case .switcher(let bool):
+      switcher.isOn = bool
+      switcher.isHidden = false
+      disclosureIcon.isHidden = true
+    }
+    
+    guard separator == true else {
+      self.separator.removeFromSuperview()
+      return
     }
+  }
 }
diff --git a/Sources/Shared/Views/SearchComponent.swift b/Sources/Shared/Views/SearchComponent.swift
index 2edd280f23bb8ee82fb79b0003eb9eebcbee7359..5fb6fe2ad99153b117a9115fc5ad38fc9858eeb1 100644
--- a/Sources/Shared/Views/SearchComponent.swift
+++ b/Sources/Shared/Views/SearchComponent.swift
@@ -1,185 +1,186 @@
 import UIKit
 import Combine
+import AppResources
 
 public final class SearchComponent: UIView {
-    let rightButton = UIButton()
-    let leftImageView = UIImageView()
-    let containerView = UIView()
-    let inputField = UITextField()
-
-    public var rightPublisher: AnyPublisher<Void, Never> {
-        rightSubject.eraseToAnyPublisher()
-    }
-
-    public var textPublisher: AnyPublisher<String, Never> {
-        textSubject.eraseToAnyPublisher()
-    }
-
-    public var returnPublisher: AnyPublisher<Void, Never> {
-        returnSubject.eraseToAnyPublisher()
-    }
-
-    private var rightImage = Asset.sharedScan.image {
-        didSet {
-            rightButton.setImage(rightImage, for: .normal)
-        }
-    }
-
-    public var isEditingPublisher: AnyPublisher<Bool, Never> {
-        isEditingSubject.eraseToAnyPublisher()
-    }
-
-    private var cancellables = Set<AnyCancellable>()
-    private let rightSubject = PassthroughSubject<Void, Never>()
-    private let textSubject = PassthroughSubject<String, Never>()
-    private let returnSubject = PassthroughSubject<Void, Never>()
-    private let isEditingSubject = CurrentValueSubject<Bool, Never>(false)
-
-    public init() {
-        super.init(frame: .zero)
-
-        containerView.layer.cornerRadius = 25
-        containerView.backgroundColor = Asset.neutralSecondary.color
-
-        leftImageView.image = Asset.lens.image
-        leftImageView.contentMode = .center
-        leftImageView.tintColor = Asset.neutralDisabled.color
-
-        rightButton.tintColor = Asset.neutralBody.color
-        rightButton.setImage(rightImage, for: .normal)
-        rightButton.setContentHuggingPriority(.required, for: .horizontal)
-        rightButton.setContentCompressionResistancePriority(.required, for: .horizontal)
-
-        inputField.delegate = self
-        inputField.autocapitalizationType = .none
-        inputField.textColor = Asset.neutralActive.color
-        inputField.font = Fonts.Mulish.regular.font(size: 16.0)
-
-        let attrPlaceholder
-        = NSAttributedString(
-            string: Localized.Shared.Search.placeholder,
-            attributes: [
-                .font: Fonts.Mulish.regular.font(size: 14.0) as Any,
-                .foregroundColor: Asset.neutralWeak.color
-            ])
-
-        inputField.attributedPlaceholder = attrPlaceholder
-
-        inputField.textPublisher
-            .sink { [weak textSubject] in textSubject?.send($0) }
-            .store(in: &cancellables)
-
-        rightButton.publisher(for: .touchUpInside)
-            .sink { [weak rightSubject, self] in
-                if isEditingSubject.value == true {
-                    abortEditing()
-                } else {
-                    rightSubject?.send()
-                }
-            }.store(in: &cancellables)
-
-        addSubview(containerView)
-        containerView.addSubview(inputField)
-        containerView.addSubview(leftImageView)
-        containerView.addSubview(rightButton)
-
-        setupConstraints()
+  let rightButton = UIButton()
+  let leftImageView = UIImageView()
+  let containerView = UIView()
+  let inputField = UITextField()
+  
+  public var rightPublisher: AnyPublisher<Void, Never> {
+    rightSubject.eraseToAnyPublisher()
+  }
+  
+  public var textPublisher: AnyPublisher<String, Never> {
+    textSubject.eraseToAnyPublisher()
+  }
+  
+  public var returnPublisher: AnyPublisher<Void, Never> {
+    returnSubject.eraseToAnyPublisher()
+  }
+  
+  private var rightImage = Asset.sharedScan.image {
+    didSet {
+      rightButton.setImage(rightImage, for: .normal)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    public func set(
-        placeholder: String? = nil,
-        imageAtRight: UIImage? = nil,
-        inputAccessibility: String? = nil,
-        rightAccessibility: String? = nil
-    ) {
-        inputField.accessibilityIdentifier = inputAccessibility
-        rightButton.accessibilityIdentifier = rightAccessibility
-
-        if let placeholder = placeholder {
-            let attrPlaceholder
-                = NSAttributedString(
-                    string: placeholder,
-                    attributes: [
-                        .font: Fonts.Mulish.regular.font(size: 14.0) as Any,
-                        .foregroundColor: Asset.neutralWeak.color
-                    ])
-
-            inputField.attributedPlaceholder = attrPlaceholder
-        }
-
-        if let image = imageAtRight {
-            self.rightImage = image
+  }
+  
+  public var isEditingPublisher: AnyPublisher<Bool, Never> {
+    isEditingSubject.eraseToAnyPublisher()
+  }
+  
+  private var cancellables = Set<AnyCancellable>()
+  private let rightSubject = PassthroughSubject<Void, Never>()
+  private let textSubject = PassthroughSubject<String, Never>()
+  private let returnSubject = PassthroughSubject<Void, Never>()
+  private let isEditingSubject = CurrentValueSubject<Bool, Never>(false)
+  
+  public init() {
+    super.init(frame: .zero)
+    
+    containerView.layer.cornerRadius = 25
+    containerView.backgroundColor = Asset.neutralSecondary.color
+    
+    leftImageView.image = Asset.lens.image
+    leftImageView.contentMode = .center
+    leftImageView.tintColor = Asset.neutralDisabled.color
+    
+    rightButton.tintColor = Asset.neutralBody.color
+    rightButton.setImage(rightImage, for: .normal)
+    rightButton.setContentHuggingPriority(.required, for: .horizontal)
+    rightButton.setContentCompressionResistancePriority(.required, for: .horizontal)
+    
+    inputField.delegate = self
+    inputField.autocapitalizationType = .none
+    inputField.textColor = Asset.neutralActive.color
+    inputField.font = Fonts.Mulish.regular.font(size: 16.0)
+    
+    let attrPlaceholder
+    = NSAttributedString(
+      string: Localized.Shared.Search.placeholder,
+      attributes: [
+        .font: Fonts.Mulish.regular.font(size: 14.0) as Any,
+        .foregroundColor: Asset.neutralWeak.color
+      ])
+    
+    inputField.attributedPlaceholder = attrPlaceholder
+    
+    inputField.textPublisher
+      .sink { [weak textSubject] in textSubject?.send($0) }
+      .store(in: &cancellables)
+    
+    rightButton.publisher(for: .touchUpInside)
+      .sink { [weak rightSubject, self] in
+        if isEditingSubject.value == true {
+          abortEditing()
         } else {
-            rightButton.isHidden = true
+          rightSubject?.send()
         }
-    }
-
-    public func update(content: String) {
-        inputField.text = content
-    }
-
-    public func update(placeholder: String) {
-        inputField.attributedPlaceholder = NSAttributedString(
-            string: placeholder,
-            attributes: [
-                .font: Fonts.Mulish.regular.font(size: 14.0) as Any,
-                .foregroundColor: Asset.neutralWeak.color
+      }.store(in: &cancellables)
+    
+    addSubview(containerView)
+    containerView.addSubview(inputField)
+    containerView.addSubview(leftImageView)
+    containerView.addSubview(rightButton)
+    
+    setupConstraints()
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  public func set(
+    placeholder: String? = nil,
+    imageAtRight: UIImage? = nil,
+    inputAccessibility: String? = nil,
+    rightAccessibility: String? = nil
+  ) {
+    inputField.accessibilityIdentifier = inputAccessibility
+    rightButton.accessibilityIdentifier = rightAccessibility
+    
+    if let placeholder = placeholder {
+      let attrPlaceholder
+      = NSAttributedString(
+        string: placeholder,
+        attributes: [
+          .font: Fonts.Mulish.regular.font(size: 14.0) as Any,
+          .foregroundColor: Asset.neutralWeak.color
         ])
+      
+      inputField.attributedPlaceholder = attrPlaceholder
     }
-
-    public func abortEditing() {
-        inputField.text = nil
-        textSubject.send("")
-        inputField.endEditing(true)
-        isEditingSubject.send(false)
+    
+    if let image = imageAtRight {
+      self.rightImage = image
+    } else {
+      rightButton.isHidden = true
     }
-
-    private func setupConstraints() {
-        containerView.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-            $0.height.equalTo(50)
-        }
-
-        leftImageView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(10)
-            $0.left.equalToSuperview().offset(13)
-            $0.bottom.equalToSuperview().offset(-10)
-            $0.height.equalTo(leftImageView.snp.width)
-        }
-
-        inputField.snp.makeConstraints {
-            $0.top.bottom.equalToSuperview()
-            $0.left.equalTo(leftImageView.snp.right).offset(20)
-            $0.right.equalTo(rightButton.snp.left).offset(-32)
-        }
-
-        rightButton.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.right.equalToSuperview().offset(-13)
-            $0.bottom.equalToSuperview()
-        }
+  }
+  
+  public func update(content: String) {
+    inputField.text = content
+  }
+  
+  public func update(placeholder: String) {
+    inputField.attributedPlaceholder = NSAttributedString(
+      string: placeholder,
+      attributes: [
+        .font: Fonts.Mulish.regular.font(size: 14.0) as Any,
+        .foregroundColor: Asset.neutralWeak.color
+      ])
+  }
+  
+  public func abortEditing() {
+    inputField.text = nil
+    textSubject.send("")
+    inputField.endEditing(true)
+    isEditingSubject.send(false)
+  }
+  
+  private func setupConstraints() {
+    containerView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+      $0.height.equalTo(50)
     }
-
-    public func textFieldDidBeginEditing(_ textField: UITextField) {
-        rightButton.setImage(Asset.sharedCross.image, for: .normal)
-        isEditingSubject.send(true)
+    
+    leftImageView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(10)
+      $0.left.equalToSuperview().offset(13)
+      $0.bottom.equalToSuperview().offset(-10)
+      $0.height.equalTo(leftImageView.snp.width)
     }
-
-    public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
-        inputField.resignFirstResponder()
-        returnSubject.send(())
-        return true
+    
+    inputField.snp.makeConstraints {
+      $0.top.bottom.equalToSuperview()
+      $0.left.equalTo(leftImageView.snp.right).offset(20)
+      $0.right.equalTo(rightButton.snp.left).offset(-32)
     }
-
-    public func textFieldDidEndEditing(_ textField: UITextField) {
-        rightButton.setImage(rightImage, for: .normal)
-        isEditingSubject.send(false)
+    
+    rightButton.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.right.equalToSuperview().offset(-13)
+      $0.bottom.equalToSuperview()
     }
+  }
+  
+  public func textFieldDidBeginEditing(_ textField: UITextField) {
+    rightButton.setImage(Asset.sharedCross.image, for: .normal)
+    isEditingSubject.send(true)
+  }
+  
+  public func textFieldShouldReturn(_ textField: UITextField) -> Bool {
+    inputField.resignFirstResponder()
+    returnSubject.send(())
+    return true
+  }
+  
+  public func textFieldDidEndEditing(_ textField: UITextField) {
+    rightButton.setImage(rightImage, for: .normal)
+    isEditingSubject.send(false)
+  }
 }
 
 extension SearchComponent: UITextFieldDelegate {}
diff --git a/Sources/Shared/Views/SearchCountryComponent.swift b/Sources/Shared/Views/SearchCountryComponent.swift
index 186c58b95981ce45a799c93e27c8a53530b16cf4..5975925f63c1f8e25661b1bab138895d4eb139af 100644
--- a/Sources/Shared/Views/SearchCountryComponent.swift
+++ b/Sources/Shared/Views/SearchCountryComponent.swift
@@ -1,57 +1,58 @@
 import UIKit
+import AppResources
 
 public final class SearchCountryComponent: UIControl {
-    let flagLabel = UILabel()
-    let prefixLabel = UILabel()
-    let containerView = UIView()
-
-    public init() {
-        super.init(frame: .zero)
-
-        containerView.layer.cornerRadius = 25
-        containerView.backgroundColor = Asset.neutralSecondary.color
-
-        flagLabel.text = "🇺🇸"
-        prefixLabel.text = "+1"
-        prefixLabel.textColor = Asset.neutralDisabled.color
-        prefixLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
-
-        addSubview(containerView)
-        containerView.addSubview(flagLabel)
-        containerView.addSubview(prefixLabel)
-
-        containerView.isUserInteractionEnabled = false
-
-        setupConstraints()
-        flagLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
-        prefixLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
+  let flagLabel = UILabel()
+  let prefixLabel = UILabel()
+  let containerView = UIView()
+  
+  public init() {
+    super.init(frame: .zero)
+    
+    containerView.layer.cornerRadius = 25
+    containerView.backgroundColor = Asset.neutralSecondary.color
+    
+    flagLabel.text = "🇺🇸"
+    prefixLabel.text = "+1"
+    prefixLabel.textColor = Asset.neutralDisabled.color
+    prefixLabel.font = Fonts.Mulish.semiBold.font(size: 14.0)
+    
+    addSubview(containerView)
+    containerView.addSubview(flagLabel)
+    containerView.addSubview(prefixLabel)
+    
+    containerView.isUserInteractionEnabled = false
+    
+    setupConstraints()
+    flagLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
+    prefixLabel.setContentCompressionResistancePriority(.required, for: .horizontal)
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  public func setFlag(_ flag: String, prefix: String) {
+    flagLabel.text = flag
+    prefixLabel.text = prefix
+  }
+  
+  private func setupConstraints() {
+    containerView.snp.makeConstraints {
+      $0.top.equalToSuperview()
+      $0.left.equalToSuperview()
+      $0.right.equalToSuperview()
+      $0.bottom.equalToSuperview()
+      $0.height.equalTo(50)
     }
-
-    required init?(coder: NSCoder) { nil }
-
-    public func setFlag(_ flag: String, prefix: String) {
-        flagLabel.text = flag
-        prefixLabel.text = prefix
+    
+    flagLabel.snp.makeConstraints {
+      $0.left.equalToSuperview().offset(13)
+      $0.centerY.equalToSuperview()
     }
-
-    private func setupConstraints() {
-        containerView.snp.makeConstraints {
-            $0.top.equalToSuperview()
-            $0.left.equalToSuperview()
-            $0.right.equalToSuperview()
-            $0.bottom.equalToSuperview()
-            $0.height.equalTo(50)
-        }
-
-        flagLabel.snp.makeConstraints {
-            $0.left.equalToSuperview().offset(13)
-            $0.centerY.equalToSuperview()
-        }
-
-        prefixLabel.snp.makeConstraints {
-            $0.left.equalTo(flagLabel.snp.right).offset(10)
-            $0.right.equalToSuperview().offset(-13)
-            $0.centerY.equalToSuperview()
-        }
+    
+    prefixLabel.snp.makeConstraints {
+      $0.left.equalTo(flagLabel.snp.right).offset(10)
+      $0.right.equalToSuperview().offset(-13)
+      $0.centerY.equalToSuperview()
     }
+  }
 }
diff --git a/Sources/Shared/Views/SheetCardComponent.swift b/Sources/Shared/Views/SheetCardComponent.swift
index c5aa0b219e2fef53fc062cc777e7f58f3e45ccfc..6f60bb1688304323b59d439915c7ac87739b71a9 100644
--- a/Sources/Shared/Views/SheetCardComponent.swift
+++ b/Sources/Shared/Views/SheetCardComponent.swift
@@ -1,40 +1,30 @@
 import UIKit
+import AppResources
 
 public final class SheetCardComponent: UIView {
-    // MARK: UI
-
-    public let stack = UIStackView()
-
-    // MARK: Lifecycle
-
-    public init() {
-        super.init(frame: .zero)
-        setup()
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    // MARK: Public
-
-    public func set(buttons: [CapsuleButton]) {
-        buttons.forEach { stack.addArrangedSubview($0) }
-    }
-
-    // MARK: Private
-
-    private func setup() {
-        layer.cornerRadius = 24
-        backgroundColor = Asset.neutralSecondary.color
-
-        stack.spacing = 20
-        stack.axis = .vertical
-        addSubview(stack)
-
-        stack.snp.makeConstraints { make in
-            make.top.equalToSuperview().offset(24)
-            make.left.equalToSuperview().offset(24)
-            make.right.equalToSuperview().offset(-24)
-            make.bottom.equalToSuperview().offset(-24)
-        }
+  public let stackView = UIStackView()
+  
+  public init() {
+    super.init(frame: .zero)
+    
+    layer.cornerRadius = 24
+    backgroundColor = Asset.neutralSecondary.color
+    
+    stackView.spacing = 20
+    stackView.axis = .vertical
+    addSubview(stackView)
+    
+    stackView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(24)
+      $0.left.equalToSuperview().offset(24)
+      $0.right.equalToSuperview().offset(-24)
+      $0.bottom.equalToSuperview().offset(-24)
     }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  public func set(buttons: [CapsuleButton]) {
+    buttons.forEach { stackView.addArrangedSubview($0) }
+  }
 }
diff --git a/Sources/Shared/Views/SnackBar.swift b/Sources/Shared/Views/SnackBar.swift
index 9240ccf9537d12cf8377bcfb4e0d222442325f4c..4ca6961d64080ebc48b300cd73e4cc104d8e1f72 100644
--- a/Sources/Shared/Views/SnackBar.swift
+++ b/Sources/Shared/Views/SnackBar.swift
@@ -1,35 +1,36 @@
 import UIKit
+import AppResources
 
 public final class SnackBar: UIView {
-    private let titleLabel = UILabel()
-    private let imageView = UIImageView()
-    private let stackView = UIStackView()
-
-    public init() {
-        super.init(frame: .zero)
-
-        //alpha = 0.0
-        backgroundColor = Asset.brandPrimary.color
-
-        imageView.contentMode = .center
-        titleLabel.text = Localized.Shared.SnackBar.title
-        titleLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
-        titleLabel.textColor = Asset.neutralWhite.color
-        imageView.image = Asset.sharedWhiteExclamation.image
-
-        stackView.spacing = 14
-        stackView.addArrangedSubview(imageView)
-        stackView.addArrangedSubview(titleLabel)
-
-        addSubview(stackView)
-
-        stackView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(16)
-            $0.left.equalToSuperview().offset(20)
-            $0.right.equalToSuperview().offset(-20)
-            $0.bottom.equalToSuperview().offset(-16)
-        }
+  private let titleLabel = UILabel()
+  private let imageView = UIImageView()
+  private let stackView = UIStackView()
+  
+  public init() {
+    super.init(frame: .zero)
+    
+    //alpha = 0.0
+    backgroundColor = Asset.brandPrimary.color
+    
+    imageView.contentMode = .center
+    titleLabel.text = Localized.Shared.SnackBar.title
+    titleLabel.font = Fonts.Mulish.semiBold.font(size: 13.0)
+    titleLabel.textColor = Asset.neutralWhite.color
+    imageView.image = Asset.sharedWhiteExclamation.image
+    
+    stackView.spacing = 14
+    stackView.addArrangedSubview(imageView)
+    stackView.addArrangedSubview(titleLabel)
+    
+    addSubview(stackView)
+    
+    stackView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(16)
+      $0.left.equalToSuperview().offset(20)
+      $0.right.equalToSuperview().offset(-20)
+      $0.bottom.equalToSuperview().offset(-16)
     }
-
-    required init?(coder: NSCoder) { nil }
+  }
+  
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/Shared/Views/TextWithInfoView.swift b/Sources/Shared/Views/TextWithInfoView.swift
index 62133c1d6136e300762dcb718a16ca57a02009a0..0fbe08bed56850680bc3c1dcc72c7cd50ffbe0b1 100644
--- a/Sources/Shared/Views/TextWithInfoView.swift
+++ b/Sources/Shared/Views/TextWithInfoView.swift
@@ -1,63 +1,64 @@
 import UIKit
+import AppResources
 
 public final class TextWithInfoView: UIView {
-    private let textView = UITextView()
-    public private(set) var didTapInfo: (() -> Void)?
-
-    public init() {
-        super.init(frame: .zero)
-        textView.backgroundColor = .clear
-
-        textView.isEditable = false
-        textView.isScrollEnabled = false
-        textView.isSelectable = false
-
-        addSubview(textView)
-        textView.snp.makeConstraints { $0.edges.equalToSuperview() }
-    }
-
-    required init?(coder: NSCoder) { nil }
-
-    public func setup(
-        text: String,
-        attributes: [NSAttributedString.Key: Any],
-        didTapInfo: @escaping () -> Void
-    ) {
-        let mutable = NSMutableAttributedString(string: "\(text)  ", attributes: attributes)
-
-        let imageAttachment = NSTextAttachment()
-        imageAttachment.image = Asset.infoIcon.image
-
-        let imageString = NSAttributedString(attachment: imageAttachment)
-        mutable.append(imageString)
-        textView.attributedText = mutable
-
-        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tappedTextView(_:)))
-        textView.addGestureRecognizer(tapGesture)
-
-        self.didTapInfo = didTapInfo
-    }
-
-    @objc private func tappedTextView(_ sender: UITapGestureRecognizer) {
-        let textView = sender.view as! UITextView
-        let layoutManager = textView.layoutManager
-
-        var location = sender.location(in: textView)
-        location.x -= textView.textContainerInset.left;
-        location.y -= textView.textContainerInset.top;
-
-        let characterIndex = layoutManager.characterIndex(
-            for: location, in: textView.textContainer, fractionOfDistanceBetweenInsertionPoints: nil
-        )
-
-        if characterIndex < textView.textStorage.length {
-            let attributeValue = textView.attributedText.attribute(
-                NSAttributedString.Key.attachment, at: characterIndex, effectiveRange: nil
-            ) as? NSTextAttachment
-
-            if let _ = attributeValue {
-                didTapInfo?()
-            }
-        }
+  private let textView = UITextView()
+  public private(set) var didTapInfo: (() -> Void)?
+  
+  public init() {
+    super.init(frame: .zero)
+    textView.backgroundColor = .clear
+    
+    textView.isEditable = false
+    textView.isScrollEnabled = false
+    textView.isSelectable = false
+    
+    addSubview(textView)
+    textView.snp.makeConstraints { $0.edges.equalToSuperview() }
+  }
+  
+  required init?(coder: NSCoder) { nil }
+  
+  public func setup(
+    text: String,
+    attributes: [NSAttributedString.Key: Any],
+    didTapInfo: @escaping () -> Void
+  ) {
+    let mutable = NSMutableAttributedString(string: "\(text)  ", attributes: attributes)
+    
+    let imageAttachment = NSTextAttachment()
+    imageAttachment.image = Asset.infoIcon.image
+    
+    let imageString = NSAttributedString(attachment: imageAttachment)
+    mutable.append(imageString)
+    textView.attributedText = mutable
+    
+    let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tappedTextView(_:)))
+    textView.addGestureRecognizer(tapGesture)
+    
+    self.didTapInfo = didTapInfo
+  }
+  
+  @objc private func tappedTextView(_ sender: UITapGestureRecognizer) {
+    let textView = sender.view as! UITextView
+    let layoutManager = textView.layoutManager
+    
+    var location = sender.location(in: textView)
+    location.x -= textView.textContainerInset.left;
+    location.y -= textView.textContainerInset.top;
+    
+    let characterIndex = layoutManager.characterIndex(
+      for: location, in: textView.textContainer, fractionOfDistanceBetweenInsertionPoints: nil
+    )
+    
+    if characterIndex < textView.textStorage.length {
+      let attributeValue = textView.attributedText.attribute(
+        NSAttributedString.Key.attachment, at: characterIndex, effectiveRange: nil
+      ) as? NSTextAttachment
+      
+      if let _ = attributeValue {
+        didTapInfo?()
+      }
     }
+  }
 }
diff --git a/Sources/Shared/Views/UnselectableTextView.swift b/Sources/Shared/Views/UnselectableTextView.swift
index c664c022bb340d50ccf007940a9d97ca3ba740cc..5da1855737f7a36acde4c09ad8c51018b962a862 100644
--- a/Sources/Shared/Views/UnselectableTextView.swift
+++ b/Sources/Shared/Views/UnselectableTextView.swift
@@ -1,19 +1,19 @@
 import UIKit
 
 public final class UnselectableTextView: UITextView {
-    public override var selectedTextRange: UITextRange? {
-        get { return nil }
-        set {}
-    }
-
-    public override func point(
-        inside point: CGPoint,
-        with event: UIEvent?
-    ) -> Bool {
-        guard let pos = closestPosition(to: point) else { return false }
-        guard let range = tokenizer.rangeEnclosingPosition(pos, with: .character, inDirection: .layout(.left)) else { return false }
-
-        let startIndex = offset(from: beginningOfDocument, to: range.start)
-        return attributedText.attribute(.link, at: startIndex, effectiveRange: nil) != nil
-    }
+  public override var selectedTextRange: UITextRange? {
+    get { return nil }
+    set {}
+  }
+  
+  public override func point(
+    inside point: CGPoint,
+    with event: UIEvent?
+  ) -> Bool {
+    guard let pos = closestPosition(to: point) else { return false }
+    guard let range = tokenizer.rangeEnclosingPosition(pos, with: .character, inDirection: .layout(.left)) else { return false }
+    
+    let startIndex = offset(from: beginningOfDocument, to: range.start)
+    return attributedText.attribute(.link, at: startIndex, effectiveRange: nil) != nil
+  }
 }
diff --git a/Sources/StatusBarFeature/StatusBarDependency.swift b/Sources/StatusBarFeature/StatusBarDependency.swift
new file mode 100644
index 0000000000000000000000000000000000000000..2d04e3932df4074598f04beeb297baed54cbaf50
--- /dev/null
+++ b/Sources/StatusBarFeature/StatusBarDependency.swift
@@ -0,0 +1,13 @@
+import Dependencies
+
+private enum StatusBarDependencyKey: DependencyKey {
+  static let liveValue: StatusBarStyleManager = .live()
+  static let testValue: StatusBarStyleManager = .unimplemented
+}
+
+extension DependencyValues {
+  public var statusBar: StatusBarStyleManager {
+    get { self[StatusBarDependencyKey.self] }
+    set { self[StatusBarDependencyKey.self] = newValue }
+  }
+}
diff --git a/Sources/StatusBarFeature/StatusBarStyleFetch.swift b/Sources/StatusBarFeature/StatusBarStyleFetch.swift
new file mode 100644
index 0000000000000000000000000000000000000000..e57027ce0f9e9df7d87bf7e850ed06c2698d8a1a
--- /dev/null
+++ b/Sources/StatusBarFeature/StatusBarStyleFetch.swift
@@ -0,0 +1,16 @@
+import UIKit
+import XCTestDynamicOverlay
+
+public struct StatusBarStyleFetch {
+  public var run: () -> UIStatusBarStyle
+
+  public func callAsFunction() -> UIStatusBarStyle {
+    run()
+  }
+}
+
+extension StatusBarStyleFetch {
+  public static let unimplemented = StatusBarStyleFetch(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/StatusBarFeature/StatusBarStyleManager.swift b/Sources/StatusBarFeature/StatusBarStyleManager.swift
new file mode 100644
index 0000000000000000000000000000000000000000..3dbfe089beefd930fb13eafd35bea7fcd2734a3f
--- /dev/null
+++ b/Sources/StatusBarFeature/StatusBarStyleManager.swift
@@ -0,0 +1,39 @@
+import UIKit
+import Combine
+import XCTestDynamicOverlay
+
+public struct StatusBarStyleManager {
+  public var update: StatusBarStyleUpdate
+  public var current: StatusBarStyleFetch
+  public var observe: StatusBarStyleObserve
+}
+
+extension StatusBarStyleManager {
+  public static func live() -> StatusBarStyleManager {
+    class Context {
+      let styleSubject = CurrentValueSubject<UIStatusBarStyle, Never>(.lightContent)
+    }
+
+    let context = Context()
+
+    return .init(
+      update: .init {
+        context.styleSubject.send($0)
+      },
+      current: .init {
+        context.styleSubject.value
+      },
+      observe: .init {
+        context.styleSubject.eraseToAnyPublisher()
+      }
+    )
+  }
+}
+
+extension StatusBarStyleManager {
+  public static let unimplemented = StatusBarStyleManager(
+    update: .unimplemented,
+    current: .unimplemented,
+    observe: .unimplemented
+  )
+}
diff --git a/Sources/StatusBarFeature/StatusBarStyleObserve.swift b/Sources/StatusBarFeature/StatusBarStyleObserve.swift
new file mode 100644
index 0000000000000000000000000000000000000000..77c70223e0893b91a9df3b13365f76910adce573
--- /dev/null
+++ b/Sources/StatusBarFeature/StatusBarStyleObserve.swift
@@ -0,0 +1,17 @@
+import UIKit
+import Combine
+import XCTestDynamicOverlay
+
+public struct StatusBarStyleObserve {
+  public var run: () -> AnyPublisher<UIStatusBarStyle, Never>
+
+  public func callAsFunction() -> AnyPublisher<UIStatusBarStyle, Never> {
+    run()
+  }
+}
+
+extension StatusBarStyleObserve {
+  public static let unimplemented = StatusBarStyleObserve(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/StatusBarFeature/StatusBarStyleUpdate.swift b/Sources/StatusBarFeature/StatusBarStyleUpdate.swift
new file mode 100644
index 0000000000000000000000000000000000000000..95831faa90eb248a64de1e5e9b31b2d3d2820b8e
--- /dev/null
+++ b/Sources/StatusBarFeature/StatusBarStyleUpdate.swift
@@ -0,0 +1,16 @@
+import UIKit
+import XCTestDynamicOverlay
+
+public struct StatusBarStyleUpdate {
+  public var run: (UIStatusBarStyle) -> Void
+
+  public func callAsFunction(_ style: UIStatusBarStyle) -> Void {
+    run(style)
+  }
+}
+
+extension StatusBarStyleUpdate {
+  public static let unimplemented = StatusBarStyleUpdate(
+    run: XCTUnimplemented("\(Self.self)")
+  )
+}
diff --git a/Sources/TermsFeature/RadioButton.swift b/Sources/TermsFeature/RadioButton.swift
index 201aa3b9c19b2325a06168c4e9abfba4cecf0cd5..77b2a084b2a6726527416844cb2dd55e0486240b 100644
--- a/Sources/TermsFeature/RadioButton.swift
+++ b/Sources/TermsFeature/RadioButton.swift
@@ -1,53 +1,54 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RadioButton: UIControl {
-    private let filledView = UIView()
-    private let containerView = UIView()
+  private let filledView = UIView()
+  private let containerView = UIView()
 
-    init() {
-        super.init(frame: .zero)
+  init() {
+    super.init(frame: .zero)
 
-        containerView.layer.borderWidth = 1
-        containerView.layer.cornerRadius = 15
-        containerView.layer.masksToBounds = true
-        containerView.layer.borderColor = Asset.neutralWhite.color.cgColor
+    containerView.layer.borderWidth = 1
+    containerView.layer.cornerRadius = 15
+    containerView.layer.masksToBounds = true
+    containerView.layer.borderColor = Asset.neutralWhite.color.cgColor
 
-        filledView.isHidden = true
-        filledView.layer.cornerRadius = 10
-        filledView.layer.masksToBounds = true
-        filledView.backgroundColor = Asset.neutralWhite.color
+    filledView.isHidden = true
+    filledView.layer.cornerRadius = 10
+    filledView.layer.masksToBounds = true
+    filledView.backgroundColor = Asset.neutralWhite.color
 
-        containerView.isUserInteractionEnabled = false
-        filledView.isUserInteractionEnabled = false
+    containerView.isUserInteractionEnabled = false
+    filledView.isUserInteractionEnabled = false
 
-        addSubview(containerView)
-        containerView.addSubview(filledView)
+    addSubview(containerView)
+    containerView.addSubview(filledView)
 
-        setupConstraints()
-    }
+    setupConstraints()
+  }
+
+  required init?(coder: NSCoder) { nil }
 
-    required init?(coder: NSCoder) { nil }
+  func set(enabled: Bool) {
+    filledView.isHidden = !enabled
+  }
 
-    func set(enabled: Bool) {
-        filledView.isHidden = !enabled
+  private func setupConstraints() {
+    containerView.snp.makeConstraints {
+      $0.width.equalTo(30)
+      $0.height.equalTo(30)
+      $0.top.equalToSuperview().offset(5)
+      $0.left.equalToSuperview().offset(5)
+      $0.right.equalToSuperview().offset(-5)
+      $0.bottom.equalToSuperview().offset(-5)
     }
 
-    private func setupConstraints() {
-        containerView.snp.makeConstraints {
-            $0.width.equalTo(30)
-            $0.height.equalTo(30)
-            $0.top.equalToSuperview().offset(5)
-            $0.left.equalToSuperview().offset(5)
-            $0.right.equalToSuperview().offset(-5)
-            $0.bottom.equalToSuperview().offset(-5)
-        }
-
-        filledView.snp.makeConstraints {
-            $0.top.equalToSuperview().offset(5)
-            $0.left.equalToSuperview().offset(5)
-            $0.right.equalToSuperview().offset(-5)
-            $0.bottom.equalToSuperview().offset(-5)
-        }
+    filledView.snp.makeConstraints {
+      $0.top.equalToSuperview().offset(5)
+      $0.left.equalToSuperview().offset(5)
+      $0.right.equalToSuperview().offset(-5)
+      $0.bottom.equalToSuperview().offset(-5)
     }
+  }
 }
diff --git a/Sources/TermsFeature/RadioTextComponent.swift b/Sources/TermsFeature/RadioTextComponent.swift
index 8f6509f21562ebc8d3a0941cff1a5db53b997908..0d7906aea227f922387d4642c893e93d0ee9abf1 100644
--- a/Sources/TermsFeature/RadioTextComponent.swift
+++ b/Sources/TermsFeature/RadioTextComponent.swift
@@ -1,40 +1,37 @@
 import UIKit
 import Shared
+import AppResources
 
 final class RadioTextComponent: UIView {
-    let titleLabel = UILabel()
-    let radioButton = RadioButton()
+  let titleLabel = UILabel()
+  let radioButton = RadioButton()
 
-    var isEnabled: Bool = false {
-        didSet { radioButton.set(enabled: isEnabled) }
-    }
+  var isEnabled: Bool = false {
+    didSet { radioButton.set(enabled: isEnabled) }
+  }
 
-    init() {
-        super.init(frame: .zero)
+  init() {
+    super.init(frame: .zero)
 
-        titleLabel.numberOfLines = 0
-        titleLabel.textColor = Asset.neutralWhite.color
-        titleLabel.font = Fonts.Mulish.regular.font(size: 13.0)
+    titleLabel.numberOfLines = 0
+    titleLabel.textColor = Asset.neutralWhite.color
+    titleLabel.font = Fonts.Mulish.regular.font(size: 13.0)
 
-        addSubview(titleLabel)
-        addSubview(radioButton)
+    addSubview(titleLabel)
+    addSubview(radioButton)
 
-        setupConstraints()
+    titleLabel.snp.makeConstraints {
+      $0.left.equalTo(radioButton.snp.right).offset(7)
+      $0.centerY.equalTo(radioButton)
+      $0.right.equalToSuperview()
     }
 
-    required init?(coder: NSCoder) { nil }
-
-    private func setupConstraints() {
-        titleLabel.snp.makeConstraints {
-            $0.left.equalTo(radioButton.snp.right).offset(7)
-            $0.centerY.equalTo(radioButton)
-            $0.right.equalToSuperview()
-        }
-
-        radioButton.snp.makeConstraints {
-            $0.left.equalToSuperview()
-            $0.top.greaterThanOrEqualToSuperview()
-            $0.bottom.equalToSuperview()
-        }
+    radioButton.snp.makeConstraints {
+      $0.left.equalToSuperview()
+      $0.top.greaterThanOrEqualToSuperview()
+      $0.bottom.equalToSuperview()
     }
+  }
+
+  required init?(coder: NSCoder) { nil }
 }
diff --git a/Sources/TermsFeature/TermsConditionsController.swift b/Sources/TermsFeature/TermsConditionsController.swift
index 9485704fe85d1fe461dc22ccf6c513049368089d..23fd543b54b13ff0599436d5e4301677795cab37 100644
--- a/Sources/TermsFeature/TermsConditionsController.swift
+++ b/Sources/TermsFeature/TermsConditionsController.swift
@@ -5,6 +5,7 @@ import Shared
 import Combine
 import Defaults
 import Navigation
+import AppResources
 
 public final class TermsConditionsController: UIViewController {
   @Dependency var navigator: Navigator
@@ -61,9 +62,9 @@ public final class TermsConditionsController: UIViewController {
       .sink { [unowned self] in
         didAcceptTerms = true
         if username != nil {
-          navigator.perform(PresentChatList())
+          navigator.perform(PresentChatList(on: navigationController!))
         } else {
-          navigator.perform(PresentOnboardingUsername())
+          navigator.perform(PresentOnboardingUsername(on: navigationController!))
         }
       }.store(in: &cancellables)
 
diff --git a/Sources/TermsFeature/TermsConditionsView.swift b/Sources/TermsFeature/TermsConditionsView.swift
index 2f3ff8fa327956951be5299f32b6537d7ad4824d..e3dd19a9427f823ebd4d54700176a4deeebcf1f3 100644
--- a/Sources/TermsFeature/TermsConditionsView.swift
+++ b/Sources/TermsFeature/TermsConditionsView.swift
@@ -1,56 +1,57 @@
 import UIKit
 import Shared
+import AppResources
 
 final class TermsConditionsView: UIView {
-    let nextButton = CapsuleButton()
-    let logoImageView = UIImageView()
-    let showTermsButton = CapsuleButton()
-    let radioComponent = RadioTextComponent()
+  let nextButton = CapsuleButton()
+  let logoImageView = UIImageView()
+  let showTermsButton = CapsuleButton()
+  let radioComponent = RadioTextComponent()
 
-    init() {
-        super.init(frame: .zero)
-        backgroundColor = Asset.neutralWhite.color
+  init() {
+    super.init(frame: .zero)
+    backgroundColor = Asset.neutralWhite.color
 
-        logoImageView.contentMode = .center
-        logoImageView.image = Asset.onboardingLogoStart.image
-        radioComponent.titleLabel.text = Localized.Terms.radio
+    logoImageView.contentMode = .center
+    logoImageView.image = Asset.onboardingLogoStart.image
+    radioComponent.titleLabel.text = Localized.Terms.radio
 
-        nextButton.isEnabled = false
-        nextButton.set(style: .white, title: Localized.Terms.accept)
-        showTermsButton.set(style: .seeThroughWhite, title: Localized.Terms.show)
+    nextButton.isEnabled = false
+    nextButton.set(style: .white, title: Localized.Terms.accept)
+    showTermsButton.set(style: .seeThroughWhite, title: Localized.Terms.show)
 
-        addSubview(logoImageView)
-        addSubview(nextButton)
-        addSubview(radioComponent)
-        addSubview(showTermsButton)
+    addSubview(logoImageView)
+    addSubview(nextButton)
+    addSubview(radioComponent)
+    addSubview(showTermsButton)
 
-        setupConstraints()
+    setupConstraints()
+  }
+
+  required init?(coder: NSCoder) { nil }
+
+  private func setupConstraints() {
+    logoImageView.snp.makeConstraints {
+      $0.top.equalTo(safeAreaLayoutGuide).offset(30)
+      $0.centerX.equalToSuperview()
+    }
+
+    radioComponent.snp.makeConstraints {
+      $0.left.equalToSuperview().offset(40)
+      $0.right.equalToSuperview().offset(-40)
+      $0.bottom.equalTo(nextButton.snp.top).offset(-20)
+    }
+
+    nextButton.snp.makeConstraints {
+      $0.left.equalToSuperview().offset(40)
+      $0.right.equalToSuperview().offset(-40)
+      $0.bottom.equalTo(showTermsButton.snp.top).offset(-10)
     }
 
-    required init?(coder: NSCoder) { nil }
-
-    private func setupConstraints() {
-        logoImageView.snp.makeConstraints {
-            $0.top.equalTo(safeAreaLayoutGuide).offset(30)
-            $0.centerX.equalToSuperview()
-        }
-
-        radioComponent.snp.makeConstraints {
-            $0.left.equalToSuperview().offset(40)
-            $0.right.equalToSuperview().offset(-40)
-            $0.bottom.equalTo(nextButton.snp.top).offset(-20)
-        }
-
-        nextButton.snp.makeConstraints {
-            $0.left.equalToSuperview().offset(40)
-            $0.right.equalToSuperview().offset(-40)
-            $0.bottom.equalTo(showTermsButton.snp.top).offset(-10)
-        }
-
-        showTermsButton.snp.makeConstraints {
-            $0.left.equalToSuperview().offset(40)
-            $0.right.equalToSuperview().offset(-40)
-            $0.bottom.equalTo(safeAreaLayoutGuide).offset(-40)
-        }
+    showTermsButton.snp.makeConstraints {
+      $0.left.equalToSuperview().offset(40)
+      $0.right.equalToSuperview().offset(-40)
+      $0.bottom.equalTo(safeAreaLayoutGuide).offset(-40)
     }
+  }
 }
diff --git a/Sources/Voxophone/Voxophone.swift b/Sources/Voxophone/Voxophone.swift
deleted file mode 100644
index 578a46a85df147350013fc526a5d8cd63c0718dd..0000000000000000000000000000000000000000
--- a/Sources/Voxophone/Voxophone.swift
+++ /dev/null
@@ -1,229 +0,0 @@
-import AVFoundation
-import Combine
-import Shared
-
-public final class Voxophone: NSObject, AVAudioRecorderDelegate, AVAudioPlayerDelegate {
-    public enum State: Equatable {
-        case empty(isLoudspeaker: Bool)
-        case idle(URL, duration: TimeInterval, isLoudspeaker: Bool)
-        case recording(URL, time: TimeInterval, isLoudspeaker: Bool)
-        case playing(URL, duration: TimeInterval, time: TimeInterval, isLoudspeaker: Bool)
-    }
-
-    public override init() {
-        super.init()
-    }
-
-    deinit {
-        destroyPlayer()
-        destroyRecorder()
-        stopTimer()
-    }
-
-    @Published public private(set) var state: State = .empty(isLoudspeaker: false)
-
-    private let session: AVAudioSession = .sharedInstance()
-    private var recorder: AVAudioRecorder?
-    private var player: AVAudioPlayer?
-    private var timer: Timer?
-
-    public func reset() {
-        destroyPlayer()
-        destroyRecorder()
-        state = .empty(isLoudspeaker: false)
-    }
-
-    public func toggleLoudspeaker() {
-        state.isLoudspeaker.toggle()
-        setupSessionCategory()
-    }
-
-    public func load(_ url: URL) {
-        destroyPlayer()
-        destroyRecorder()
-        let player = setupPlayer(url: url)
-        state = .idle(url, duration: player.duration, isLoudspeaker: state.isLoudspeaker)
-    }
-
-    public func play() {
-        guard let player = player, let url = player.url else { return }
-        destroyRecorder()
-        state = .playing(url, duration: player.duration, time: player.currentTime, isLoudspeaker: state.isLoudspeaker)
-        startPlayback()
-    }
-
-    public func record() {
-        let url = URL(fileURLWithPath: FileManager.xxPath + "/recording_\(Date.asTimestamp).m4a")
-
-        destroyPlayer()
-        destroyRecorder()
-        let recorder = setupRecorder(url: url)
-        state = .recording(url, time: recorder.currentTime, isLoudspeaker: state.isLoudspeaker)
-        startRecording()
-    }
-
-    public func stop() {
-        switch state {
-        case .empty, .idle:
-            return
-
-        case .recording:
-            finishRecording()
-
-        case .playing(let url, let duration, _, let isLoudspeaker):
-            stopPlayback()
-            state = .idle(url, duration: duration, isLoudspeaker: isLoudspeaker)
-        }
-    }
-
-    // MARK: - Player
-
-    private func setupPlayer(url: URL) -> AVAudioPlayer {
-        let player = try! AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.m4a.rawValue)
-        self.player = player
-        return player
-    }
-
-    private func setupSessionCategory() {
-        switch state {
-        case .playing(_, _, _, let isLoud):
-            if isLoud, session.category != .playback {
-                try! session.setCategory(.playback, options: .duckOthers)
-            }
-
-            if !isLoud, session.category != .playAndRecord {
-                try! session.setCategory(.playAndRecord, options: .duckOthers)
-            }
-        case .recording(_, _, _):
-            if session.category != .playAndRecord {
-                try! session.setCategory(.playAndRecord, options: .duckOthers)
-            }
-        default:
-            break
-        }
-    }
-
-    private func startPlayback() {
-        guard let player = player else { return }
-        try! session.setActive(true)
-        setupSessionCategory()
-        player.delegate = self
-        player.prepareToPlay()
-        player.play()
-        startTimer()
-    }
-
-    private func stopPlayback() {
-        guard let player = player else { return }
-        player.stop()
-    }
-
-    private func destroyPlayer() {
-        player?.delegate = nil
-        player?.stop()
-        player = nil
-    }
-
-    // MARK: - Recorder
-
-    private func setupRecorder(url: URL) -> AVAudioRecorder {
-        let recorder = try! AVAudioRecorder(url: url, settings: [
-            AVFormatIDKey: kAudioFormatMPEG4AAC,
-            AVSampleRateKey: 12000,
-            AVNumberOfChannelsKey: 1
-        ])
-        self.recorder = recorder
-        return recorder
-    }
-
-    private func startRecording() {
-        guard let recorder = recorder else { return }
-        try! session.setActive(true)
-        setupSessionCategory()
-        recorder.delegate = self
-        recorder.record()
-        startTimer()
-    }
-
-    private func finishRecording() {
-        guard let recorder = recorder else { return }
-        recorder.stop()
-    }
-
-    private func destroyRecorder() {
-        recorder?.delegate = nil
-        recorder?.stop()
-        recorder = nil
-    }
-
-    // MARK: - Timer
-
-    private func startTimer() {
-        stopTimer()
-        timer = Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { _ in
-            self.timerTick()
-        }
-    }
-
-    private func timerTick() {
-        switch state {
-        case .empty, .idle:
-            stopTimer()
-
-        case .recording(_, _, let isLoud):
-            guard let recorder = recorder else { return }
-            state = .recording(recorder.url, time: recorder.currentTime, isLoudspeaker: isLoud)
-
-        case .playing(_, _, _, let isLoud):
-            guard let player = player, let url = player.url else { return }
-            state = .playing(url, duration: player.duration, time: player.currentTime, isLoudspeaker: isLoud)
-        }
-    }
-
-    private func stopTimer() {
-        timer?.invalidate()
-        timer = nil
-    }
-
-    // MARK: - AVAudioRecorderDelegate
-
-    public func audioRecorderDidFinishRecording(_ recorder: AVAudioRecorder, successfully flag: Bool) {
-        guard flag else {
-            state = .empty(isLoudspeaker: state.isLoudspeaker)
-            return
-        }
-        load(recorder.url)
-    }
-
-    // MARK: - AVAudioPlayerDelegate
-
-    public func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
-        guard flag, let url = player.url else {
-            state = .empty(isLoudspeaker: state.isLoudspeaker)
-            return
-        }
-        load(url)
-    }
-}
-
-public extension Voxophone.State {
-    var isLoudspeaker: Bool {
-        get {
-            switch self {
-            case .playing(_, _, _, let isLoud), .idle(_, _, let isLoud), .empty(let isLoud), .recording(_, _, let isLoud):
-                return isLoud
-            }
-        } set {
-            switch self {
-            case .empty(_):
-                self = .empty(isLoudspeaker: newValue)
-            case let .idle(url, duration, _):
-                self = .idle(url, duration: duration, isLoudspeaker: newValue)
-            case let .playing(url, duration, time, _):
-                self = .playing(url, duration: duration, time: time, isLoudspeaker: newValue)
-            case let .recording(url, time, _):
-                self = .recording(url, time: time, isLoudspeaker: newValue)
-            }
-        }
-    }
-}
diff --git a/Sources/XXLogger/Logger.swift b/Sources/XXLogger/Logger.swift
deleted file mode 100644
index 805887aabfde4b6a27c3fdb58fc14114a4a5bbb3..0000000000000000000000000000000000000000
--- a/Sources/XXLogger/Logger.swift
+++ /dev/null
@@ -1,103 +0,0 @@
-import Foundation
-import SwiftyBeaver
-
-public typealias LogClosure = (Any, String, String, Int) -> Void
-
-public struct XXLogger {
-    var logInfo: LogClosure
-    var logDebug: LogClosure
-    var logError: LogClosure
-    var logWarning: LogClosure
-    var logVerbose: LogClosure
-
-    public init(
-        info: @escaping LogClosure,
-        debug: @escaping LogClosure,
-        error: @escaping LogClosure,
-        warning: @escaping LogClosure,
-        verbose: @escaping LogClosure
-    ) {
-        self.logInfo = info
-        self.logDebug = debug
-        self.logError = error
-        self.logWarning = warning
-        self.logVerbose = verbose
-    }
-
-    public func info(_ contents: Any, file: String = #file, function: String = #function, line: Int = #line) {
-        logInfo(contents, file, function, line)
-    }
-
-    public func debug(_ contents: Any, file: String = #file, function: String = #function, line: Int = #line) {
-        logDebug(contents, file, function, line)
-    }
-
-    public func error(_ contents: Any, file: String = #file, function: String = #function, line: Int = #line) {
-        logError(contents, file, function, line)
-    }
-
-    public func warning(_ contents: Any, file: String = #file, function: String = #function, line: Int = #line) {
-        logWarning(contents, file, function, line)
-    }
-
-    public func verbose(_ contents: Any, file: String = #file, function: String = #function, line: Int = #line) {
-        logVerbose(contents, file, function, line)
-    }
-}
-
-public extension XXLogger {
-    static func stop() {
-        let log = SwiftyBeaver.self
-        log.removeAllDestinations()
-
-        let url = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask)[0]
-            .appendingPathComponent("swiftybeaver.log")
-
-        try? "".write(to: url, atomically: false, encoding: .utf8)
-    }
-
-    static func start() {
-        let log = SwiftyBeaver.self
-
-        let console = ConsoleDestination()
-        console.levelString.error = "🟥"
-        console.levelString.info = "✅"
-        console.levelString.warning = "[BACKEND]"
-        console.levelString.verbose = "[VERBOSE]"
-        console.format = "$DHH:mm:ss$d $L $N.$F:$l $M"
-
-        let file = FileDestination()
-        file.levelString.error = "🟥"
-        file.levelString.info = "✅"
-        file.levelString.warning = "[BACKEND]"
-        file.minLevel = .debug
-        file.format = "$DHH:mm:ss$d $L $N.$F:$l $M"
-
-        log.addDestination(console)
-        log.addDestination(file)
-    }
-
-    static func live() -> Self {
-        let log = SwiftyBeaver.self
-
-        return .init {
-            log.info($0, $1, $2, line: $3)
-        } debug: {
-            log.debug($0, $1, $2, line: $3)
-        } error: {
-            log.error($0, $1, $2, line: $3)
-        } warning: {
-            log.warning($0, $1, $2, line: $3)
-        } verbose: {
-            log.verbose($0, $1, $2, line: $3)
-        }
-    }
-
-    static let noop: Self = .init(
-        info: { _,_,_,_ in },
-        debug: { _,_,_,_ in },
-        error: { _,_,_,_ in },
-        warning: { _,_,_,_ in },
-        verbose: { _,_,_,_ in }
-    )
-}
diff --git a/Tests/AppTests/General/DateTests.swift b/Tests/AppFeatureTests/General/DateTests.swift
similarity index 100%
rename from Tests/AppTests/General/DateTests.swift
rename to Tests/AppFeatureTests/General/DateTests.swift
diff --git a/Tests/AppTests/General/InvitationTests.swift b/Tests/AppFeatureTests/General/InvitationTests.swift
similarity index 100%
rename from Tests/AppTests/General/InvitationTests.swift
rename to Tests/AppFeatureTests/General/InvitationTests.swift
diff --git a/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved b/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
index 6006a39d34ebab1c7bbe76132c3f428df725ee71..fa732be43c432b37cc0f8bd9f88a1e9c9d2f4592 100644
--- a/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
+++ b/client-ios.xcworkspace/xcshareddata/swiftpm/Package.resolved
@@ -293,8 +293,17 @@
       "kind" : "remoteSourceControl",
       "location" : "https://github.com/pointfreeco/swift-case-paths",
       "state" : {
-        "revision" : "7346701ea29da0a85d4403cf3d7a589a58ae3dee",
-        "version" : "0.9.2"
+        "revision" : "bb436421f57269fbcfe7360735985321585a86e5",
+        "version" : "0.10.1"
+      }
+    },
+    {
+      "identity" : "swift-clocks",
+      "kind" : "remoteSourceControl",
+      "location" : "https://github.com/pointfreeco/swift-clocks",
+      "state" : {
+        "revision" : "20b25ca0dd88ebfb9111ec937814ddc5a8880172",
+        "version" : "0.2.0"
       }
     },
     {
@@ -311,8 +320,8 @@
       "kind" : "remoteSourceControl",
       "location" : "https://github.com/pointfreeco/swift-composable-architecture.git",
       "state" : {
-        "revision" : "9ea8c763061287052a68d5e6723fed45e898b7d9",
-        "version" : "0.40.2"
+        "revision" : "1fcd53fc875bade47d850749ea53c324f74fd64d",
+        "version" : "0.45.0"
       }
     },
     {
@@ -360,15 +369,6 @@
         "version" : "0.8.1"
       }
     },
-    {
-      "identity" : "swiftybeaver",
-      "kind" : "remoteSourceControl",
-      "location" : "https://github.com/SwiftyBeaver/SwiftyBeaver.git",
-      "state" : {
-        "revision" : "12b5acf96d98f91d50de447369bd18df74600f1a",
-        "version" : "1.9.6"
-      }
-    },
     {
       "identity" : "swiftydropbox",
       "kind" : "remoteSourceControl",
@@ -386,6 +386,15 @@
         "revision" : "16e6409ee82e1b81390bdffbf217b9c08ab32784",
         "version" : "0.5.0"
       }
+    },
+    {
+      "identity" : "xxm-di",
+      "kind" : "remoteSourceControl",
+      "location" : "https://git.xx.network/elixxir/xxm-di",
+      "state" : {
+        "revision" : "43b1e12c32109f1753fcc62e5b0b21e479ee27e3",
+        "version" : "1.0.0"
+      }
     }
   ],
   "version" : 2