Featured tags data

This commit is contained in:
Justin Mazzocchi 2021-01-17 23:17:45 -08:00
parent 2eddf8c558
commit a51d9aafae
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
13 changed files with 142 additions and 3 deletions

View file

@ -56,6 +56,7 @@ extension AccountRecord {
static let moved = belongsTo(AccountRecord.self)
static let relationship = hasOne(Relationship.self)
static let identityProofs = hasMany(IdentityProofRecord.self)
static let featuredTags = hasMany(FeaturedTagRecord.self)
static let pinnedStatusJoins = hasMany(AccountPinnedStatusJoin.self)
.order(AccountPinnedStatusJoin.Columns.index)
static let pinnedStatuses = hasMany(

View file

@ -57,6 +57,15 @@ extension ContentDatabase {
t.primaryKey(["accountId", "provider"], onConflict: .replace)
}
try db.create(table: "featuredTagRecord") { t in
t.column("id", .text).primaryKey(onConflict: .replace)
t.column("name", .text).notNull()
t.column("url", .text).notNull()
t.column("statusesCount", .integer).notNull()
t.column("lastStatusAt", .date).notNull()
t.column("accountId", .text).notNull().references("accountRecord", onDelete: .cascade)
}
try db.create(table: "statusRecord") { t in
t.column("id", .text).primaryKey(onConflict: .replace)
t.column("uri", .text).notNull()

View file

@ -284,6 +284,23 @@ public extension ContentDatabase {
.eraseToAnyPublisher()
}
func insert(featuredTags: [FeaturedTag], id: Account.Id) -> AnyPublisher<Never, Error> {
databaseWriter.writePublisher {
for featuredTag in featuredTags {
try FeaturedTagRecord(
id: featuredTag.id,
name: featuredTag.name,
url: featuredTag.url,
statusesCount: featuredTag.statusesCount,
lastStatusAt: featuredTag.lastStatusAt,
accountId: id)
.save($0)
}
}
.ignoreOutput()
.eraseToAnyPublisher()
}
func insert(relationships: [Relationship]) -> AnyPublisher<Never, Error> {
databaseWriter.writePublisher {
for relationship in relationships {

View file

@ -0,0 +1,25 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Foundation
import GRDB
import Mastodon
struct FeaturedTagRecord: ContentDatabaseRecord, Hashable {
let id: FeaturedTag.Id
let name: String
let url: URL
let statusesCount: Int
let lastStatusAt: Date
let accountId: Account.Id
}
extension FeaturedTagRecord {
enum Columns {
static let id = Column(CodingKeys.id)
static let name = Column(CodingKeys.name)
static let url = Column(CodingKeys.url)
static let statusesCount = Column(CodingKeys.statusesCount)
static let lastStatusAt = Column(CodingKeys.lastStatusAt)
static let accountId = Column(CodingKeys.accountId)
}
}

View file

@ -8,6 +8,7 @@ struct ProfileInfo: Codable, Hashable, FetchableRecord {
let accountInfo: AccountInfo
let relationship: Relationship?
let identityProofRecords: [IdentityProofRecord]
let featuredTagRecords: [FeaturedTagRecord]
}
extension ProfileInfo {
@ -15,6 +16,7 @@ extension ProfileInfo {
AccountInfo.addingIncludes(request)
.including(optional: AccountRecord.relationship.forKey(CodingKeys.relationship))
.including(all: AccountRecord.identityProofs.forKey(CodingKeys.identityProofRecords))
.including(all: AccountRecord.featuredTags.forKey(CodingKeys.featuredTagRecords))
}
static func request(_ request: QueryInterfaceRequest<AccountRecord>) -> QueryInterfaceRequest<Self> {

View file

@ -7,11 +7,13 @@ public struct Profile: Codable, Hashable {
public let account: Account
public let relationship: Relationship?
public let identityProofs: [IdentityProof]
public let featuredTags: [FeaturedTag]
public init(account: Account) {
self.account = account
self.relationship = nil
self.identityProofs = []
self.featuredTags = []
}
}
@ -20,5 +22,6 @@ extension Profile {
account = Account(info: info.accountInfo)
relationship = info.relationship
identityProofs = info.identityProofRecords.map(IdentityProof.init(record:))
featuredTags = info.featuredTagRecords.map(FeaturedTag.init(record:))
}
}

View file

@ -0,0 +1,16 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Foundation
import GRDB
import Mastodon
extension FeaturedTag {
init(record: FeaturedTagRecord) {
self.init(
id: record.id,
name: record.name,
url: record.url,
statusesCount: record.statusesCount,
lastStatusAt: record.lastStatusAt)
}
}

View file

@ -0,0 +1,23 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Foundation
public struct FeaturedTag: Codable, Hashable {
public let id: Id
public let name: String
public let url: URL
public let statusesCount: Int
public let lastStatusAt: Date
public init(id: FeaturedTag.Id, name: String, url: URL, statusesCount: Int, lastStatusAt: Date) {
self.id = id
self.name = name
self.url = url
self.statusesCount = statusesCount
self.lastStatusAt = lastStatusAt
}
}
public extension FeaturedTag {
typealias Id = String
}

View file

@ -0,0 +1,35 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Foundation
import HTTP
import Mastodon
public enum FeaturedTagsEndpoint {
case featuredTags(id: Account.Id)
}
extension FeaturedTagsEndpoint: Endpoint {
public typealias ResultType = [FeaturedTag]
public var context: [String] {
switch self {
case .featuredTags:
return defaultContext + ["accounts"]
}
}
public var pathComponentsInContext: [String] {
switch self {
case let .featuredTags(id):
return [id, "featured_tags"]
}
}
public var method: HTTPMethod {
switch self {
case .featuredTags:
return .get
}
}
}

View file

@ -10,6 +10,7 @@ public struct AccountService {
public let account: Account
public let relationship: Relationship?
public let identityProofs: [IdentityProof]
public let featuredTags: [FeaturedTag]
public let navigationService: NavigationService
private let mastodonAPIClient: MastodonAPIClient
@ -18,11 +19,13 @@ public struct AccountService {
public init(account: Account,
relationship: Relationship? = nil,
identityProofs: [IdentityProof] = [],
featuredTags: [FeaturedTag] = [],
mastodonAPIClient: MastodonAPIClient,
contentDatabase: ContentDatabase) {
self.account = account
self.relationship = relationship
self.identityProofs = identityProofs
self.featuredTags = featuredTags
navigationService = NavigationService(mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase)
self.mastodonAPIClient = mastodonAPIClient
self.contentDatabase = contentDatabase

View file

@ -103,7 +103,6 @@ public extension EmojiPickerService {
promise(.failure(error))
}
}
.print()
.eraseToAnyPublisher()
}

View file

@ -49,6 +49,7 @@ public struct ProfileService {
account: $0.account,
relationship: $0.relationship,
identityProofs: $0.identityProofs,
featuredTags: $0.featuredTags,
mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase)
}
@ -65,14 +66,17 @@ public extension ProfileService {
}
func fetchProfile() -> AnyPublisher<Never, Error> {
Publishers.Merge3(
Publishers.Merge4(
mastodonAPIClient.request(AccountEndpoint.accounts(id: id))
.flatMap { contentDatabase.insert(accounts: [$0]) },
mastodonAPIClient.request(RelationshipsEndpoint.relationships(ids: [id]))
.flatMap { contentDatabase.insert(relationships: $0) },
mastodonAPIClient.request(IdentityProofsEndpoint.identityProofs(id: id))
.catch { _ in Empty() }
.flatMap { contentDatabase.insert(identityProofs: $0, id: id) })
.flatMap { contentDatabase.insert(identityProofs: $0, id: id) },
mastodonAPIClient.request(FeaturedTagsEndpoint.featuredTags(id: id))
.catch { _ in Empty() }
.flatMap { contentDatabase.insert(featuredTags: $0, id: id) })
.eraseToAnyPublisher()
}

View file

@ -44,6 +44,8 @@ public extension AccountViewModel {
var identityProofs: [IdentityProof] { accountService.identityProofs }
var featuredTags: [FeaturedTag] { accountService.featuredTags }
var fields: [Account.Field] { accountService.account.fields }
var note: NSAttributedString { accountService.account.note.attributed }