Refactoring

This commit is contained in:
Justin Mazzocchi 2020-10-05 00:04:15 -07:00
parent f3e1baecaa
commit a07d25c80b
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
8 changed files with 96 additions and 101 deletions

View file

@ -0,0 +1,38 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Combine
import DB
import Foundation
import Mastodon
import MastodonAPI
public struct ContextService: CollectionService {
public let sections: AnyPublisher<[[CollectionItem]], Error>
public let navigationService: NavigationService
public let nextPageMaxIDs: AnyPublisher<String?, Never> = Empty().eraseToAnyPublisher()
public let title: String? = nil
public var contextParentID: String? { statusID }
private let statusID: String
private let mastodonAPIClient: MastodonAPIClient
private let contentDatabase: ContentDatabase
init(statusID: String, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) {
self.statusID = statusID
self.mastodonAPIClient = mastodonAPIClient
self.contentDatabase = contentDatabase
sections = contentDatabase.contextObservation(parentID: statusID)
navigationService = NavigationService(
status: nil,
mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase)
}
public func request(maxID: String?, minID: String?) -> AnyPublisher<Never, Error> {
mastodonAPIClient.request(StatusEndpoint.status(id: statusID))
.flatMap(contentDatabase.insert(status:))
.merge(with: mastodonAPIClient.request(ContextEndpoint.context(id: statusID))
.flatMap { contentDatabase.insert(context: $0, parentID: statusID) })
.eraseToAnyPublisher()
}
}

View file

@ -177,8 +177,8 @@ public extension IdentityService {
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
func service(timeline: Timeline) -> StatusListService { func service(timeline: Timeline) -> TimelineService {
StatusListService(timeline: timeline, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) TimelineService(timeline: timeline, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase)
} }
} }

View file

@ -31,7 +31,7 @@ public extension NavigationService {
if let tag = tag(url: url) { if let tag = tag(url: url) {
return Just( return Just(
.collection( .collection(
StatusListService( TimelineService(
timeline: .tag(tag), timeline: .tag(tag),
mastodonAPIClient: mastodonAPIClient, mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase))) contentDatabase: contentDatabase)))
@ -39,13 +39,7 @@ public extension NavigationService {
} else if let accountID = accountID(url: url) { } else if let accountID = accountID(url: url) {
return Just(.profile(profileService(id: accountID))).eraseToAnyPublisher() return Just(.profile(profileService(id: accountID))).eraseToAnyPublisher()
} else if mastodonAPIClient.instanceURL.host == url.host, let statusID = url.statusID { } else if mastodonAPIClient.instanceURL.host == url.host, let statusID = url.statusID {
return Just( return Just(.collection(contextService(id: statusID))).eraseToAnyPublisher()
.collection(
StatusListService(
statusID: statusID,
mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase)))
.eraseToAnyPublisher()
} }
if url.shouldWebfinger { if url.shouldWebfinger {
@ -55,8 +49,8 @@ public extension NavigationService {
} }
} }
func contextStatusListService(id: String) -> StatusListService { func contextService(id: String) -> ContextService {
StatusListService(statusID: id, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) ContextService(statusID: id, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase)
} }
func profileService(id: String) -> ProfileService { func profileService(id: String) -> ProfileService {
@ -113,18 +107,14 @@ private extension NavigationService {
.map { results -> Navigation in .map { results -> Navigation in
if let tag = results.hashtags.first { if let tag = results.hashtags.first {
return .collection( return .collection(
StatusListService( TimelineService(
timeline: .tag(tag.name), timeline: .tag(tag.name),
mastodonAPIClient: mastodonAPIClient, mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase)) contentDatabase: contentDatabase))
} else if let account = results.accounts.first { } else if let account = results.accounts.first {
return .profile(profileService(account: account)) return .profile(profileService(account: account))
} else if let status = results.statuses.first { } else if let status = results.statuses.first {
return .collection( return .collection(contextService(id: status.id))
StatusListService(
statusID: status.id,
mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase))
} else { } else {
return .url(url) return .url(url)
} }

View file

@ -50,8 +50,8 @@ public struct ProfileService {
} }
public extension ProfileService { public extension ProfileService {
func statusListService(profileCollection: ProfileCollection) -> StatusListService { func timelineService(profileCollection: ProfileCollection) -> TimelineService {
StatusListService( TimelineService(
timeline: .profile(accountId: accountID, profileCollection: profileCollection), timeline: .profile(accountId: accountID, profileCollection: profileCollection),
mastodonAPIClient: mastodonAPIClient, mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase) contentDatabase: contentDatabase)

View file

@ -1,78 +0,0 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Combine
import DB
import Foundation
import Mastodon
import MastodonAPI
public struct StatusListService: CollectionService {
public let sections: AnyPublisher<[[CollectionItem]], Error>
public let nextPageMaxIDs: AnyPublisher<String?, Never>
public let contextParentID: String?
public let title: String?
public let navigationService: NavigationService
private let filterContext: Filter.Context
private let mastodonAPIClient: MastodonAPIClient
private let contentDatabase: ContentDatabase
private let requestClosure: (_ maxID: String?, _ minID: String?) -> AnyPublisher<Never, Error>
}
extension StatusListService {
init(timeline: Timeline, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) {
var title: String?
if case let .tag(tag) = timeline {
title = "#".appending(tag)
}
let nextPageMaxIDsSubject = PassthroughSubject<String?, Never>()
self.init(sections: contentDatabase.observation(timeline: timeline),
nextPageMaxIDs: nextPageMaxIDsSubject.eraseToAnyPublisher(),
contextParentID: nil,
title: title,
navigationService: NavigationService(
status: nil,
mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase),
filterContext: timeline.filterContext,
mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase) { maxID, minID in
mastodonAPIClient.pagedRequest(timeline.endpoint, maxID: maxID, minID: minID)
.handleEvents(receiveOutput: { nextPageMaxIDsSubject.send($0.info.maxID) })
.flatMap { contentDatabase.insert(statuses: $0.result, timeline: timeline) }
.eraseToAnyPublisher()
}
}
init(statusID: String, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) {
self.init(sections: contentDatabase.contextObservation(parentID: statusID),
nextPageMaxIDs: Empty().eraseToAnyPublisher(),
contextParentID: statusID,
title: nil,
navigationService: NavigationService(
status: nil,
mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase),
filterContext: .thread,
mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase) { _, _ in
Publishers.Merge(
mastodonAPIClient.request(StatusEndpoint.status(id: statusID))
.flatMap(contentDatabase.insert(status:))
.eraseToAnyPublisher(),
mastodonAPIClient.request(ContextEndpoint.context(id: statusID))
.flatMap { contentDatabase.insert(context: $0, parentID: statusID) }
.eraseToAnyPublisher())
.eraseToAnyPublisher()
}
}
}
public extension StatusListService {
func request(maxID: String?, minID: String?) -> AnyPublisher<Never, Error> {
requestClosure(maxID, minID)
}
}

View file

@ -0,0 +1,45 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Combine
import DB
import Foundation
import Mastodon
import MastodonAPI
public struct TimelineService: CollectionService {
public let sections: AnyPublisher<[[CollectionItem]], Error>
public let navigationService: NavigationService
public let nextPageMaxIDs: AnyPublisher<String?, Never>
public let title: String?
public let contextParentID: String? = nil
private let timeline: Timeline
private let mastodonAPIClient: MastodonAPIClient
private let contentDatabase: ContentDatabase
private let nextPageMaxIDsSubject = PassthroughSubject<String?, Never>()
init(timeline: Timeline, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) {
self.timeline = timeline
self.mastodonAPIClient = mastodonAPIClient
self.contentDatabase = contentDatabase
sections = contentDatabase.observation(timeline: timeline)
navigationService = NavigationService(
status: nil,
mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase)
nextPageMaxIDs = nextPageMaxIDsSubject.eraseToAnyPublisher()
if case let .tag(tag) = timeline {
title = "#".appending(tag)
} else {
title = nil
}
}
public func request(maxID: String?, minID: String?) -> AnyPublisher<Never, Error> {
mastodonAPIClient.pagedRequest(timeline.endpoint, maxID: maxID, minID: minID)
.handleEvents(receiveOutput: { nextPageMaxIDsSubject.send($0.info.maxID) })
.flatMap { contentDatabase.insert(statuses: $0.result, timeline: timeline) }
.eraseToAnyPublisher()
}
}

View file

@ -66,7 +66,7 @@ extension ListViewModel: CollectionViewModel {
ListViewModel( ListViewModel(
collectionService: collectionService collectionService: collectionService
.navigationService .navigationService
.contextStatusListService(id: configuration.status.displayStatus.id)))) .contextService(id: configuration.status.displayStatus.id))))
case .loadMore: case .loadMore:
loadMoreViewModel(item: identifier)?.loadMore() loadMoreViewModel(item: identifier)?.loadMore()
case let .account(account): case let .account(account):

View file

@ -18,7 +18,7 @@ final public class ProfileViewModel {
self.profileService = profileService self.profileService = profileService
collectionViewModel = CurrentValueSubject( collectionViewModel = CurrentValueSubject(
ListViewModel(collectionService: profileService.statusListService(profileCollection: .statuses))) ListViewModel(collectionService: profileService.timelineService(profileCollection: .statuses)))
profileService.accountServicePublisher profileService.accountServicePublisher
.map(AccountViewModel.init(accountService:)) .map(AccountViewModel.init(accountService:))
@ -26,7 +26,7 @@ final public class ProfileViewModel {
.assign(to: &$accountViewModel) .assign(to: &$accountViewModel)
$collection.dropFirst() $collection.dropFirst()
.map(profileService.statusListService(profileCollection:)) .map(profileService.timelineService(profileCollection:))
.map(ListViewModel.init(collectionService:)) .map(ListViewModel.init(collectionService:))
.sink { [weak self] in .sink { [weak self] in
guard let self = self else { return } guard let self = self else { return }