diff --git a/App/NotificationExtension/NotificationService.swift b/App/NotificationExtension/NotificationService.swift
index 495958b9ab1e9b26981c9996f088b17b5fa1053d..4444b66a596ebbc62040280bd2c675f2c9744515 100644
--- a/App/NotificationExtension/NotificationService.swift
+++ b/App/NotificationExtension/NotificationService.swift
@@ -2,12 +2,12 @@ import PushFeature
 import UserNotifications
 
 final class NotificationService: UNNotificationServiceExtension {
-    private let pushHandler = PushHandler()
+  private let pushHandler = PushHandler()
 
-    override func didReceive(
-        _ request: UNNotificationRequest,
-        withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
-    ) {
-        pushHandler.handlePush(request, contentHandler)
-    }
+  override func didReceive(
+    _ request: UNNotificationRequest,
+    withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
+  ) {
+    pushHandler.handlePush(request, contentHandler)
+  }
 }
diff --git a/App/client-ios.xcodeproj/project.pbxproj b/App/client-ios.xcodeproj/project.pbxproj
index 87ff542bdc1cb222888508d0c6737164e264baf4..b173e088056b9a96da598954f6a23b4d0024d8d0 100644
--- a/App/client-ios.xcodeproj/project.pbxproj
+++ b/App/client-ios.xcodeproj/project.pbxproj
@@ -448,7 +448,7 @@
 				CODE_SIGN_ENTITLEMENTS = "client-ios/Resources/client-ios.entitlements";
 				CODE_SIGN_IDENTITY = "Apple Development";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 289;
+				CURRENT_PROJECT_VERSION = 292;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEVELOPMENT_TEAM = S6JDM2WW29;
 				ENABLE_BITCODE = NO;
@@ -487,7 +487,7 @@
 				CODE_SIGN_ENTITLEMENTS = "client-ios/Resources/client-ios.entitlements";
 				CODE_SIGN_IDENTITY = "Apple Development";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 289;
+				CURRENT_PROJECT_VERSION = 292;
 				DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
 				DEVELOPMENT_TEAM = S6JDM2WW29;
 				ENABLE_BITCODE = NO;
@@ -522,7 +522,7 @@
 				CODE_SIGN_ENTITLEMENTS = NotificationExtension/NotificationExtension.entitlements;
 				CODE_SIGN_IDENTITY = "Apple Development";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 289;
+				CURRENT_PROJECT_VERSION = 292;
 				DEVELOPMENT_TEAM = S6JDM2WW29;
 				ENABLE_BITCODE = NO;
 				FRAMEWORK_SEARCH_PATHS = (
@@ -553,7 +553,7 @@
 				CODE_SIGN_ENTITLEMENTS = NotificationExtension/NotificationExtension.entitlements;
 				CODE_SIGN_IDENTITY = "Apple Development";
 				CODE_SIGN_STYLE = Automatic;
-				CURRENT_PROJECT_VERSION = 289;
+				CURRENT_PROJECT_VERSION = 292;
 				DEVELOPMENT_TEAM = S6JDM2WW29;
 				ENABLE_BITCODE = NO;
 				FRAMEWORK_SEARCH_PATHS = (
diff --git a/Sources/App/AppDelegate.swift b/Sources/App/AppDelegate.swift
index 25a3041a36827376d2fc3dc0a60e41bd82522b48..ec35ad28c85991a2255727da59a5dcaee95429dc 100644
--- a/Sources/App/AppDelegate.swift
+++ b/Sources/App/AppDelegate.swift
@@ -21,6 +21,7 @@ import CloudFilesDropbox
 
 public class AppDelegate: UIResponder, UIApplicationDelegate {
   @Dependency var navigator: Navigator
+  @Dependency var pushRouter: PushRouter
   @Dependency var pushHandler: PushHandling
   @Dependency var crashReporter: CrashReporter
 
@@ -52,6 +53,10 @@ public class AppDelegate: UIResponder, UIApplicationDelegate {
     window?.makeKeyAndVisible()
 
     DependencyRegistrator.registerNavigators(navController)
+
+    DependencyInjection.Container.shared.register(
+      PushRouter.live(navigationController: navController)
+    )
     return true
   }
 
@@ -86,12 +91,10 @@ public class AppDelegate: UIResponder, UIApplicationDelegate {
         guard UIApplication.shared.backgroundTimeRemaining > 9 else {
           if !self.forceFailedPendingMessages {
             self.forceFailedPendingMessages = true
-
             let query = Message.Query(status: [.sending])
             let assignment = Message.Assignments(status: .sendingFailed)
             _ = try? database.bulkUpdateMessages(query, assignment)
           }
-
           return
         }
       })
@@ -166,7 +169,7 @@ extension AppDelegate: UNUserNotificationCenterDelegate {
     withCompletionHandler completionHandler: @escaping () -> Void
   ) {
     let userInfo = response.notification.request.content.userInfo
-    //pushHandler.handleAction(pushRouter, userInfo, completionHandler)
+    pushHandler.handleAction(pushRouter, userInfo, completionHandler)
   }
 
   public func application(
diff --git a/Sources/App/DependencyRegistrator.swift b/Sources/App/DependencyRegistrator.swift
index 795e5d7d5b106e3f2de2061d9b4a241c046ad253..dfa6014673d4c9c4a9054092e7e252478ab0471e 100644
--- a/Sources/App/DependencyRegistrator.swift
+++ b/Sources/App/DependencyRegistrator.swift
@@ -243,38 +243,13 @@ struct DependencyRegistrator {
     ) as Navigator)
   }
 
-  //    container.register(
-  //      ProfileCoordinator(
-  //        imagePickerFactory: UIImagePickerController.init,
-  //        permissionFactory: RequestPermissionController.init,
-  //        countriesFactory: CountryListController.init(_:)
-  //        //codeFactory: ProfileCodeController.init(_:_:)
-  //      ) as ProfileCoordinating)
-
-  //    container.register(
-  //      SearchCoordinator(
-  //        contactsFactory: ContactListController.init,
-  //        requestsFactory: RequestsContainerController.init,
-  //        contactFactory: ContactController.init(_:),
-  //        countriesFactory: CountryListController.init(_:)
-  //      ) as SearchCoordinating)
-
-  //    container.register(
-  //      ContactListCoordinator(
-  //        scanFactory: ScanContainerController.init,
-  //        searchFactory: SearchContainerController.init,
-  //        newGroupFactory: CreateGroupController.init,
-  //        requestsFactory: RequestsContainerController.init,
-  //        contactFactory: ContactController.init(_:),
-  //        singleChatFactory: SingleChatController.init(_:),
-  //        groupChatFactory: GroupChatController.init(_:),
-  //        sideMenuFactory: MenuController.init(_:_:),
-  //        groupDrawerFactory: CreateDrawerController.init(_:_:)
-  //      ) as ContactListCoordinating)
-
   static private func registerCommonDependencies() {
     var environment: MessengerEnvironment = .live()
     environment.ndfEnvironment = .mainnet
+    environment.serviceList = .userDefaults(
+      key: "preImage",
+      userDefaults: UserDefaults(suiteName: "group.elixxir.messenger")!
+    )
     environment.udEnvironment = .init(
       address: AlternativeUDConstants.address,
       cert: AlternativeUDConstants.cert.data(using: .utf8)!,
diff --git a/Sources/LaunchFeature/LaunchViewModel+Messenger.swift b/Sources/LaunchFeature/LaunchViewModel+Messenger.swift
index 364be5cf10c6295580e83fc02ec1ccd06ad36651..0fa99f35a9c81debbae2c2cddcaefaa5caab3739 100644
--- a/Sources/LaunchFeature/LaunchViewModel+Messenger.swift
+++ b/Sources/LaunchFeature/LaunchViewModel+Messenger.swift
@@ -79,8 +79,10 @@ extension LaunchViewModel {
   }
 
   func setupLogWriter() {
-    _ = try! SetLogLevel.live(.fatal)
-    RegisterLogWriter.live(.init(handle: { XXLogger.live().debug($0) }))
+    _ = try! SetLogLevel.live(.error)
+    RegisterLogWriter.live(.init(handle: {
+      XXLogger.live().debug($0)
+    }))
   }
 
   func listenToNetworkUpdates() {
@@ -439,6 +441,11 @@ extension LaunchViewModel {
     if !messenger.isBackupRunning() {
       try? messenger.resumeBackup()
     }
+
+    try messenger.trackServices {
+      print(">>> Error on track services callback: \($0.localizedDescription)")
+    }
+
     // TODO: Biometric auth
   }
 }
diff --git a/Sources/PushFeature/Push.swift b/Sources/PushFeature/Push.swift
index 51c25bd52f513816ca850930e07a4c0a72204798..a5ce515126a20ce0fd6e01671eba919d338472c9 100644
--- a/Sources/PushFeature/Push.swift
+++ b/Sources/PushFeature/Push.swift
@@ -1,15 +1,7 @@
+import XXClient
 import Foundation
 
 public struct Push {
-    public let type: PushType
-    public let source: Data?
-
-    public init?(type: String, source: Data?) {
-        guard let pushType = PushType(rawValue: type) else {
-            return nil
-        }
-
-        self.type = pushType
-        self.source = source
-    }
+  public let type: NotificationReport.ReportType
+  public let source: Data
 }
diff --git a/Sources/PushFeature/PushExtractor.swift b/Sources/PushFeature/PushExtractor.swift
index 6d080841ae0e87120bb57391d09cd41e73bf39d4..dd00bcbe3a9b3d488a43f7ec5975cd6c188fb1ab 100644
--- a/Sources/PushFeature/PushExtractor.swift
+++ b/Sources/PushFeature/PushExtractor.swift
@@ -1,57 +1,46 @@
 import XXModels
 import Foundation
+import XXClient
+import XXMessengerClient
 import DependencyInjection
 
 public struct PushExtractor {
-    enum Constants {
-        static let preImage = "preImage"
-        static let appGroup = "group.elixxir.messenger"
-        static let notificationData = "notificationData"
-    }
-
-    public var extractFrom: ([AnyHashable: Any]) -> Result<[Push]?, Error>
+  enum Constants {
+    static let preImage = "preImage"
+    static let appGroup = "group.elixxir.messenger"
+    static let notificationData = "notificationData"
+  }
+  
+  public var extractFrom: ([AnyHashable: Any]) -> Result<[Push]?, Error>
 }
 
 public extension PushExtractor {
-    static let live = PushExtractor { dictionary in
-        NSLog("EXTRACTING PUSH A...")
-
-        guard let database = try? DependencyInjection.Container.shared.resolve() as Database,
-              let anyone = try? database.fetchContacts(.init()).first else {
-            NSLog("EXTRACTING PUSH B...")
-            return .success(nil)
-        }
-
-        NSLog("EXTRACTING PUSH C...")
-
-        return .success([.init(type: PushType.request.rawValue, source: anyone.id)!])
-
-//        guard let messenger = try? DependencyInjection.Container.shared.resolve() as Messenger,
-//              let data = dictionary[Constants.notificationData] as? String else {
-//            return .success(nil)
-//        }
-//
-//        do {
-//            let reportFunctor = GetNotificationsReport.live()
-//            let report = try reportFunctor(
-//                e2eId: messenger.e2e.get()!.getId(),
-//                notificationCSV: data,
-//                marshaledServices: Data() // <--- ???
-//            )
-//
-//            guard report.forMe,
-//                  report.type != .silent,
-//                  report.type != .default
-//            else {
-//                return .success(nil)
-//            }
-//
-//            return .success([Push(
-//                type: report.type.rawValue,
-//                source: report.source)!
-//            ])
-//        } catch {
-//            return .failure(error)
-//        }
+  static let live = PushExtractor { dictionary in
+    var environment: MessengerEnvironment = .live()
+    environment.ndfEnvironment = .mainnet
+    environment.serviceList = .userDefaults(
+      key: "preImage",
+      userDefaults: UserDefaults(suiteName: "group.elixxir.messenger")!
+    )
+    let messenger = Messenger.live(environment)
+    guard let csv = dictionary[Constants.notificationData] as? String,
+          let defaults = UserDefaults(suiteName: Constants.appGroup) else {
+      return .success(nil)
+    }
+    do {
+      let report = try messenger.getNotificationReport(notificationCSV: csv)
+      guard report.forMe,
+            report.type != .silent,
+            report.type != .default
+      else {
+        return .success(nil)
+      }
+      return .success([Push(
+        type: report.type,
+        source: report.source
+      )])
+    } catch {
+      return .failure(error)
     }
+  }
 }
diff --git a/Sources/PushFeature/PushHandler.swift b/Sources/PushFeature/PushHandler.swift
index b43a575d275a44c3c6e63979ecf37c5d1cf3fdbd..c22b66dd5b1bf6398dad00faa905fbda525bb3b8 100644
--- a/Sources/PushFeature/PushHandler.swift
+++ b/Sources/PushFeature/PushHandler.swift
@@ -8,171 +8,212 @@ import ReportingFeature
 import DependencyInjection
 
 public final class PushHandler: PushHandling {
-    private enum Constants {
-        static let appGroup = "group.elixxir.messenger"
-        static let usernamesSetting = "isShowingUsernames"
+  private enum Constants {
+    static let appGroup = "group.elixxir.messenger"
+    static let usernamesSetting = "isShowingUsernames"
+  }
+
+  @Dependency var messenger: Messenger
+
+  @KeyObject(.pushNotifications, defaultValue: false) var isPushEnabled: Bool
+
+  let requestAuth: RequestAuth
+  public static let defaultRequestAuth = UNUserNotificationCenter.current().requestAuthorization
+  public typealias RequestAuth = (UNAuthorizationOptions, @escaping (Bool, Error?) -> Void) -> Void
+
+  public var pushExtractor: PushExtractor
+  public var contentsBuilder: ContentsBuilder
+  public var applicationState: () -> UIApplication.State
+
+  public init(
+    requestAuth: @escaping RequestAuth = defaultRequestAuth,
+    pushExtractor: PushExtractor = .live,
+    contentsBuilder: ContentsBuilder = .live,
+    applicationState: @escaping () -> UIApplication.State = { UIApplication.shared.applicationState }
+  ) {
+    self.requestAuth = requestAuth
+    self.pushExtractor = pushExtractor
+    self.contentsBuilder = contentsBuilder
+    self.applicationState = applicationState
+  }
+
+  public func registerToken(_ token: Data) {
+    do {
+      try RegisterForNotifications.live(
+        e2eId: messenger.e2e.get()!.getId(),
+        token: token.map { String(format: "%02hhx", $0) }.joined()
+      )
+    } catch {
+      print(error.localizedDescription)
+      isPushEnabled = false
     }
+  }
 
-    @Dependency var messenger: Messenger
-    @Dependency var reportingStatus: ReportingStatus
-
-    @KeyObject(.pushNotifications, defaultValue: false) var isPushEnabled: Bool
-
-    let requestAuth: RequestAuth
-    public static let defaultRequestAuth = UNUserNotificationCenter.current().requestAuthorization
-    public typealias RequestAuth = (UNAuthorizationOptions, @escaping (Bool, Error?) -> Void) -> Void
-
-    public var pushExtractor: PushExtractor
-    public var contentsBuilder: ContentsBuilder
-    public var applicationState: () -> UIApplication.State
-
-    public init(
-        requestAuth: @escaping RequestAuth = defaultRequestAuth,
-        pushExtractor: PushExtractor = .live,
-        contentsBuilder: ContentsBuilder = .live,
-        applicationState: @escaping () -> UIApplication.State = { UIApplication.shared.applicationState }
-    ) {
-        self.requestAuth = requestAuth
-        self.pushExtractor = pushExtractor
-        self.contentsBuilder = contentsBuilder
-        self.applicationState = applicationState
-    }
-
-    public func registerToken(_ token: Data) {
-        do {
-            try RegisterForNotifications.live(
-                e2eId: messenger.e2e.get()!.getId(),
-                token: token.map { String(format: "%02hhx", $0) }.joined()
-            )
-        } catch {
-            print(error.localizedDescription)
-            isPushEnabled = false
-        }
-    }
-
-    public func requestAuthorization(
-        _ completion: @escaping (Result<Bool, Error>) -> Void
-    ) {
-        let options: UNAuthorizationOptions = [.alert, .sound, .badge]
+  public func requestAuthorization(
+    _ completion: @escaping (Result<Bool, Error>) -> Void
+  ) {
+    let options: UNAuthorizationOptions = [.alert, .sound, .badge]
 
-        requestAuth(options) { granted, error in
-            guard let error = error else {
-                completion(.success(granted))
-                return
-            }
+    requestAuth(options) { granted, error in
+      guard let error = error else {
+        completion(.success(granted))
+        return
+      }
 
-            completion(.failure(error))
-        }
+      completion(.failure(error))
     }
-
-    public func handlePush(
-        _ userInfo: [AnyHashable: Any],
-        _ completion: @escaping (UIBackgroundFetchResult) -> Void
-    ) {
-        do {
-            guard
-                let pushes = try pushExtractor.extractFrom(userInfo).get(),
-                applicationState() == .background,
-                pushes.isEmpty == false
-            else {
-                completion(.noData)
-                return
-            }
-
-            let content = contentsBuilder.build("New Messages Available", pushes.first!)
-            let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
-            let request = UNNotificationRequest(identifier: Bundle.main.bundleIdentifier!, content: content, trigger: trigger)
-
-            UNUserNotificationCenter.current().add(request) { error in
-                if error == nil {
-                    completion(.newData)
-                } else {
-                    completion(.failed)
-                }
-            }
-        } catch {
-            completion(.failed)
+  }
+
+  public func handlePush(
+    _ userInfo: [AnyHashable: Any],
+    _ completion: @escaping (UIBackgroundFetchResult) -> Void
+  ) {
+    do {
+      guard
+        let pushes = try pushExtractor.extractFrom(userInfo).get(),
+        applicationState() == .background,
+        pushes.isEmpty == false
+      else {
+        completion(.noData)
+        return
+      }
+
+      let content = contentsBuilder.build("New Messages Available", pushes.first!)
+      let trigger = UNTimeIntervalNotificationTrigger(timeInterval: 1, repeats: false)
+      let request = UNNotificationRequest(identifier: Bundle.main.bundleIdentifier!, content: content, trigger: trigger)
+
+      UNUserNotificationCenter.current().add(request) { error in
+        if error == nil {
+          completion(.newData)
+        } else {
+          completion(.failed)
         }
+      }
+    } catch {
+      completion(.failed)
+    }
+  }
+
+  public func handlePush(
+    _ request: UNNotificationRequest,
+    _ completion: @escaping (UNNotificationContent) -> Void
+  ) {
+    guard let pushes = try? pushExtractor.extractFrom(request.content.userInfo).get(), !pushes.isEmpty,
+          let defaults = UserDefaults(suiteName: Constants.appGroup) else { return }
+
+    let dbPath = FileManager.default
+      .containerURL(forSecurityApplicationGroupIdentifier: "group.elixxir.messenger")!
+      .appendingPathComponent("xxm_database")
+      .appendingPathExtension("sqlite").path
+
+    let tuples: [(String, Push)] = pushes.compactMap {
+      guard let dbManager = try? Database.onDisk(path: dbPath),
+            let contact = try? dbManager.fetchContacts(.init(id: [$0.source])).first else {
+        return (getStringForUnknown(type: $0.type), $0)
+      }
+
+      if ReportingStatus.live().isEnabled(), (contact.isBlocked || contact.isBanned) {
+        return nil
+      }
+
+      if let showSender = defaults.value(forKey: Constants.usernamesSetting) as? Bool, showSender == true {
+        let name = (contact.nickname ?? contact.username) ?? ""
+        return (getStringForKnown(name: name, type: $0.type), $0)
+      } else {
+        return (getStringForUnknown(type: $0.type), $0)
+      }
     }
 
-    public func handlePush(
-        _ request: UNNotificationRequest,
-        _ completion: @escaping (UNNotificationContent) -> Void
-    ) {
-        guard let pushes = try? pushExtractor.extractFrom(request.content.userInfo).get(), !pushes.isEmpty,
-              let defaults = UserDefaults(suiteName: Constants.appGroup) else {
-            return
-        }
-
-        let dbPath = FileManager.default
-            .containerURL(forSecurityApplicationGroupIdentifier: "group.elixxir.messenger")!
-            .appendingPathComponent("xxm_database")
-            .appendingPathExtension("sqlite").path
-
-        let tuples: [(String, Push)] = pushes.compactMap {
-            guard let userId = $0.source,
-                  let dbManager = try? Database.onDisk(path: dbPath),
-                  let contact = try? dbManager.fetchContacts(.init(id: [userId])).first else {
-                return ($0.type.unknownSenderContent!, $0)
-            }
-
-            if reportingStatus.isEnabled(), (contact.isBlocked || contact.isBanned) {
-                return nil
-            }
-
-            if let showSender = defaults.value(forKey: Constants.usernamesSetting) as? Bool, showSender == true {
-                let name = (contact.nickname ?? contact.username) ?? ""
-                return ($0.type.knownSenderContent(name)!, $0)
-            } else {
-                return ($0.type.unknownSenderContent!, $0)
-            }
-        }
-
-        tuples
-            .map(contentsBuilder.build)
-            .forEach { completion($0) }
+    tuples
+      .map(contentsBuilder.build)
+      .forEach { completion($0) }
+  }
+
+  public func handleAction(
+    _ router: PushRouter,
+    _ userInfo: [AnyHashable : Any],
+    _ completion: @escaping () -> Void
+  ) {
+    guard let typeString = userInfo["type"] as? String,
+          let type = NotificationReport.ReportType.init(rawValue: typeString) else {
+      completion()
+      return
     }
 
-    public func handleAction(
-        _ router: PushRouter,
-        _ userInfo: [AnyHashable : Any],
-        _ completion: @escaping () -> Void
-    ) {
-        guard let typeString = userInfo["type"] as? String,
-              let type = PushType(rawValue: typeString) else {
-            completion()
-            return
-        }
+    let route: PushRouter.Route
 
-        let route: PushRouter.Route
+    switch type {
+    case .e2e:
+      guard let source = userInfo["source"] as? Data else {
+        completion()
+        return
+      }
 
-        switch type {
-        case .e2e:
-            guard let source = userInfo["source"] as? Data else {
-                completion()
-                return
-            }
+      route = .contactChat(id: source)
 
-            route = .contactChat(id: source)
+    case .group:
+      guard let source = userInfo["source"] as? Data else {
+        completion()
+        return
+      }
 
-        case .group:
-            guard let source = userInfo["source"] as? Data else {
-                completion()
-                return
-            }
+      route = .groupChat(id: source)
 
-            route = .groupChat(id: source)
+    case .request, .groupRQ:
+      route = .requests
 
-        case .request, .groupRq:
-            route = .requests
+    case .silent, .`default`:
+      fatalError("Silent/Default push types should be filtered at this point")
 
-        case .silent, .`default`:
-            fatalError("Silent/Default push types should be filtered at this point")
+    case .reset, .endFT, .confirm:
+      route = .requests
+    }
 
-        case .reset, .endFT, .confirm:
-            route = .requests
-        }
+    router.navigateTo(route, completion)
+  }
+}
 
-        router.navigateTo(route, completion)
-    }
+private func getStringForUnknown(type: NotificationReport.ReportType) -> String {
+  switch type {
+  case .`default`, .silent:
+    return ""
+  case .request:
+    return "Request received"
+  case .reset:
+    return "One of your contacts has restored their account"
+  case .confirm:
+    return "Request accepted"
+  case .e2e:
+    return "New private message"
+  case .group:
+    return "New group message"
+  case .endFT:
+    return "New media received"
+  case .groupRQ:
+    return "Group request received"
+  }
+}
+
+private func getStringForKnown(
+  name: String,
+  type: NotificationReport.ReportType
+) -> String {
+  switch type {
+  case .silent, .`default`:
+    return ""
+  case .e2e:
+    return String(format: "%@ sent you a private message", name)
+  case .reset:
+    return String(format: "%@ restored their account", name)
+  case .endFT:
+    return String(format: "%@ sent you a file", name)
+  case .group:
+    return String(format: "%@ sent you a group message", name)
+  case .groupRQ:
+    return String(format: "%@ sent you a group request", name)
+  case .confirm:
+    return String(format: "%@ confirmed your contact request", name)
+  case .request:
+    return String(format: "%@ sent you a contact request", name)
+  }
 }
diff --git a/Sources/PushFeature/PushType.swift b/Sources/PushFeature/PushType.swift
deleted file mode 100644
index 7cd2fefefcbce0968a7d4478aa4e5cc01d771f98..0000000000000000000000000000000000000000
--- a/Sources/PushFeature/PushType.swift
+++ /dev/null
@@ -1,53 +0,0 @@
-public enum PushType: String {
-    case e2e
-    case reset
-    case endFT
-    case group
-    case silent
-    case groupRq
-    case confirm
-    case request
-    case `default`
-
-    var unknownSenderContent: String? {
-        switch self {
-        case .silent, .`default`:
-            return nil
-        case .endFT:
-            return "New media received"
-        case .group:
-            return "New group message"
-        case .groupRq:
-            return "Group request received"
-        case .e2e:
-            return "New private message"
-        case .reset:
-            return "One of your contacts has restored their account"
-        case .request:
-            return "Request received"
-        case .confirm:
-            return "Request accepted"
-        }
-    }
-
-    var knownSenderContent: (String) -> String? {
-        switch self {
-        case .silent, .`default`:
-            return { _ in nil }
-        case .e2e:
-            return { String(format: "%@ sent you a private message", $0) }
-        case .reset:
-            return { String(format: "%@ restored their account", $0) }
-        case .endFT:
-            return { String(format: "%@ sent you a file", $0) }
-        case .group:
-            return { String(format: "%@ sent you a group message", $0) }
-        case .groupRq:
-            return { String(format: "%@ sent you a group request", $0) }
-        case .confirm:
-            return { String(format: "%@ confirmed your contact request", $0) }
-        case .request:
-            return { String(format: "%@ sent you a contact request", $0) }
-        }
-    }
-}
diff --git a/Sources/ReportingFeature/ReportingStatus.swift b/Sources/ReportingFeature/ReportingStatus.swift
index 1bb72983430de28a6d46c47cd7ec2a3a21612659..f6346ce1350caa9bca8ead86515724a5edf7171d 100644
--- a/Sources/ReportingFeature/ReportingStatus.swift
+++ b/Sources/ReportingFeature/ReportingStatus.swift
@@ -1,51 +1,51 @@
 import Combine
 
 public struct ReportingStatus {
-    public var isOptional: () -> Bool
-    public var isEnabled: () -> Bool
-    public var isEnabledPublisher: () -> AnyPublisher<Bool, Never>
-    public var enable: (Bool) -> Void
+  public var isOptional: () -> Bool
+  public var isEnabled: () -> Bool
+  public var isEnabledPublisher: () -> AnyPublisher<Bool, Never>
+  public var enable: (Bool) -> Void
 }
 
 extension ReportingStatus {
-    public static func live(
-        isOptional: ReportingStatusIsOptional = .live(),
-        isEnabled: ReportingStatusIsEnabled = .live()
-    ) -> ReportingStatus {
-        ReportingStatus(
-            isOptional: {
-                isOptional.get()
-            },
-            isEnabled: {
-                if isOptional.get() == false {
-                    return true
-                }
+  public static func live(
+    isOptional: ReportingStatusIsOptional = .live(),
+    isEnabled: ReportingStatusIsEnabled = .live()
+  ) -> ReportingStatus {
+    ReportingStatus(
+      isOptional: {
+        isOptional.get()
+      },
+      isEnabled: {
+        if isOptional.get() == false {
+          return true
+        }
 
-                return isEnabled.get()
-            },
-            isEnabledPublisher: {
-                if isOptional.get() == false {
-                    return Just(true).eraseToAnyPublisher()
-                }
+        return isEnabled.get()
+      },
+      isEnabledPublisher: {
+        if isOptional.get() == false {
+          return Just(true).eraseToAnyPublisher()
+        }
 
-                return isEnabled.publisher()
-            },
-            enable: { enabled in
-                isEnabled.set(enabled)
-            }
-        )
-    }
+        return isEnabled.publisher()
+      },
+      enable: { enabled in
+        isEnabled.set(enabled)
+      }
+    )
+  }
 
-    public static func mock(
-        isEnabled: Bool = false,
-        isOptional: Bool = true
-    ) -> ReportingStatus {
-        let isEnabledSubject = CurrentValueSubject<Bool, Never>(isEnabled)
-        return ReportingStatus(
-            isOptional: { isOptional },
-            isEnabled: { isEnabledSubject.value },
-            isEnabledPublisher: { isEnabledSubject.eraseToAnyPublisher() },
-            enable: { isEnabledSubject.send($0) }
-        )
-    }
+  public static func mock(
+    isEnabled: Bool = false,
+    isOptional: Bool = true
+  ) -> ReportingStatus {
+    let isEnabledSubject = CurrentValueSubject<Bool, Never>(isEnabled)
+    return ReportingStatus(
+      isOptional: { isOptional },
+      isEnabled: { isEnabledSubject.value },
+      isEnabledPublisher: { isEnabledSubject.eraseToAnyPublisher() },
+      enable: { isEnabledSubject.send($0) }
+    )
+  }
 }
diff --git a/Sources/SearchFeature/Controllers/SearchLeftController.swift b/Sources/SearchFeature/Controllers/SearchLeftController.swift
index 8370152285392b1d722c41013a687dee5c254502..3db6a1dc74fed08a9856943d2506dd6a54a40195 100644
--- a/Sources/SearchFeature/Controllers/SearchLeftController.swift
+++ b/Sources/SearchFeature/Controllers/SearchLeftController.swift
@@ -108,24 +108,6 @@ final class SearchLeftController: UIViewController {
   }
 
   private func setupBindings() {
-    //        viewModel.hudPublisher
-    //            .removeDuplicates()
-    //            .receive(on: DispatchQueue.main)
-    //            .sink { [unowned self] in
-    //                hud.update(with: $0)
-    //
-    //                if case .onAction = $0, let hudBtn = hud.actionButton {
-    //                    hudBtn.publisher(for: .touchUpInside)
-    //                        .receive(on: DispatchQueue.main)
-    //                        .sink { [unowned self] in viewModel.didTapCancelSearch() }
-    //                        .store(in: &self.hudCancellables)
-    //                } else {
-    //                    hudCancellables.forEach { $0.cancel() }
-    //                    hudCancellables.removeAll()
-    //                }
-    //            }
-    //            .store(in: &cancellables)
-
     viewModel
       .statePublisher
       .map(\.item)
diff --git a/Sources/SearchFeature/ViewModels/SearchContainerViewModel.swift b/Sources/SearchFeature/ViewModels/SearchContainerViewModel.swift
index 9306052b15cd56eb80c7d649635936fab0676334..011442d5025d3df89d5b23dd2e9aabe015b0ea3f 100644
--- a/Sources/SearchFeature/ViewModels/SearchContainerViewModel.swift
+++ b/Sources/SearchFeature/ViewModels/SearchContainerViewModel.swift
@@ -1,8 +1,8 @@
 import UIKit
 import Combine
 import Defaults
-import PushFeature
 import XXClient
+import PushFeature
 import DependencyInjection
 
 final class SearchContainerViewModel {
diff --git a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
index 8f21ff47a2f5d6fab2517d555ec355b623afc529..93fe554a846e084811fbc9f4474821037c7ed0be 100644
--- a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
+++ b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift
@@ -62,11 +62,19 @@ final class SearchLeftViewModel {
     if let pendingInvitation = invitation {
       invitation = nil
       stateSubject.value.input = pendingInvitation
-      hudController.show(.init(actionTitle: Localized.Ud.Search.cancel))
+      hudController.show(.init(
+        actionTitle: Localized.Ud.Search.cancel,
+        hasDotAnimation: true,
+        onTapClosure: { [weak self] in
+          guard let self else { return }
+          self.didTapCancelSearch()
+        }
+      ))
 
       networkCancellable.removeAll()
 
-      networkMonitor.statusPublisher
+      networkMonitor
+        .statusPublisher
         .first { $0 == .available }
         .eraseToAnyPublisher()
         .flatMap { _ in
@@ -102,7 +110,14 @@ final class SearchLeftViewModel {
   func didStartSearching() {
     guard stateSubject.value.input.isEmpty == false else { return }
 
-    hudController.show(.init(actionTitle: Localized.Ud.Search.cancel))
+    hudController.show(.init(
+      actionTitle: Localized.Ud.Search.cancel,
+      hasDotAnimation: true,
+      onTapClosure: { [weak self] in
+        guard let self else { return }
+        self.didTapCancelSearch()
+      }
+    ))
 
     var content = stateSubject.value.input
 
diff --git a/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift b/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift
index 4337264c1fcd97117547e4b8f61d971446e195cc..63d3713b68c07fe9cf968581314e2767bc850714 100644
--- a/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift
+++ b/Sources/SettingsFeature/ViewModels/SettingsViewModel.swift
@@ -118,9 +118,12 @@ final class SettingsViewModel {
         case .success(let granted):
           self.pushNotifications = granted
           self.stateRelay.value.isPushNotification = granted
-          if granted { DispatchQueue.main.async { UIApplication.shared.registerForRemoteNotifications() }}
+          if granted {
+            DispatchQueue.main.async {
+              UIApplication.shared.registerForRemoteNotifications()
+            }
+          }
           self.hudController.dismiss()
-          
         case .failure(let error):
           self.hudController.show(.init(error: error))
           self.pushNotifications = false
@@ -130,19 +133,15 @@ final class SettingsViewModel {
     } else {
       backgroundScheduler.schedule { [weak self] in
         guard let self else { return }
-        
         do {
           try UnregisterForNotifications.live(
             e2eId: self.messenger.e2e.get()!.getId()
           )
-          
           self.hudController.dismiss()
         } catch {
           let xxError = CreateUserFriendlyErrorMessage.live(error.localizedDescription)
           self.hudController.show(.init(content: xxError))
-
         }
-        
         self.pushNotifications = false
         self.stateRelay.value.isPushNotification = false
       }
diff --git a/Sources/Shared/Controllers/HUDController.swift b/Sources/Shared/Controllers/HUDController.swift
index fc48d6c7dd643aebcbf21aa24a8e6e71732a2ede..7606cd7fd85f4255d6990c804baeed7b8b20d3b0 100644
--- a/Sources/Shared/Controllers/HUDController.swift
+++ b/Sources/Shared/Controllers/HUDController.swift
@@ -1,6 +1,9 @@
 import Combine
+import Foundation
 
 public final class HUDController {
+  private var timer: Timer?
+
   var modelPublisher: AnyPublisher<HUDModel?, Never> {
     modelSubject.eraseToAnyPublisher()
   }
@@ -19,6 +22,13 @@ public final class HUDController {
       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/Models/HUDModel.swift b/Sources/Shared/Models/HUDModel.swift
index ddc8fb5c2cd3ae20e8733147c937e66c59411b96..c77d5607aca8b33031373e17d47d087d36aedce8 100644
--- a/Sources/Shared/Models/HUDModel.swift
+++ b/Sources/Shared/Models/HUDModel.swift
@@ -13,7 +13,6 @@ public struct HUDModel {
     content: String? = nil,
     actionTitle: String? = nil,
     hasDotAnimation: Bool = false,
-    isAutoDismissable: Bool = false,
     onTapClosure: (() -> Void)? = nil
   ) {
     self.title = title
@@ -21,7 +20,7 @@ public struct HUDModel {
     self.actionTitle = actionTitle
     self.onTapClosure = onTapClosure
     self.hasDotAnimation = hasDotAnimation
-    self.isAutoDismissable = isAutoDismissable
+    self.isAutoDismissable = onTapClosure == nil && !hasDotAnimation
   }
 
   public init(