This commit is contained in:
Justin Mazzocchi 2020-09-26 19:03:53 -07:00
parent 0173c118ae
commit 7f75b27ce2
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
18 changed files with 52 additions and 55 deletions

View file

@ -6,7 +6,7 @@ import GRDB
struct AccountStatusJoin: Codable, FetchableRecord, PersistableRecord { struct AccountStatusJoin: Codable, FetchableRecord, PersistableRecord {
let accountId: String let accountId: String
let statusId: String let statusId: String
let collection: AccountStatusCollection let collection: ProfileCollection
static let status = belongsTo(StatusRecord.self, using: ForeignKey([Column("statusId")])) static let status = belongsTo(StatusRecord.self, using: ForeignKey([Column("statusId")]))
} }

View file

@ -102,7 +102,7 @@ public extension ContentDatabase {
func insert( func insert(
statuses: [Status], statuses: [Status],
accountID: String, accountID: String,
collection: AccountStatusCollection) -> AnyPublisher<Never, Error> { collection: ProfileCollection) -> AnyPublisher<Never, Error> {
databaseQueue.writePublisher { databaseQueue.writePublisher {
for status in statuses { for status in statuses {
try status.save($0) try status.save($0)
@ -202,7 +202,7 @@ public extension ContentDatabase {
func statusesObservation( func statusesObservation(
accountID: String, accountID: String,
collection: AccountStatusCollection) -> AnyPublisher<[[Status]], Error> { collection: ProfileCollection) -> AnyPublisher<[[Status]], Error> {
ValueObservation.tracking { db -> [[StatusResult]] in ValueObservation.tracking { db -> [[StatusResult]] in
let statuses = try StatusRecord.filter( let statuses = try StatusRecord.filter(
AccountStatusJoin AccountStatusJoin

View file

@ -2,7 +2,7 @@
import Foundation import Foundation
public enum AccountStatusCollection: String, Codable, CaseIterable { public enum ProfileCollection: String, Codable, CaseIterable {
case statuses case statuses
case statusesAndReplies case statusesAndReplies
case media case media

View file

@ -3,7 +3,7 @@
import Foundation import Foundation
import ViewModels import ViewModels
extension AccountStatusCollection { extension ProfileCollection {
var title: String { var title: String {
switch self { switch self {
case .statuses: case .statuses:

View file

@ -18,7 +18,7 @@
D0625E5F250F0CFF00502611 /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0625E5E250F0CFF00502611 /* StatusView.swift */; }; D0625E5F250F0CFF00502611 /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0625E5E250F0CFF00502611 /* StatusView.swift */; };
D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = D06B492224D4611300642749 /* KingfisherSwiftUI */; }; D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = D06B492224D4611300642749 /* KingfisherSwiftUI */; };
D0B32F50250B373600311912 /* RegistrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B32F4F250B373600311912 /* RegistrationView.swift */; }; D0B32F50250B373600311912 /* RegistrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B32F4F250B373600311912 /* RegistrationView.swift */; };
D0B5FE9B251583DB00478838 /* AccountStatusCollection+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B5FE9A251583DB00478838 /* AccountStatusCollection+Extensions.swift */; }; D0B5FE9B251583DB00478838 /* ProfileCollection+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B5FE9A251583DB00478838 /* ProfileCollection+Extensions.swift */; };
D0B7434925100DBB00C13DB6 /* StatusView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D0B7434825100DBB00C13DB6 /* StatusView.xib */; }; D0B7434925100DBB00C13DB6 /* StatusView.xib in Resources */ = {isa = PBXBuildFile; fileRef = D0B7434825100DBB00C13DB6 /* StatusView.xib */; };
D0BEB1F324F8EE8C001B0F04 /* AttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */; }; D0BEB1F324F8EE8C001B0F04 /* AttachmentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */; };
D0BEB1F724F9A84B001B0F04 /* LoadingTableFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F624F9A84B001B0F04 /* LoadingTableFooterView.swift */; }; D0BEB1F724F9A84B001B0F04 /* LoadingTableFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0BEB1F624F9A84B001B0F04 /* LoadingTableFooterView.swift */; };
@ -106,7 +106,7 @@
D085C3BB25008DEC008A6C5E /* DB */ = {isa = PBXFileReference; lastKnownFileType = folder; path = DB; sourceTree = "<group>"; }; D085C3BB25008DEC008A6C5E /* DB */ = {isa = PBXFileReference; lastKnownFileType = folder; path = DB; sourceTree = "<group>"; };
D0AD03552505814D0085A466 /* Base16 */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Base16; sourceTree = "<group>"; }; D0AD03552505814D0085A466 /* Base16 */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Base16; sourceTree = "<group>"; };
D0B32F4F250B373600311912 /* RegistrationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegistrationView.swift; sourceTree = "<group>"; }; D0B32F4F250B373600311912 /* RegistrationView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RegistrationView.swift; sourceTree = "<group>"; };
D0B5FE9A251583DB00478838 /* AccountStatusCollection+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountStatusCollection+Extensions.swift"; sourceTree = "<group>"; }; D0B5FE9A251583DB00478838 /* ProfileCollection+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProfileCollection+Extensions.swift"; sourceTree = "<group>"; };
D0B7434825100DBB00C13DB6 /* StatusView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StatusView.xib; sourceTree = "<group>"; }; D0B7434825100DBB00C13DB6 /* StatusView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = StatusView.xib; sourceTree = "<group>"; };
D0BDF66524FD7A6400C7FA1C /* ServiceLayer */ = {isa = PBXFileReference; lastKnownFileType = folder; path = ServiceLayer; sourceTree = "<group>"; }; D0BDF66524FD7A6400C7FA1C /* ServiceLayer */ = {isa = PBXFileReference; lastKnownFileType = folder; path = ServiceLayer; sourceTree = "<group>"; };
D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentView.swift; sourceTree = "<group>"; }; D0BEB1F224F8EE8C001B0F04 /* AttachmentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentView.swift; sourceTree = "<group>"; };
@ -326,7 +326,7 @@
D0C7D46824F76169001EBDBB /* Extensions */ = { D0C7D46824F76169001EBDBB /* Extensions */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D0B5FE9A251583DB00478838 /* AccountStatusCollection+Extensions.swift */, D0B5FE9A251583DB00478838 /* ProfileCollection+Extensions.swift */,
D01C6FAB252024BD003D0300 /* Array+Extensions.swift */, D01C6FAB252024BD003D0300 /* Array+Extensions.swift */,
D0F0B135251AA12700942152 /* CollectionItemKind+Extensions.swift */, D0F0B135251AA12700942152 /* CollectionItemKind+Extensions.swift */,
D0C7D46E24F76169001EBDBB /* KingfisherOptionsInfo+Extensions.swift */, D0C7D46E24F76169001EBDBB /* KingfisherOptionsInfo+Extensions.swift */,
@ -533,7 +533,7 @@
D0625E5F250F0CFF00502611 /* StatusView.swift in Sources */, D0625E5F250F0CFF00502611 /* StatusView.swift in Sources */,
D0625E59250F092900502611 /* StatusListCell.swift in Sources */, D0625E59250F092900502611 /* StatusListCell.swift in Sources */,
D0C7D49D24F7616A001EBDBB /* PostingReadingPreferencesView.swift in Sources */, D0C7D49D24F7616A001EBDBB /* PostingReadingPreferencesView.swift in Sources */,
D0B5FE9B251583DB00478838 /* AccountStatusCollection+Extensions.swift in Sources */, D0B5FE9B251583DB00478838 /* ProfileCollection+Extensions.swift in Sources */,
D0C7D49E24F7616A001EBDBB /* SecondaryNavigationView.swift in Sources */, D0C7D49E24F7616A001EBDBB /* SecondaryNavigationView.swift in Sources */,
D0C7D4DA24F7616A001EBDBB /* View+Extensions.swift in Sources */, D0C7D4DA24F7616A001EBDBB /* View+Extensions.swift in Sources */,
D0C7D4D524F7616A001EBDBB /* String+Extensions.swift in Sources */, D0C7D4D524F7616A001EBDBB /* String+Extensions.swift in Sources */,

View file

@ -1,5 +0,0 @@
// Copyright © 2020 Metabolist. All rights reserved.
import DB
public typealias AccountStatusCollection = DB.AccountStatusCollection

View file

@ -0,0 +1,5 @@
// Copyright © 2020 Metabolist. All rights reserved.
import DB
public typealias ProfileCollection = DB.ProfileCollection

View file

@ -9,7 +9,7 @@ import MastodonAPI
public enum Navigation { public enum Navigation {
case url(URL) case url(URL)
case statusList(StatusListService) case statusList(StatusListService)
case accountStatuses(AccountStatusesService) case profile(ProfileService)
case webfingerStart case webfingerStart
case webfingerEnd case webfingerEnd
} }
@ -37,7 +37,7 @@ public extension NavigationService {
contentDatabase: contentDatabase))) contentDatabase: contentDatabase)))
.eraseToAnyPublisher() .eraseToAnyPublisher()
} else if let accountID = accountID(url: url) { } else if let accountID = accountID(url: url) {
return Just(.accountStatuses(accountStatusesService(id: accountID))).eraseToAnyPublisher() return Just(.profile(profileService(id: accountID))).eraseToAnyPublisher()
} else if mastodonAPIClient.instanceURL.host == url.host, let statusID = url.statusID { } else if mastodonAPIClient.instanceURL.host == url.host, let statusID = url.statusID {
return Just( return Just(
.statusList( .statusList(
@ -59,12 +59,12 @@ public extension NavigationService {
StatusListService(statusID: id, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) StatusListService(statusID: id, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase)
} }
func accountStatusesService(id: String) -> AccountStatusesService { func profileService(id: String) -> ProfileService {
AccountStatusesService(id: id, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) ProfileService(id: id, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase)
} }
func accountStatusesService(account: Account) -> AccountStatusesService { func profileService(account: Account) -> ProfileService {
AccountStatusesService(account: account, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase) ProfileService(account: account, mastodonAPIClient: mastodonAPIClient, contentDatabase: contentDatabase)
} }
func statusService(status: Status) -> StatusService { func statusService(status: Status) -> StatusService {
@ -114,7 +114,7 @@ private extension NavigationService {
mastodonAPIClient: mastodonAPIClient, mastodonAPIClient: mastodonAPIClient,
contentDatabase: contentDatabase)) contentDatabase: contentDatabase))
} else if let account = results.accounts.first { } else if let account = results.accounts.first {
return .accountStatuses(accountStatusesService(account: account)) return .profile(profileService(account: account))
} else if let status = results.statuses.first { } else if let status = results.statuses.first {
return .statusList( return .statusList(
StatusListService( StatusListService(

View file

@ -6,7 +6,7 @@ import Foundation
import Mastodon import Mastodon
import MastodonAPI import MastodonAPI
public struct AccountStatusesService { public struct ProfileService {
public let accountService: AnyPublisher<AccountService, Error> public let accountService: AnyPublisher<AccountService, Error>
private let accountID: String private let accountID: String
@ -50,9 +50,9 @@ public struct AccountStatusesService {
} }
} }
public extension AccountStatusesService { public extension ProfileService {
func statusListService( func statusListService(
collectionPublisher: CurrentValueSubject<AccountStatusCollection, Never>) -> StatusListService { collectionPublisher: CurrentValueSubject<ProfileCollection, Never>) -> StatusListService {
StatusListService( StatusListService(
accountID: accountID, accountID: accountID,
collection: collectionPublisher, collection: collectionPublisher,

View file

@ -81,7 +81,7 @@ extension StatusListService {
init( init(
accountID: String, accountID: String,
collection: CurrentValueSubject<AccountStatusCollection, Never>, collection: CurrentValueSubject<ProfileCollection, Never>,
mastodonAPIClient: MastodonAPIClient, mastodonAPIClient: MastodonAPIClient,
contentDatabase: ContentDatabase) { contentDatabase: ContentDatabase) {
let nextPageMaxIDsSubject = PassthroughSubject<String?, Never>() let nextPageMaxIDsSubject = PassthroughSubject<String?, Never>()

View file

@ -160,7 +160,7 @@ private extension TableViewController {
} }
.store(in: &cancellables) .store(in: &cancellables)
if let accountsStatusesViewModel = viewModel as? AccountStatusesViewModel { if let accountsStatusesViewModel = viewModel as? ProfileViewModel {
// Initial size is to avoid unsatisfiable constraint warning // Initial size is to avoid unsatisfiable constraint warning
let accountHeaderView = AccountHeaderView( let accountHeaderView = AccountHeaderView(
frame: .init( frame: .init(

View file

@ -66,18 +66,15 @@ extension AccountListViewModel: CollectionViewModel {
switch item.kind { switch item.kind {
case .account: case .account:
let navigationService = accountListService.navigationService let navigationService = accountListService.navigationService
let accountStatusesService: AccountStatusesService let profileService: ProfileService
if let account = accounts[item.id] { if let account = accounts[item.id] {
accountStatusesService = navigationService.accountStatusesService(account: account) profileService = navigationService.profileService(account: account)
} else { } else {
accountStatusesService = navigationService.accountStatusesService(id: item.id) profileService = navigationService.profileService(id: item.id)
} }
navigationEventsSubject.send( navigationEventsSubject.send(.collectionNavigation(ProfileViewModel(profileService: profileService)))
.collectionNavigation(
AccountStatusesViewModel(
accountStatusesService: accountStatusesService)))
default: default:
break break
} }

View file

@ -1,5 +0,0 @@
// Copyright © 2020 Metabolist. All rights reserved.
import ServiceLayer
public typealias AccountStatusCollection = ServiceLayer.AccountStatusCollection

View file

@ -21,8 +21,8 @@ extension NavigationEvent {
self = .urlNavigation(url) self = .urlNavigation(url)
case let .statusList(statusListService): case let .statusList(statusListService):
self = .collectionNavigation(StatusListViewModel(statusListService: statusListService)) self = .collectionNavigation(StatusListViewModel(statusListService: statusListService))
case let .accountStatuses(accountStatusesService): case let .profile(profileService):
self = .collectionNavigation(AccountStatusesViewModel(accountStatusesService: accountStatusesService)) self = .collectionNavigation(ProfileViewModel(profileService: profileService))
case .webfingerStart: case .webfingerStart:
self = .webfingerStart self = .webfingerStart
case .webfingerEnd: case .webfingerEnd:

View file

@ -0,0 +1,5 @@
// Copyright © 2020 Metabolist. All rights reserved.
import ServiceLayer
public typealias ProfileCollection = ServiceLayer.ProfileCollection

View file

@ -5,24 +5,24 @@ import Foundation
import Mastodon import Mastodon
import ServiceLayer import ServiceLayer
public class AccountStatusesViewModel: StatusListViewModel { public class ProfileViewModel: StatusListViewModel {
@Published public private(set) var accountViewModel: AccountViewModel? @Published public private(set) var accountViewModel: AccountViewModel?
@Published public var collection = AccountStatusCollection.statuses @Published public var collection = ProfileCollection.statuses
private let accountStatusesService: AccountStatusesService private let profileService: ProfileService
private var cancellables = Set<AnyCancellable>() private var cancellables = Set<AnyCancellable>()
init(accountStatusesService: AccountStatusesService) { init(profileService: ProfileService) {
self.accountStatusesService = accountStatusesService self.profileService = profileService
let collectionSubject = CurrentValueSubject<AccountStatusCollection, Never>(.statuses) let collectionSubject = CurrentValueSubject<ProfileCollection, Never>(.statuses)
super.init( super.init(
statusListService: accountStatusesService.statusListService( statusListService: profileService.statusListService(
collectionPublisher: collectionSubject)) collectionPublisher: collectionSubject))
$collection.sink(receiveValue: collectionSubject.send).store(in: &cancellables) $collection.sink(receiveValue: collectionSubject.send).store(in: &cancellables)
accountStatusesService.accountService profileService.accountService
.map(AccountViewModel.init(accountService:)) .map(AccountViewModel.init(accountService:))
.assignErrorsToAlertItem(to: \.alertItem, on: self) .assignErrorsToAlertItem(to: \.alertItem, on: self)
.assign(to: &$accountViewModel) .assign(to: &$accountViewModel)
@ -53,7 +53,7 @@ public class AccountStatusesViewModel: StatusListViewModel {
public override func request(maxID: String? = nil, minID: String? = nil) { public override func request(maxID: String? = nil, minID: String? = nil) {
if case .statuses = collection, maxID == nil { if case .statuses = collection, maxID == nil {
accountStatusesService.fetchPinnedStatuses() profileService.fetchPinnedStatuses()
.assignErrorsToAlertItem(to: \.alertItem, on: self) .assignErrorsToAlertItem(to: \.alertItem, on: self)
.sink { _ in } .sink { _ in }
.store(in: &cancellables) .store(in: &cancellables)
@ -67,9 +67,9 @@ public class AccountStatusesViewModel: StatusListViewModel {
} }
} }
public extension AccountStatusesViewModel { public extension ProfileViewModel {
func fetchAccount() { func fetchAccount() {
accountStatusesService.fetchAccount() profileService.fetchAccount()
.assignErrorsToAlertItem(to: \.alertItem, on: self) .assignErrorsToAlertItem(to: \.alertItem, on: self)
.sink { _ in } .sink { _ in }
.store(in: &cancellables) .store(in: &cancellables)

View file

@ -118,8 +118,8 @@ public extension StatusViewModel {
func accountSelected() { func accountSelected() {
eventsSubject.send( eventsSubject.send(
Just(CollectionItemEvent.navigation( Just(CollectionItemEvent.navigation(
.accountStatuses( .profile(
statusService.navigationService.accountStatusesService( statusService.navigationService.profileService(
account: statusService.status.displayStatus.account)))) account: statusService.status.displayStatus.account))))
.setFailureType(to: Error.self) .setFailureType(to: Error.self)
.eraseToAnyPublisher()) .eraseToAnyPublisher())

View file

@ -9,7 +9,7 @@ class AccountHeaderView: UIView {
let noteTextView = TouchFallthroughTextView() let noteTextView = TouchFallthroughTextView()
let segmentedControl = UISegmentedControl() let segmentedControl = UISegmentedControl()
var viewModel: AccountStatusesViewModel? { var viewModel: ProfileViewModel? {
didSet { didSet {
if let accountViewModel = viewModel?.accountViewModel { if let accountViewModel = viewModel?.accountViewModel {
headerImageView.kf.setImage(with: accountViewModel.headerURL) headerImageView.kf.setImage(with: accountViewModel.headerURL)
@ -75,7 +75,7 @@ private extension AccountHeaderView {
noteTextView.delegate = self noteTextView.delegate = self
baseStackView.addArrangedSubview(noteTextView) baseStackView.addArrangedSubview(noteTextView)
for (index, collection) in AccountStatusCollection.allCases.enumerated() { for (index, collection) in ProfileCollection.allCases.enumerated() {
segmentedControl.insertSegment( segmentedControl.insertSegment(
action: UIAction(title: collection.title) { [weak self] _ in action: UIAction(title: collection.title) { [weak self] _ in
self?.viewModel?.collection = collection self?.viewModel?.collection = collection