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()
}
func statusesObservation(timeline: Timeline) -> AnyPublisher<[Status], Error> {
ValueObservation
.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))
}
func statusesObservation(collection: StatusCollection) -> AnyPublisher<[Status], Error> {
ValueObservation.tracking(collection.fetch)
.removeDuplicates()
.publisher(in: databaseQueue)
.map { $0.map(Status.init(statusResult:)) }
@ -136,13 +110,6 @@ extension ContentDatabase {
.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> {
ValueObservation.tracking(Filter.filter(Column("expiresAt") == nil || Column("expiresAt") > date).fetchAll)
.removeDuplicates()
@ -298,6 +265,7 @@ extension Account: TableRecord, FetchableRecord, PersistableRecord {
protocol StatusCollection: FetchableRecord, PersistableRecord {
var id: String { get }
var fetch: (Database) throws -> [StatusResult] { get }
func joinRecord(status: Status) -> PersistableRecord
}
@ -315,15 +283,17 @@ extension Timeline: StatusCollection {
}
init(row: Row) {
switch row[Columns.id] as String {
case Timeline.home.id:
switch (row[Columns.id] as String, row[Columns.listTitle] as String?) {
case (Timeline.home.id, _):
self = .home
case Timeline.local.id:
case (Timeline.local.id, _):
self = .local
case Timeline.federated.id:
case (Timeline.federated.id, _):
self = .federated
case (let id, .some(let title)):
self = .list(MastodonList(id: id, title: title))
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 {
TimelineStatusJoin(timelineId: id, statusId: status.id)
}
@ -374,6 +353,21 @@ private struct TransientStatusCollectionElement: Codable, TableRecord, Fetchable
}
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 {
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 status: StoredStatus
fileprivate let status: StoredStatus
let reblogAccount: Account?
let reblog: StoredStatus?
fileprivate let reblog: StoredStatus?
}
private extension Status {

View file

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

View file

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

View file

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