From a00cd6007672a1ecbcb36b362d5ff5c85bd2b695 Mon Sep 17 00:00:00 2001 From: jinsu kim Date: Thu, 5 Jan 2023 15:57:58 -0800 Subject: [PATCH] Remove duplicate function fetchUser(). --- .../Profile/RemoteProfileViewModel.swift | 42 +++++++++- Mastodon/Supporting Files/SceneDelegate.swift | 46 ++++------- .../Service/API/APIService+Account.swift | 31 ++++++++ .../Service/API/APIService+Thread.swift | 76 ------------------- 4 files changed, 84 insertions(+), 111 deletions(-) diff --git a/Mastodon/Scene/Profile/RemoteProfileViewModel.swift b/Mastodon/Scene/Profile/RemoteProfileViewModel.swift index 11a1bffcb..89ff03660 100644 --- a/Mastodon/Scene/Profile/RemoteProfileViewModel.swift +++ b/Mastodon/Scene/Profile/RemoteProfileViewModel.swift @@ -28,6 +28,7 @@ final class RemoteProfileViewModel: ProfileViewModel { ) } .retry(3) + .receive(on: DispatchQueue.main) .sink { completion in switch completion { case .failure(let error): @@ -46,9 +47,7 @@ final class RemoteProfileViewModel: ProfileViewModel { assertionFailure() return } - DispatchQueue.main.async { - self.user = mastodonUser - } + self.user = mastodonUser } .store(in: &disposeBag) } @@ -91,4 +90,41 @@ final class RemoteProfileViewModel: ProfileViewModel { } // end Task } + init(context: AppContext, authContext: AuthContext, acct: String) { + super.init(context: context, authContext: authContext, optionalMastodonUser: nil) + + let domain = authContext.mastodonAuthenticationBox.domain + let authorization = authContext.mastodonAuthenticationBox.userAuthorization + Just(acct) + .asyncMap { acct in + try await context.apiService.accountSearch( + domain: domain, + query: .init(acct: acct), + authorization: authorization + ) + } + .retry(3) + .receive(on: DispatchQueue.main) + .sink { completion in + switch completion { + case .failure(let error): + // TODO: handle error + os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: remote user %s fetch failed: %s", ((#file as NSString).lastPathComponent), #line, #function, acct, error.localizedDescription) + case .finished: + os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: remote user %s fetched", ((#file as NSString).lastPathComponent), #line, #function, acct) + } + } receiveValue: { [weak self] response in + guard let self = self else { return } + let managedObjectContext = context.managedObjectContext + let request = MastodonUser.sortedFetchRequest + request.fetchLimit = 1 + request.predicate = MastodonUser.predicate(domain: domain, id: response.value.id) + guard let mastodonUser = managedObjectContext.safeFetch(request).first else { + assertionFailure() + return + } + self.user = mastodonUser + } + .store(in: &disposeBag) + } } diff --git a/Mastodon/Supporting Files/SceneDelegate.swift b/Mastodon/Supporting Files/SceneDelegate.swift index 2c6e3bf50..382755c77 100644 --- a/Mastodon/Supporting Files/SceneDelegate.swift +++ b/Mastodon/Supporting Files/SceneDelegate.swift @@ -252,27 +252,17 @@ extension SceneDelegate { let components = url.pathComponents if components.count == 2 && components[0] == "/" { let addr = components[1] - let tokens = addr.components(separatedBy: "@") - if tokens.count != 2 { return } - let username = tokens[0] - let host = tokens[1] if let authContext = coordinator?.authContext { - Task { @MainActor in - guard let user = try await AppContext.shared.apiService.fetchUser( - username: username, - domain: host, - authenticationBox: authContext.mastodonAuthenticationBox - ) else { return } - - let profileViewModel = RemoteProfileViewModel(context: AppContext.shared, - authContext: authContext, - userID: user.id) - self.coordinator?.present( - scene: .profile(viewModel: profileViewModel), - from: nil, - transition: .show - ) - } + let profileViewModel = RemoteProfileViewModel( + context: AppContext.shared, + authContext: authContext, + acct: components[1] + ) + self.coordinator?.present( + scene: .profile(viewModel: profileViewModel), + from: nil, + transition: .show + ) } } case "status": @@ -280,19 +270,11 @@ extension SceneDelegate { if components.count == 2 && components[0] == "/" { let statusId = components[1] // View post from user - print("view status \(statusId)") if let authContext = coordinator?.authContext { - Task { - guard let thread = try await AppContext.shared.apiService.fetchThread( - statusID: statusId, - authenticationBox: authContext.mastodonAuthenticationBox - ) else { return } - - let threadViewModel = CachedThreadViewModel(context: AppContext.shared, - authContext: authContext, - status: thread) - coordinator?.present(scene: .thread(viewModel: threadViewModel), from: nil, transition: .show) - } + let threadViewModel = RemoteThreadViewModel(context: AppContext.shared, + authContext: authContext, + statusID: statusId) + coordinator?.present(scene: .thread(viewModel: threadViewModel), from: nil, transition: .show) } } default: diff --git a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Account.swift b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Account.swift index d68984587..34d398633 100644 --- a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Account.swift +++ b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Account.swift @@ -240,3 +240,34 @@ extension APIService { return result } } + +extension APIService { + public func accountSearch( + domain: String, + query: Mastodon.API.Account.AccountLookupQuery, + authorization: Mastodon.API.OAuth.Authorization + ) async throws -> Mastodon.Response.Content { + let response = try await Mastodon.API.Account.lookupAccount( + session: session, + domain: domain, + query: query, + authorization: authorization + ).singleOutput() + + // user + let managedObjectContext = self.backgroundManagedObjectContext + try await managedObjectContext.performChanges { + _ = Persistence.MastodonUser.createOrMerge( + in: managedObjectContext, + context: Persistence.MastodonUser.PersistContext( + domain: domain, + entity: response.value, + cache: nil, + networkDate: response.networkDate + ) + ) + } + + return response + } +} diff --git a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Thread.swift b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Thread.swift index d655a7e5c..f1b94376e 100644 --- a/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Thread.swift +++ b/MastodonSDK/Sources/MastodonCore/Service/API/APIService+Thread.swift @@ -50,80 +50,4 @@ extension APIService { return response } // end func - - public func fetchThread( - statusID: Mastodon.Entity.Status.ID, - authenticationBox: MastodonAuthenticationBox - ) async throws -> Status? { - let domain = authenticationBox.domain - let authorization = authenticationBox.userAuthorization - let managedObjectContext = self.backgroundManagedObjectContext - - let responseOne = try await Mastodon.API.Statuses.status( - session: session, - domain: domain, - statusID: statusID, - authorization: authorization - ).singleOutput() - - try await managedObjectContext.performChanges { - let me = authenticationBox.authenticationRecord.object(in: managedObjectContext)?.user - _ = Persistence.Status.createOrMerge( - in: managedObjectContext, - context: Persistence.Status.PersistContext( - domain: domain, - entity: responseOne.value, - me: me, - statusCache: nil, - userCache: nil, - networkDate: responseOne.networkDate - ) - ) - } - -// let responseTwo = try await Mastodon.API.Statuses.statusContext( -// session: session, -// domain: domain, -// statusID: statusID, -// authorization: authorization -// ).singleOutput() -// -// try await managedObjectContext.performChanges { -// let me = authenticationBox.authenticationRecord.object(in: managedObjectContext)?.user -// let value = responseTwo.value.ancestors + responseTwo.value.descendants -// -// for entity in value { -// _ = Persistence.Status.createOrMerge( -// in: managedObjectContext, -// context: Persistence.Status.PersistContext( -// domain: domain, -// entity: entity, -// me: me, -// statusCache: nil, -// userCache: nil, -// networkDate: responseTwo.networkDate -// ) -// ) -// } -// } - - var result: Status? - try await managedObjectContext.perform { - let me = authenticationBox.authenticationRecord.object(in: managedObjectContext)?.user - - if let status = Persistence.Status.fetch(in: managedObjectContext, - context: Persistence.Status.PersistContext( - domain: domain, - entity: responseOne.value, - me: me, - statusCache: nil, - userCache: nil, - networkDate: responseOne.networkDate - )) { - result = status - } - } - - return result - } }