Tags / DB refactor

This commit is contained in:
Justin Mazzocchi 2020-08-30 12:50:34 -07:00
parent 510a6db11e
commit 2ca92ed098
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
4 changed files with 48 additions and 46 deletions

View file

@ -93,34 +93,8 @@ extension ContentDatabase {
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
func statusesObservation(timeline: Timeline) -> AnyPublisher<[Status], Error> { func statusesObservation(collection: StatusCollection) -> AnyPublisher<[Status], Error> {
ValueObservation ValueObservation.tracking(collection.fetch)
.tracking(timeline.statuses
.including(required: StoredStatus.account)
.including(optional: StoredStatus.reblogAccount)
.including(optional: StoredStatus.reblog)
.asRequest(of: StatusResult.self)
.fetchAll)
.removeDuplicates()
.publisher(in: databaseQueue)
.map { $0.map(Status.init(statusResult:)) }
.eraseToAnyPublisher()
}
func statusesObservation(collection: TransientStatusCollection) -> AnyPublisher<[Status], Error> {
ValueObservation.tracking {
try StatusResult.fetchAll(
$0,
StoredStatus.filter(
try collection
.elements
.fetchAll($0)
.map(\.statusId)
.contains(Column("id")))
.including(required: StoredStatus.account)
.including(optional: StoredStatus.reblogAccount)
.including(optional: StoredStatus.reblog))
}
.removeDuplicates() .removeDuplicates()
.publisher(in: databaseQueue) .publisher(in: databaseQueue)
.map { $0.map(Status.init(statusResult:)) } .map { $0.map(Status.init(statusResult:)) }
@ -136,13 +110,6 @@ extension ContentDatabase {
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
func filtersObservation() -> AnyPublisher<[Filter], Error> {
ValueObservation.tracking(Filter.fetchAll)
.removeDuplicates()
.publisher(in: databaseQueue)
.eraseToAnyPublisher()
}
func activeFiltersObservation(date: Date, context: Filter.Context? = nil) -> AnyPublisher<[Filter], Error> { func activeFiltersObservation(date: Date, context: Filter.Context? = nil) -> AnyPublisher<[Filter], Error> {
ValueObservation.tracking(Filter.filter(Column("expiresAt") == nil || Column("expiresAt") > date).fetchAll) ValueObservation.tracking(Filter.filter(Column("expiresAt") == nil || Column("expiresAt") > date).fetchAll)
.removeDuplicates() .removeDuplicates()
@ -298,6 +265,7 @@ extension Account: TableRecord, FetchableRecord, PersistableRecord {
protocol StatusCollection: FetchableRecord, PersistableRecord { protocol StatusCollection: FetchableRecord, PersistableRecord {
var id: String { get } var id: String { get }
var fetch: (Database) throws -> [StatusResult] { get }
func joinRecord(status: Status) -> PersistableRecord func joinRecord(status: Status) -> PersistableRecord
} }
@ -315,15 +283,17 @@ extension Timeline: StatusCollection {
} }
init(row: Row) { init(row: Row) {
switch row[Columns.id] as String { switch (row[Columns.id] as String, row[Columns.listTitle] as String?) {
case Timeline.home.id: case (Timeline.home.id, _):
self = .home self = .home
case Timeline.local.id: case (Timeline.local.id, _):
self = .local self = .local
case Timeline.federated.id: case (Timeline.federated.id, _):
self = .federated self = .federated
case (let id, .some(let title)):
self = .list(MastodonList(id: id, title: title))
default: default:
self = .list(MastodonList(id: row[Columns.id], title: row[Columns.listTitle])) self = .tag(row[Columns.id])
} }
} }
@ -335,6 +305,15 @@ extension Timeline: StatusCollection {
} }
} }
var fetch: (Database) throws -> [StatusResult] {
statuses
.including(required: StoredStatus.account)
.including(optional: StoredStatus.reblogAccount)
.including(optional: StoredStatus.reblog)
.asRequest(of: StatusResult.self)
.fetchAll
}
func joinRecord(status: Status) -> PersistableRecord { func joinRecord(status: Status) -> PersistableRecord {
TimelineStatusJoin(timelineId: id, statusId: status.id) TimelineStatusJoin(timelineId: id, statusId: status.id)
} }
@ -374,6 +353,21 @@ private struct TransientStatusCollectionElement: Codable, TableRecord, Fetchable
} }
extension TransientStatusCollection: StatusCollection { extension TransientStatusCollection: StatusCollection {
var fetch: (Database) throws -> [StatusResult] {
{
try StatusResult.fetchAll(
$0,
StoredStatus.filter(
try elements
.fetchAll($0)
.map(\.statusId)
.contains(Column("id")))
.including(required: StoredStatus.account)
.including(optional: StoredStatus.reblogAccount)
.including(optional: StoredStatus.reblog))
}
}
func joinRecord(status: Status) -> PersistableRecord { func joinRecord(status: Status) -> PersistableRecord {
TransientStatusCollectionElement(transientStatusCollectionId: id, statusId: status.id) TransientStatusCollectionElement(transientStatusCollectionId: id, statusId: status.id)
} }
@ -489,11 +483,11 @@ extension StoredStatus: TableRecord, FetchableRecord, PersistableRecord {
} }
} }
private struct StatusResult: Codable, Hashable, FetchableRecord { struct StatusResult: Codable, Hashable, FetchableRecord {
let account: Account let account: Account
let status: StoredStatus fileprivate let status: StoredStatus
let reblogAccount: Account? let reblogAccount: Account?
let reblog: StoredStatus? fileprivate let reblog: StoredStatus?
} }
private extension Status { private extension Status {

View file

@ -7,6 +7,7 @@ enum Timeline: Hashable {
case local case local
case federated case federated
case list(MastodonList) case list(MastodonList)
case tag(String)
} }
extension Timeline { extension Timeline {
@ -22,6 +23,8 @@ extension Timeline {
return .public(local: false) return .public(local: false)
case let .list(list): case let .list(list):
return .list(id: list.id) return .list(id: list.id)
case let .tag(tag):
return .tag(tag)
} }
} }
} }
@ -37,6 +40,8 @@ extension Timeline: Identifiable {
return "federated" return "federated"
case let .list(list): case let .list(list):
return list.id return list.id
case let .tag(tag):
return "#" + tag
} }
} }
} }

View file

@ -14,7 +14,7 @@ struct TimelineService {
self.timeline = timeline self.timeline = timeline
self.networkClient = networkClient self.networkClient = networkClient
self.contentDatabase = contentDatabase self.contentDatabase = contentDatabase
statusSections = contentDatabase.statusesObservation(timeline: timeline) statusSections = contentDatabase.statusesObservation(collection: timeline)
.map { [$0] } .map { [$0] }
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
@ -46,7 +46,7 @@ private extension TimelineService {
switch timeline { switch timeline {
case .home, .list: case .home, .list:
return .home return .home
case .local, .federated: case .local, .federated, .tag:
return .public return .public
} }
} }

View file

@ -36,7 +36,7 @@ extension TabNavigationViewModel {
switch timeline { switch timeline {
case .home, .list: case .home, .list:
return identity.handle return identity.handle
case .local, .federated: case .local, .federated, .tag:
return identity.instance?.uri ?? "" return identity.instance?.uri ?? ""
} }
} }
@ -51,6 +51,8 @@ extension TabNavigationViewModel {
return NSLocalizedString("timelines.federated", comment: "") return NSLocalizedString("timelines.federated", comment: "")
case let .list(list): case let .list(list):
return list.title return list.title
case let .tag(tag):
return "#" + tag
} }
} }
@ -60,6 +62,7 @@ extension TabNavigationViewModel {
case .local: return "person.3" case .local: return "person.3"
case .federated: return "globe" case .federated: return "globe"
case .list: return "scroll" case .list: return "scroll"
case .tag: return "number"
} }
} }