diff --git a/ServiceLayer/Sources/ServiceLayer/Services/InstanceURLService.swift b/ServiceLayer/Sources/ServiceLayer/Services/InstanceURLService.swift index 533d6ce..bef62cc 100644 --- a/ServiceLayer/Sources/ServiceLayer/Services/InstanceURLService.swift +++ b/ServiceLayer/Sources/ServiceLayer/Services/InstanceURLService.swift @@ -38,14 +38,12 @@ public extension InstanceURLService { return url } - func instance(url: URL) -> AnyPublisher { + func instance(url: URL) -> AnyPublisher { httpClient.request( MastodonAPITarget( baseURL: url, endpoint: InstanceEndpoint.instance, accessToken: nil)) - .map { $0 as Instance? } - .catch { _ in Just(nil) } .eraseToAnyPublisher() } diff --git a/ViewModels/Sources/ViewModels/AddIdentityViewModel.swift b/ViewModels/Sources/ViewModels/AddIdentityViewModel.swift index 7c220ed..98ac9f3 100644 --- a/ViewModels/Sources/ViewModels/AddIdentityViewModel.swift +++ b/ViewModels/Sources/ViewModels/AddIdentityViewModel.swift @@ -13,7 +13,8 @@ public final class AddIdentityViewModel: ObservableObject { @Published public var urlFieldText = "" @Published public var alertItem: AlertItem? @Published public private(set) var loading = false - @Published public private(set) var instanceAndURL: (Instance, URL)? + @Published public private(set) var url: URL? + @Published public private(set) var instance: Instance? @Published public private(set) var isPublicTimelineAvailable = false public let addedIdentityID: AnyPublisher @@ -26,32 +27,7 @@ public final class AddIdentityViewModel: ObservableObject { self.allIdentitiesService = allIdentitiesService self.instanceURLService = instanceURLService addedIdentityID = addedIdentityIDSubject.eraseToAnyPublisher() - - let url = $urlFieldText - .debounce(for: 0.5, scheduler: DispatchQueue.global()) - .removeDuplicates() - .map(instanceURLService.url(text:)) - .share() - - url.compactMap { $0 } - .flatMap(instanceURLService.instance(url:)) - .combineLatest(url) - .map { - if let instance = $0, let url = $1 { - return (instance, url) - } - - return nil - } - .receive(on: DispatchQueue.main) - .assign(to: &$instanceAndURL) - - url.compactMap { $0 } - .flatMap(instanceURLService.isPublicTimelineAvailable(url:)) - .combineLatest(url.map { $0 != nil }) - .map { $0 && $1 } - .receive(on: DispatchQueue.main) - .assign(to: &$isPublicTimelineAvailable) + setupURLObservation() } } @@ -76,6 +52,35 @@ public extension AddIdentityViewModel { } private extension AddIdentityViewModel { + func setupURLObservation() { + let url = $urlFieldText + .debounce(for: 0.5, scheduler: DispatchQueue.global()) + .removeDuplicates() + .map(instanceURLService.url(text:)) + .share() + + url.receive(on: DispatchQueue.main).assign(to: &$url) + + url.compactMap { $0 } + .flatMap(instanceURLService.isPublicTimelineAvailable(url:)) + .replaceError(with: false) + .receive(on: DispatchQueue.main) + .assign(to: &$isPublicTimelineAvailable) + + url.flatMap { [weak self] url -> AnyPublisher in + guard let self = self, let url = url else { + return Just(nil).eraseToAnyPublisher() + } + + return self.instanceURLService.instance(url: url) + .map { $0 as Instance? } + .replaceError(with: nil) + .eraseToAnyPublisher() + } + .receive(on: DispatchQueue.main) + .assign(to: &$instance) + } + func addIdentity(authenticated: Bool) { let identityID = UUID() diff --git a/Views/AddIdentityView.swift b/Views/AddIdentityView.swift index 1ba9352..4cd5d41 100644 --- a/Views/AddIdentityView.swift +++ b/Views/AddIdentityView.swift @@ -19,7 +19,7 @@ struct AddIdentityView: View { .autocapitalization(.none) .disableAutocorrection(true) .keyboardType(.URL) - if let (instance, _) = viewModel.instanceAndURL { + if let instance = viewModel.instance { VStack(alignment: .center) { KFImage(instance.thumbnail) .placeholder { @@ -45,7 +45,7 @@ struct AddIdentityView: View { } else { Button("add-identity.log-in", action: viewModel.logInTapped) - if let (instance, url) = viewModel.instanceAndURL, + if let instance = viewModel.instance, let url = viewModel.url, instance.registrations { ZStack { NavigationLink(