mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-22 00:01:00 +00:00
Fix interacgtion with statuses in search results
This commit is contained in:
parent
6b27cd1579
commit
a3491cec85
3 changed files with 59 additions and 32 deletions
|
@ -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(
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in a new issue