This commit is contained in:
Justin Mazzocchi 2021-02-07 21:24:06 -08:00
parent f1e3f1a7fa
commit e420c6b934
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
7 changed files with 53 additions and 16 deletions

View file

@ -0,0 +1,20 @@
// Copyright © 2021 Metabolist. All rights reserved.
import Foundation
import GRDB
import Mastodon
struct AccountAndRelationshipInfo: Codable, Hashable, FetchableRecord {
let accountInfo: AccountInfo
let relationship: Relationship?
}
extension AccountAndRelationshipInfo {
static func addingIncludes<T: DerivableRequest>(_ request: T) -> T where T.RowDecoder == AccountRecord {
AccountInfo.addingIncludes(request).including(optional: AccountRecord.relationship)
}
static func request(_ request: QueryInterfaceRequest<AccountRecord>) -> QueryInterfaceRequest<Self> {
addingIncludes(request).asRequest(of: self)
}
}

View file

@ -6,12 +6,13 @@ import Mastodon
struct AccountListItemsInfo: Codable, Hashable, FetchableRecord { struct AccountListItemsInfo: Codable, Hashable, FetchableRecord {
let accountList: AccountList let accountList: AccountList
let accountInfos: [AccountInfo] let accountAndRelationshipInfos: [AccountAndRelationshipInfo]
} }
extension AccountListItemsInfo { extension AccountListItemsInfo {
static func addingIncludes<T: DerivableRequest>(_ request: T) -> T where T.RowDecoder == AccountList { static func addingIncludes<T: DerivableRequest>(_ request: T) -> T where T.RowDecoder == AccountList {
request.including(all: AccountInfo.addingIncludes(AccountList.accounts).forKey(CodingKeys.accountInfos)) request.including(all: AccountAndRelationshipInfo.addingIncludes(AccountList.accounts)
.forKey(CodingKeys.accountAndRelationshipInfos))
} }
static func request(_ request: QueryInterfaceRequest<AccountList>) -> QueryInterfaceRequest<Self> { static func request(_ request: QueryInterfaceRequest<AccountList>) -> QueryInterfaceRequest<Self> {

View file

@ -528,7 +528,11 @@ public extension ContentDatabase {
AccountListItemsInfo.request(AccountList.filter(AccountList.Columns.id == id)).fetchOne) AccountListItemsInfo.request(AccountList.filter(AccountList.Columns.id == id)).fetchOne)
.removeDuplicates() .removeDuplicates()
.publisher(in: databaseWriter) .publisher(in: databaseWriter)
.map { $0?.accountInfos.map { CollectionItem.account(.init(info: $0), configuration, nil) } } .map {
$0?.accountAndRelationshipInfos.map {
CollectionItem.account(.init(info: $0.accountInfo), configuration, $0.relationship)
}
}
.replaceNil(with: []) .replaceNil(with: [])
.map { [CollectionSection(items: $0)] } .map { [CollectionSection(items: $0)] }
.eraseToAnyPublisher() .eraseToAnyPublisher()
@ -574,17 +578,17 @@ public extension ContentDatabase {
let statusIds = results.statuses.map(\.id) let statusIds = results.statuses.map(\.id)
let accountsPublisher = ValueObservation.tracking( let accountsPublisher = ValueObservation.tracking(
AccountInfo.request( AccountAndRelationshipInfo.request(
AccountRecord.filter(accountIds.contains(AccountRecord.Columns.id))) AccountRecord.filter(accountIds.contains(AccountRecord.Columns.id)))
.fetchAll) .fetchAll)
.removeDuplicates() .removeDuplicates()
.publisher(in: databaseWriter) .publisher(in: databaseWriter)
.map { infos -> [CollectionItem] in .map { infos -> [CollectionItem] in
var accounts = infos.sorted { var accounts = infos.sorted {
accountIds.firstIndex(of: $0.record.id) ?? 0 accountIds.firstIndex(of: $0.accountInfo.record.id) ?? 0
< accountIds.firstIndex(of: $1.record.id) ?? 0 < accountIds.firstIndex(of: $1.accountInfo.record.id) ?? 0
} }
.map { CollectionItem.account(.init(info: $0), .withoutNote, nil) } // TODO: revisit .map { CollectionItem.account(.init(info: $0.accountInfo), .withoutNote, $0.relationship) }
if let limit = limit, accounts.count >= limit { if let limit = limit, accounts.count >= limit {
accounts.append(.moreResults(.init(scope: .accounts))) accounts.append(.moreResults(.init(scope: .accounts)))

View file

@ -9,9 +9,9 @@ public struct Profile: Codable, Hashable {
public let identityProofs: [IdentityProof] public let identityProofs: [IdentityProof]
public let featuredTags: [FeaturedTag] public let featuredTags: [FeaturedTag]
public init(account: Account) { public init(account: Account, relationship: Relationship?) {
self.account = account self.account = account
self.relationship = nil self.relationship = relationship
self.identityProofs = [] self.identityProofs = []
self.featuredTags = [] self.featuredTags = []
} }

View file

@ -59,8 +59,11 @@ public extension NavigationService {
ProfileService(id: id, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) ProfileService(id: id, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase)
} }
func profileService(account: Account) -> ProfileService { func profileService(account: Account, relationship: Relationship? = nil) -> ProfileService {
ProfileService(account: account, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) ProfileService(account: account,
relationship: relationship,
mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase)
} }
func statusService(status: Status) -> StatusService { func statusService(status: Status) -> StatusService {

View file

@ -13,21 +13,30 @@ public struct ProfileService {
private let mastodonAPIClient: MastodonAPIClient private let mastodonAPIClient: MastodonAPIClient
private let contentDatabase: ContentDatabase private let contentDatabase: ContentDatabase
init(account: Account, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) { init(account: Account,
relationship: Relationship?,
mastodonAPIClient: MastodonAPIClient,
contentDatabase: ContentDatabase) {
self.init( self.init(
id: account.id, id: account.id,
account: account, account: account,
relationship: relationship,
mastodonAPIClient: mastodonAPIClient, mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase) contentDatabase: contentDatabase)
} }
init(id: Account.Id, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) { init(id: Account.Id, mastodonAPIClient: MastodonAPIClient, contentDatabase: ContentDatabase) {
self.init(id: id, account: nil, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) self.init(id: id,
account: nil,
relationship: nil,
mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase)
} }
private init( private init(
id: Account.Id, id: Account.Id,
account: Account?, account: Account?,
relationship: Relationship?,
mastodonAPIClient: MastodonAPIClient, mastodonAPIClient: MastodonAPIClient,
contentDatabase: ContentDatabase) { contentDatabase: ContentDatabase) {
self.id = id self.id = id
@ -38,7 +47,7 @@ public struct ProfileService {
if let account = account { if let account = account {
profilePublisher = profilePublisher profilePublisher = profilePublisher
.merge(with: Just(Profile(account: account)).setFailureType(to: Error.self)) .merge(with: Just(Profile(account: account, relationship: relationship)).setFailureType(to: Error.self))
.removeDuplicates() .removeDuplicates()
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }

View file

@ -141,7 +141,7 @@ extension CollectionItemsViewModel: CollectionViewModel {
let item = lastUpdate.sections[indexPath.section].items[indexPath.item] let item = lastUpdate.sections[indexPath.section].items[indexPath.item]
switch item { switch item {
case let .status(status, _, relationship): case let .status(status, _, _):
send(event: .navigation(.collection(collectionService send(event: .navigation(.collection(collectionService
.navigationService .navigationService
.contextService(id: status.displayStatus.id)))) .contextService(id: status.displayStatus.id))))
@ -151,7 +151,7 @@ extension CollectionItemsViewModel: CollectionViewModel {
case let .account(account, _, relationship): case let .account(account, _, relationship):
send(event: .navigation(.profile(collectionService send(event: .navigation(.profile(collectionService
.navigationService .navigationService
.profileService(account: account)))) .profileService(account: account, relationship: relationship))))
case let .notification(notification, _): case let .notification(notification, _):
if let status = notification.status { if let status = notification.status {
send(event: .navigation(.collection(collectionService send(event: .navigation(.collection(collectionService