diff --git a/Sources/App/AppDelegate.swift b/Sources/App/AppDelegate.swift index 00b8875eaf650d668ae4541fb254fc52c2c50980..9b4a816dad120c5e01dbd428933a4161d71a1feb 100644 --- a/Sources/App/AppDelegate.swift +++ b/Sources/App/AppDelegate.swift @@ -20,7 +20,6 @@ public class AppDelegate: UIResponder, UIApplicationDelegate { @Dependency private var crashReporter: CrashReporter @Dependency private var dropboxService: DropboxInterface - @KeyObject(.invitation, defaultValue: nil) var invitation: String? @KeyObject(.hideAppList, defaultValue: false) var hideAppList: Bool @KeyObject(.recordingLogs, defaultValue: true) var recordingLogs: Bool @KeyObject(.crashReporting, defaultValue: true) var isCrashReportingEnabled: Bool @@ -145,9 +144,7 @@ public class AppDelegate: UIResponder, UIApplicationDelegate { ) -> Bool { if let username = getUsernameFromInvitationDeepLink(url) { let router = try! DependencyInjection.Container.shared.resolve() as PushRouter - invitation = username - router.navigateTo(.search, {}) - + router.navigateTo(.search(username: username), {}) return true } else { return dropboxService.handleOpenUrl(url) diff --git a/Sources/App/PushRouter.swift b/Sources/App/PushRouter.swift index d81f841fc2c8b28a0380da507e37208c0bf2faf9..a2d2d809d54818566c1aec693ed4ad07937c6999 100644 --- a/Sources/App/PushRouter.swift +++ b/Sources/App/PushRouter.swift @@ -15,17 +15,18 @@ extension PushRouter { launchController.pendingPushRoute = route } else { switch route { - case .search: - if !(navigationController.viewControllers.last is SearchContainerController) { - navigationController.setViewControllers([ - ChatListController(), - SearchContainerController() - ], animated: true) - } case .requests: if !(navigationController.viewControllers.last is RequestsContainerController) { navigationController.setViewControllers([RequestsContainerController()], animated: true) } + case .search(username: let username): + if let _ = try? DependencyInjection.Container.shared.resolve() as SessionType, + !(navigationController.viewControllers.last is SearchContainerController) { + navigationController.setViewControllers([ + ChatListController(), + SearchContainerController(username) + ], animated: true) + } case .contactChat(id: let id): if let session = try? DependencyInjection.Container.shared.resolve() as SessionType, let contact = try? session.dbManager.fetchContacts(.init(id: [id])).first { diff --git a/Sources/ChatListFeature/Coordinator/ChatListCoordinator.swift b/Sources/ChatListFeature/Coordinator/ChatListCoordinator.swift index bb412859b16fe99591c8b658fc4b8798fe27fb00..acd4fbcaecf645611fd30d058a0172f785b03fab 100644 --- a/Sources/ChatListFeature/Coordinator/ChatListCoordinator.swift +++ b/Sources/ChatListFeature/Coordinator/ChatListCoordinator.swift @@ -27,7 +27,7 @@ public struct ChatListCoordinator: ChatListCoordinating { var bottomPresenter: Presenting = BottomPresenter() var scanFactory: () -> UIViewController - var searchFactory: () -> UIViewController + var searchFactory: (String?) -> UIViewController var newGroupFactory: () -> UIViewController var contactsFactory: () -> UIViewController var contactFactory: (Contact) -> UIViewController @@ -37,7 +37,7 @@ public struct ChatListCoordinator: ChatListCoordinating { public init( scanFactory: @escaping () -> UIViewController, - searchFactory: @escaping () -> UIViewController, + searchFactory: @escaping (String?) -> UIViewController, newGroupFactory: @escaping () -> UIViewController, contactsFactory: @escaping () -> UIViewController, contactFactory: @escaping (Contact) -> UIViewController, @@ -58,7 +58,7 @@ public struct ChatListCoordinator: ChatListCoordinating { public extension ChatListCoordinator { func toSearch(from parent: UIViewController) { - let screen = searchFactory() + let screen = searchFactory(nil) pushPresenter.present(screen, from: parent) } diff --git a/Sources/ContactListFeature/Coordinator/ContactListCoordinator.swift b/Sources/ContactListFeature/Coordinator/ContactListCoordinator.swift index 56043d7556f0d0d4eb19c4e9fae21cd9163c878c..eb967cf04231cb85c203714bb66dd9546bac3209 100644 --- a/Sources/ContactListFeature/Coordinator/ContactListCoordinator.swift +++ b/Sources/ContactListFeature/Coordinator/ContactListCoordinator.swift @@ -28,7 +28,7 @@ public struct ContactListCoordinator: ContactListCoordinating { var replacePresenter: Presenting = ReplacePresenter(mode: .replaceLast) var scanFactory: () -> UIViewController - var searchFactory: () -> UIViewController + var searchFactory: (String?) -> UIViewController var newGroupFactory: () -> UIViewController var requestsFactory: () -> UIViewController var contactFactory: (Contact) -> UIViewController @@ -39,7 +39,7 @@ public struct ContactListCoordinator: ContactListCoordinating { public init( scanFactory: @escaping () -> UIViewController, - searchFactory: @escaping () -> UIViewController, + searchFactory: @escaping (String?) -> UIViewController, newGroupFactory: @escaping () -> UIViewController, requestsFactory: @escaping () -> UIViewController, contactFactory: @escaping (Contact) -> UIViewController, @@ -84,7 +84,7 @@ public extension ContactListCoordinator { } func toSearch(from parent: UIViewController) { - let screen = searchFactory() + let screen = searchFactory(nil) pushPresenter.present(screen, from: parent) } diff --git a/Sources/Defaults/KeyObject.swift b/Sources/Defaults/KeyObject.swift index 5714b112586e2c54b1c6aeae19224e4a060770fc..7757f7ed4fa550c478736b76cd7c1036ef4fde34 100644 --- a/Sources/Defaults/KeyObject.swift +++ b/Sources/Defaults/KeyObject.swift @@ -21,7 +21,6 @@ public enum Key: String { // MARK: General case theme - case invitation // MARK: Requests diff --git a/Sources/LaunchFeature/LaunchController.swift b/Sources/LaunchFeature/LaunchController.swift index 0a6a1c651affe95c973a5eb6b5b46a968b5b5a48..9d904232f4f1900e8ea1880a83717a4b9eadafd6 100644 --- a/Sources/LaunchFeature/LaunchController.swift +++ b/Sources/LaunchFeature/LaunchController.swift @@ -49,17 +49,15 @@ public final class LaunchController: UIViewController { .receive(on: DispatchQueue.main) .sink { [unowned self] in switch $0 { - case .search: - coordinator.toSearch(from: self) case .chats: if let pushRoute = pendingPushRoute { switch pushRoute { - case .search: - coordinator.toSearch(from: self) - case .requests: coordinator.toRequests(from: self) + case .search(username: let username): + coordinator.toSearch(searching: username, from: self) + case .groupChat(id: let groupId): if let groupInfo = viewModel.getGroupInfoWith(groupId: groupId) { coordinator.toGroupChat(with: groupInfo, from: self) diff --git a/Sources/LaunchFeature/LaunchCoordinator.swift b/Sources/LaunchFeature/LaunchCoordinator.swift index a9612d61ecf217dcdef7af544cef60b67509adbd..28ac7f90d6833c85d43cf5dfc2fd56a0bc4dad23 100644 --- a/Sources/LaunchFeature/LaunchCoordinator.swift +++ b/Sources/LaunchFeature/LaunchCoordinator.swift @@ -5,8 +5,8 @@ import Presentation public protocol LaunchCoordinating { func toChats(from: UIViewController) - func toSearch(from: UIViewController) func toRequests(from: UIViewController) + func toSearch(searching: String, from: UIViewController) func toOnboarding(with: String, from: UIViewController) func toSingleChat(with: Contact, from: UIViewController) func toGroupChat(with: GroupInfo, from: UIViewController) @@ -15,7 +15,7 @@ public protocol LaunchCoordinating { public struct LaunchCoordinator: LaunchCoordinating { var replacePresenter: Presenting = ReplacePresenter() - var searchFactory: () -> UIViewController + var searchFactory: (String) -> UIViewController var requestsFactory: () -> UIViewController var chatListFactory: () -> UIViewController var onboardingFactory: (String) -> UIViewController @@ -23,7 +23,7 @@ public struct LaunchCoordinator: LaunchCoordinating { var groupChatFactory: (GroupInfo) -> UIViewController public init( - searchFactory: @escaping () -> UIViewController, + searchFactory: @escaping (String) -> UIViewController, requestsFactory: @escaping () -> UIViewController, chatListFactory: @escaping () -> UIViewController, onboardingFactory: @escaping (String) -> UIViewController, @@ -40,8 +40,8 @@ public struct LaunchCoordinator: LaunchCoordinating { } public extension LaunchCoordinator { - func toSearch(from parent: UIViewController) { - let screen = searchFactory() + func toSearch(searching: String, from parent: UIViewController) { + let screen = searchFactory(searching) let chatListScreen = chatListFactory() replacePresenter.present(chatListScreen, screen, from: parent) } diff --git a/Sources/LaunchFeature/LaunchViewModel.swift b/Sources/LaunchFeature/LaunchViewModel.swift index 42b69bb7bfc8e2d45ec2fe14acdf18f01e9bd3db..0b8354dacde4b0a364b2f7d2b4a3b7701a66093e 100644 --- a/Sources/LaunchFeature/LaunchViewModel.swift +++ b/Sources/LaunchFeature/LaunchViewModel.swift @@ -24,7 +24,6 @@ struct Update { enum LaunchRoute { case chats - case search case update(Update) case onboarding(String) } @@ -37,7 +36,6 @@ final class LaunchViewModel { @Dependency private var permissionHandler: PermissionHandling @KeyObject(.username, defaultValue: nil) var username: String? - @KeyObject(.invitation, defaultValue: nil) var invitation: String? @KeyObject(.biometrics, defaultValue: false) var isBiometricsOn: Bool var hudPublisher: AnyPublisher<HUDStatus, Never> { @@ -187,23 +185,14 @@ final class LaunchViewModel { switch $0 { case .success(let granted): guard granted else { return } - - if self.invitation != nil { - self.routeSubject.send(.search) - } else { - self.routeSubject.send(.chats) - } + self.routeSubject.send(.chats) case .failure(let error): self.hudSubject.send(.error(HUDError(with: error))) } } } else { - if self.invitation != nil { - self.routeSubject.send(.search) - } else { - self.routeSubject.send(.chats) - } + self.routeSubject.send(.chats) } } } diff --git a/Sources/OnboardingFeature/Coordinator/OnboardingCoordinator.swift b/Sources/OnboardingFeature/Coordinator/OnboardingCoordinator.swift index ca73d7c55d96709e85f076e6e06d74e6bc09a155..59bf66c4e95c27f4a151472e473f657c88c13e1e 100644 --- a/Sources/OnboardingFeature/Coordinator/OnboardingCoordinator.swift +++ b/Sources/OnboardingFeature/Coordinator/OnboardingCoordinator.swift @@ -41,7 +41,7 @@ public struct OnboardingCoordinator: OnboardingCoordinating { var emailFactory: () -> UIViewController var phoneFactory: () -> UIViewController - var searchFactory: () -> UIViewController + var searchFactory: (String?) -> UIViewController var welcomeFactory: () -> UIViewController var chatListFactory: () -> UIViewController var usernameFactory: (String) -> UIViewController @@ -54,7 +54,7 @@ public struct OnboardingCoordinator: OnboardingCoordinating { public init( emailFactory: @escaping () -> UIViewController, phoneFactory: @escaping () -> UIViewController, - searchFactory: @escaping () -> UIViewController, + searchFactory: @escaping (String?) -> UIViewController, welcomeFactory: @escaping () -> UIViewController, chatListFactory: @escaping () -> UIViewController, usernameFactory: @escaping (String) -> UIViewController, @@ -114,7 +114,7 @@ public extension OnboardingCoordinator { } func toChats(from parent: UIViewController) { - let searchScreen = searchFactory() + let searchScreen = searchFactory(nil) let chatListScreen = chatListFactory() replacePresenter.present(chatListScreen, searchScreen, from: parent) } diff --git a/Sources/PushFeature/PushRouter.swift b/Sources/PushFeature/PushRouter.swift index 51af8a80ae87cf6bbab518a666256e9925685325..05885d5196b6025f24d18bd47f5922f1164d1f43 100644 --- a/Sources/PushFeature/PushRouter.swift +++ b/Sources/PushFeature/PushRouter.swift @@ -4,10 +4,10 @@ public struct PushRouter { public typealias NavigateTo = (Route, @escaping () -> Void) -> Void public enum Route { - case search case requests case groupChat(id: Data) case contactChat(id: Data) + case search(username: String) } public var navigateTo: NavigateTo diff --git a/Sources/RequestsFeature/Coordinator/RequestsCoordinator.swift b/Sources/RequestsFeature/Coordinator/RequestsCoordinator.swift index 3c798cfc0243bffbbf54939c37d7ea7eb90c1294..571bf625fc1a98b1cf2905154a660fd4cbebd92e 100644 --- a/Sources/RequestsFeature/Coordinator/RequestsCoordinator.swift +++ b/Sources/RequestsFeature/Coordinator/RequestsCoordinator.swift @@ -24,7 +24,7 @@ public struct RequestsCoordinator: RequestsCoordinating { var bottomPresenter: Presenting = BottomPresenter() var fullscreenPresenter: Presenting = FullscreenPresenter() - var searchFactory: () -> UIViewController + var searchFactory: (String?) -> UIViewController var contactFactory: (Contact) -> UIViewController var singleChatFactory: (Contact) -> UIViewController var groupChatFactory: (GroupInfo) -> UIViewController @@ -32,7 +32,7 @@ public struct RequestsCoordinator: RequestsCoordinating { var nicknameFactory: (String, @escaping StringClosure) -> UIViewController public init( - searchFactory: @escaping () -> UIViewController, + searchFactory: @escaping (String?) -> UIViewController, contactFactory: @escaping (Contact) -> UIViewController, singleChatFactory: @escaping (Contact) -> UIViewController, groupChatFactory: @escaping (GroupInfo) -> UIViewController, @@ -81,7 +81,7 @@ public extension RequestsCoordinator { } func toSearch(from parent: UIViewController) { - let screen = searchFactory() + let screen = searchFactory(nil) pushPresenter.present(screen, from: parent) } diff --git a/Sources/SearchFeature/Controllers/SearchContainerController.swift b/Sources/SearchFeature/Controllers/SearchContainerController.swift index ad85b25640a1f1a5e418bf9974b2a0656021d202..9cba53034d3a3a09a5fc5bcd80e4c48b7566eb06 100644 --- a/Sources/SearchFeature/Controllers/SearchContainerController.swift +++ b/Sources/SearchFeature/Controllers/SearchContainerController.swift @@ -14,11 +14,18 @@ public final class SearchContainerController: UIViewController { private var contentOffset: CGPoint? private var cancellables = Set<AnyCancellable>() + private let leftController: SearchLeftController private let viewModel = SearchContainerViewModel() - private let leftController = SearchLeftController() private let rightController = SearchRightController() private var drawerCancellables = Set<AnyCancellable>() + public init(_ invitation: String? = nil) { + self.leftController = .init(invitation) + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { nil } + public override func loadView() { view = screenView embedControllers() diff --git a/Sources/SearchFeature/Controllers/SearchLeftController.swift b/Sources/SearchFeature/Controllers/SearchLeftController.swift index b3ca0e83922c6fe4868b68e5338ff1ee7fdaa496..cc46ad60cf83f8baa03aa3ac7bb34562fbccaea8 100644 --- a/Sources/SearchFeature/Controllers/SearchLeftController.swift +++ b/Sources/SearchFeature/Controllers/SearchLeftController.swift @@ -19,14 +19,21 @@ final class SearchLeftController: UIViewController { lazy private var screenView = SearchLeftView() + let viewModel: SearchLeftViewModel private var dataSource: SearchDiffableDataSource! - private(set) var viewModel = SearchLeftViewModel() private var drawerCancellables = Set<AnyCancellable>() private let adrpURLString = "https://links.xx.network/adrp" private var cancellables = Set<AnyCancellable>() private var hudCancellables = Set<AnyCancellable>() + init(_ invitation: String? = nil) { + self.viewModel = .init(invitation) + super.init(nibName: nil, bundle: nil) + } + + required init?(coder: NSCoder) { nil } + override func loadView() { view = screenView } diff --git a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift index 8206e136f89d0068432458ccac97d8ebe544c2da..9f9d0ffd312f03a1d583a1ddebe12f1e8779f0da 100644 --- a/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift +++ b/Sources/SearchFeature/ViewModels/SearchLeftViewModel.swift @@ -3,7 +3,6 @@ import UIKit import Shared import Combine import XXModels -import Defaults import Countries import Integration import NetworkMonitor @@ -22,8 +21,6 @@ final class SearchLeftViewModel { @Dependency var session: SessionType @Dependency var networkMonitor: NetworkMonitoring - @KeyObject(.invitation, defaultValue: nil) var invitation: String? - var hudPublisher: AnyPublisher<HUDStatus, Never> { hudSubject.eraseToAnyPublisher() } @@ -36,12 +33,17 @@ final class SearchLeftViewModel { stateSubject.eraseToAnyPublisher() } + private var invitation: String? private var searchCancellables = Set<AnyCancellable>() private let successSubject = PassthroughSubject<Contact, Never>() private let hudSubject = CurrentValueSubject<HUDStatus, Never>(.none) private let stateSubject = CurrentValueSubject<SearchLeftViewState, Never>(.init()) private var networkCancellable = Set<AnyCancellable>() + init(_ invitation: String? = nil) { + self.invitation = invitation + } + func viewDidAppear() { if let pendingInvitation = invitation { invitation = nil