Fix interacgtion with statuses in search results

This commit is contained in:
Justin Mazzocchi 2021-01-23 23:21:35 -08:00
parent 6b27cd1579
commit a3491cec85
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
3 changed files with 59 additions and 32 deletions

View file

@ -425,37 +425,17 @@ public extension ContentDatabase {
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
func process(results: Results) -> AnyPublisher<[CollectionSection], Error> { func insert(results: Results) -> AnyPublisher<Never, Error> {
databaseWriter.writePublisher { db -> ([StatusInfo], [Status.Id]) in databaseWriter.writePublisher {
for account in results.accounts { for account in results.accounts {
try account.save(db) try account.save($0)
} }
for status in results.statuses { for status in results.statuses {
try status.save(db) try status.save($0)
} }
let ids = results.statuses.map(\.id)
let statusInfos = try StatusInfo.request(
StatusRecord.filter(ids.contains(StatusRecord.Columns.id)))
.fetchAll(db)
return (statusInfos, ids)
}
.map { statusInfos, ids -> [CollectionSection] in
[
.init(items: results.accounts.map(CollectionItem.account), titleLocalizedStringKey: "search.accounts"),
.init(items: statusInfos
.sorted { ids.firstIndex(of: $0.record.id) ?? 0 < ids.firstIndex(of: $1.record.id) ?? 0 }
.map {
.status(.init(info: $0),
.init(showContentToggled: $0.showContentToggled,
showAttachmentsToggled: $0.showAttachmentsToggled))
},
titleLocalizedStringKey: "search.statuses"),
.init(items: results.hashtags.map(CollectionItem.tag), titleLocalizedStringKey: "search.tags")
]
} }
.ignoreOutput()
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
@ -528,6 +508,52 @@ public extension ContentDatabase {
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
func publisher(results: Results) -> AnyPublisher<[CollectionSection], Error> {
let accountIds = results.accounts.map(\.id)
let statusIds = results.statuses.map(\.id)
let accountsPublisher = ValueObservation.tracking(
AccountInfo.request(
AccountRecord.filter(accountIds.contains(AccountRecord.Columns.id)))
.fetchAll)
.removeDuplicates()
.publisher(in: databaseWriter)
.map {
$0.sorted {
accountIds.firstIndex(of: $0.record.id) ?? 0
< accountIds.firstIndex(of: $1.record.id) ?? 0
}
.map { CollectionItem.account(.init(info: $0)) }
}
let statusesPublisher = ValueObservation.tracking(
StatusInfo.request(
StatusRecord.filter(statusIds.contains(StatusRecord.Columns.id)))
.fetchAll)
.removeDuplicates()
.publisher(in: databaseWriter)
.map {
$0.sorted {
statusIds.firstIndex(of: $0.record.id) ?? 0
< statusIds.firstIndex(of: $1.record.id) ?? 0
}
.map {
CollectionItem.status(
.init(info: $0),
.init(showContentToggled: $0.showContentToggled,
showAttachmentsToggled: $0.showAttachmentsToggled))
}
}
return accountsPublisher.combineLatest(statusesPublisher)
.map { accounts, statuses in
[.init(items: accounts, titleLocalizedStringKey: "search.accounts"),
.init(items: statuses, titleLocalizedStringKey: "search.statuses"),
.init(items: results.hashtags.map(CollectionItem.tag), titleLocalizedStringKey: "search.tags")]
}
.eraseToAnyPublisher()
}
func notificationsPublisher() -> AnyPublisher<[CollectionSection], Error> { func notificationsPublisher() -> AnyPublisher<[CollectionSection], Error> {
ValueObservation.tracking( ValueObservation.tracking(
NotificationInfo.request( NotificationInfo.request(

View file

@ -14,14 +14,14 @@ public struct SearchService {
private let mastodonAPIClient: MastodonAPIClient private let mastodonAPIClient: MastodonAPIClient
private let contentDatabase: ContentDatabase private let contentDatabase: ContentDatabase
private let nextPageMaxIdSubject = PassthroughSubject<String, Never>() private let nextPageMaxIdSubject = PassthroughSubject<String, Never>()
private let sectionsSubject = PassthroughSubject<[CollectionSection], Error>() private let resultsSubject = PassthroughSubject<Results, Error>()
init(mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) { init(mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) {
self.mastodonAPIClient = mastodonAPIClient self.mastodonAPIClient = mastodonAPIClient
self.contentDatabase = contentDatabase self.contentDatabase = contentDatabase
nextPageMaxId = nextPageMaxIdSubject.eraseToAnyPublisher() nextPageMaxId = nextPageMaxIdSubject.eraseToAnyPublisher()
navigationService = NavigationService(mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) navigationService = NavigationService(mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase)
sections = sectionsSubject.eraseToAnyPublisher() sections = resultsSubject.flatMap(contentDatabase.publisher(results:)).eraseToAnyPublisher()
} }
} }
@ -30,9 +30,8 @@ extension SearchService: CollectionService {
guard let search = search else { return Empty().eraseToAnyPublisher() } guard let search = search else { return Empty().eraseToAnyPublisher() }
return mastodonAPIClient.request(ResultsEndpoint.search(search)) return mastodonAPIClient.request(ResultsEndpoint.search(search))
.flatMap(contentDatabase.process(results:)) .handleEvents(receiveOutput: resultsSubject.send)
.handleEvents(receiveOutput: sectionsSubject.send) .flatMap(contentDatabase.insert(results:))
.ignoreOutput()
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
} }

View file

@ -31,12 +31,14 @@ final class LineChartView: UIView {
guard valueCount > 0, let maxValue = values.max() else { return } guard valueCount > 0, let maxValue = values.max() else { return }
let inset = Self.lineWidth / 2
for (index, value) in values.enumerated() { for (index, value) in values.enumerated() {
let x = CGFloat(index) / CGFloat(valueCount) * rect.width let x = CGFloat(index) / CGFloat(valueCount) * rect.width
let y = rect.height - CGFloat(value) / max(CGFloat(maxValue), CGFloat(0).nextUp) * rect.height let y = rect.height - CGFloat(value) / max(CGFloat(maxValue), CGFloat(0).nextUp) * rect.height
let point = CGPoint( let point = CGPoint(
x: min(max(x, Self.lineWidth / 2), rect.width - Self.lineWidth / 2), x: min(max(x, inset), rect.width - inset),
y: min(max(y, Self.lineWidth / 2), rect.height - Self.lineWidth / 2)) y: min(max(y, inset), rect.height - inset))
if index > 0 { if index > 0 {
path.addLine(to: point) path.addLine(to: point)