Keep references to identity context in view models

This commit is contained in:
Justin Mazzocchi 2021-01-25 16:45:18 -08:00
parent fe093d7e33
commit a291f3114a
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
29 changed files with 52 additions and 65 deletions

View file

@ -7,13 +7,11 @@ import ViewModels
final class ExploreViewController: UICollectionViewController {
private let viewModel: ExploreViewModel
private let rootViewModel: RootViewModel
private let identityContext: IdentityContext
private var cancellables = Set<AnyCancellable>()
init(viewModel: ExploreViewModel, rootViewModel: RootViewModel, identityContext: IdentityContext) {
init(viewModel: ExploreViewModel, rootViewModel: RootViewModel) {
self.viewModel = viewModel
self.rootViewModel = rootViewModel
self.identityContext = identityContext
super.init(collectionViewLayout: UICollectionViewFlowLayout())
@ -36,7 +34,6 @@ final class ExploreViewController: UICollectionViewController {
let searchResultsController = TableViewController(
viewModel: viewModel.searchViewModel,
rootViewModel: rootViewModel,
identityContext: identityContext,
insetBottom: false,
parentNavigationController: navigationController)

View file

@ -60,15 +60,13 @@ private extension MainNavigationViewController {
rootViewModel: rootViewModel),
ExploreViewController(
viewModel: viewModel.exploreViewModel,
rootViewModel: rootViewModel,
identityContext: viewModel.identityContext)
rootViewModel: rootViewModel)
]
if let notificationsViewModel = viewModel.notificationsViewModel {
let notificationsViewController = TableViewController(
viewModel: notificationsViewModel,
rootViewModel: rootViewModel,
identityContext: viewModel.identityContext)
rootViewModel: rootViewModel)
notificationsViewController.tabBarItem = NavigationViewModel.Tab.notifications.tabBarItem
@ -78,8 +76,7 @@ private extension MainNavigationViewController {
if let conversationsViewModel = viewModel.conversationsViewModel {
let conversationsViewController = TableViewController(
viewModel: conversationsViewModel,
rootViewModel: rootViewModel,
identityContext: viewModel.identityContext)
rootViewModel: rootViewModel)
conversationsViewController.tabBarItem = NavigationViewModel.Tab.messages.tabBarItem
conversationsViewController.navigationItem.title = NavigationViewModel.Tab.messages.title

View file

@ -19,7 +19,6 @@ final class ProfileViewController: TableViewController {
super.init(
viewModel: viewModel,
rootViewModel: rootViewModel,
identityContext: identityContext,
parentNavigationController: parentNavigationController)
}

View file

@ -13,7 +13,6 @@ class TableViewController: UITableViewController {
private let viewModel: CollectionViewModel
private let rootViewModel: RootViewModel
private let identityContext: IdentityContext
private let loadingTableFooterView = LoadingTableFooterView()
private let webfingerIndicatorView = WebfingerIndicatorView()
@Published private var loading = false
@ -30,12 +29,10 @@ class TableViewController: UITableViewController {
init(viewModel: CollectionViewModel,
rootViewModel: RootViewModel,
identityContext: IdentityContext,
insetBottom: Bool = true,
parentNavigationController: UINavigationController? = nil) {
self.viewModel = viewModel
self.rootViewModel = rootViewModel
self.identityContext = identityContext
self.insetBottom = insetBottom
self.parentNavigationController = parentNavigationController
@ -130,7 +127,7 @@ class TableViewController: UITableViewController {
return cellHeightCaches[tableView.frame.width]?[item]
?? item.estimatedHeight(width: tableView.readableContentGuide.layoutFrame.width,
identityContext: identityContext)
identityContext: viewModel.identityContext)
}
override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
@ -346,9 +343,8 @@ private extension TableViewController {
let vc = TableViewController(
viewModel: CollectionItemsViewModel(
collectionService: collectionService,
identityContext: identityContext),
identityContext: viewModel.identityContext),
rootViewModel: rootViewModel,
identityContext: identityContext,
parentNavigationController: parentNavigationController)
if let parentNavigationController = parentNavigationController {
@ -360,9 +356,9 @@ private extension TableViewController {
let vc = ProfileViewController(
viewModel: ProfileViewModel(
profileService: profileService,
identityContext: identityContext),
identityContext: viewModel.identityContext),
rootViewModel: rootViewModel,
identityContext: identityContext,
identityContext: viewModel.identityContext,
parentNavigationController: parentNavigationController)
if let parentNavigationController = parentNavigationController {
@ -420,7 +416,7 @@ private extension TableViewController {
func compose(inReplyToViewModel: StatusViewModel?, redraft: Status?) {
let newStatusViewModel = rootViewModel.newStatusViewModel(
identityContext: identityContext,
identityContext: viewModel.identityContext,
inReplyTo: inReplyToViewModel,
redraft: redraft)
let newStatusViewController = NewStatusViewController(viewModel: newStatusViewModel)

View file

@ -21,8 +21,7 @@ final class TimelinesViewController: UIPageViewController {
timelineViewControllers.append(
TableViewController(
viewModel: viewModel.viewModel(timeline: timeline),
rootViewModel: rootViewModel,
identityContext: viewModel.identityContext))
rootViewModel: rootViewModel))
segmentedControl.insertSegment(withTitle: timeline.title, at: index, animated: false)
}
@ -76,8 +75,7 @@ final class TimelinesViewController: UIPageViewController {
let vc = TableViewController(
viewModel: self.viewModel.viewModel(timeline: $0),
rootViewModel: self.rootViewModel,
identityContext: self.viewModel.identityContext)
rootViewModel: self.rootViewModel)
vc.navigationItem.title = $0.title

View file

@ -7,9 +7,9 @@ import ServiceLayer
public struct AccountViewModel: CollectionItemViewModel {
public let events: AnyPublisher<AnyPublisher<CollectionItemEvent, Error>, Never>
public let identityContext: IdentityContext
private let accountService: AccountService
private let identityContext: IdentityContext
private let eventsSubject = PassthroughSubject<AnyPublisher<CollectionItemEvent, Error>, Never>()
init(accountService: AccountService, identityContext: IdentityContext) {

View file

@ -10,8 +10,8 @@ public final class AttachmentViewModel: ObservableObject {
@Published public var editingDescription: String
@Published public var editingFocus: Attachment.Meta.Focus
@Published public private(set) var descriptionRemainingCharacters = AttachmentViewModel.descriptionMaxCharacters
public let identityContext: IdentityContext
private let identityContext: IdentityContext
private let status: Status?
init(attachment: Attachment, identityContext: IdentityContext, status: Status? = nil) {

View file

@ -7,6 +7,7 @@ import ServiceLayer
// swiftlint:disable file_length
public class CollectionItemsViewModel: ObservableObject {
public let identityContext: IdentityContext
@Published public var alertItem: AlertItem?
public private(set) var nextPageMaxId: String?
@ -15,7 +16,6 @@ public class CollectionItemsViewModel: ObservableObject {
maintainScrollPositionItemId: nil,
shouldAdjustContentInset: false)
private let collectionService: CollectionService
private let identityContext: IdentityContext
private var viewModelCache = [CollectionItem: (viewModel: CollectionItemViewModel, events: AnyCancellable)]()
private let eventsSubject = PassthroughSubject<CollectionItemEvent, Never>()
private let loadingSubject = PassthroughSubject<Bool, Never>()

View file

@ -4,6 +4,7 @@ import Combine
import Foundation
public protocol CollectionViewModel {
var identityContext: IdentityContext { get }
var updates: AnyPublisher<CollectionUpdate, Never> { get }
var title: AnyPublisher<String, Never> { get }
var titleLocalizationComponents: AnyPublisher<[String], Never> { get }

View file

@ -9,9 +9,9 @@ public final class ConversationViewModel: CollectionItemViewModel, ObservableObj
public let accountViewModels: [AccountViewModel]
public let statusViewModel: StatusViewModel?
public let events: AnyPublisher<AnyPublisher<CollectionItemEvent, Error>, Never>
public let identityContext: IdentityContext
private let conversationService: ConversationService
private let identityContext: IdentityContext
private let eventsSubject = PassthroughSubject<AnyPublisher<CollectionItemEvent, Error>, Never>()
init(conversationService: ConversationService, identityContext: IdentityContext) {

View file

@ -10,12 +10,12 @@ public final class EditFilterViewModel: ObservableObject {
@Published public var saving = false
@Published public var alertItem: AlertItem?
public let saveCompleted: AnyPublisher<Void, Never>
public let identityContext: IdentityContext
public var date: Date {
didSet { filter.expiresAt = date }
}
private let identityContext: IdentityContext
private let saveCompletedSubject = PassthroughSubject<Void, Never>()
private var cancellables = Set<AnyCancellable>()

View file

@ -5,9 +5,9 @@ import ServiceLayer
public final class ExploreViewModel: ObservableObject {
public let searchViewModel: SearchViewModel
public let identityContext: IdentityContext
private let exploreService: ExploreService
private let identityContext: IdentityContext
init(service: ExploreService, identityContext: IdentityContext) {
exploreService = service

View file

@ -9,8 +9,8 @@ public final class FiltersViewModel: ObservableObject {
@Published public var activeFilters = [Filter]()
@Published public var expiredFilters = [Filter]()
@Published public var alertItem: AlertItem?
public let identityContext: IdentityContext
private let identityContext: IdentityContext
private var cancellables = Set<AnyCancellable>()
public init(identityContext: IdentityContext) {

View file

@ -10,8 +10,8 @@ public final class IdentitiesViewModel: ObservableObject {
@Published public var unauthenticated = [Identity]()
@Published public var pending = [Identity]()
@Published public var alertItem: AlertItem?
public let identityContext: IdentityContext
private let identityContext: IdentityContext
private var cancellables = Set<AnyCancellable>()
public init(identityContext: IdentityContext) {

View file

@ -9,8 +9,8 @@ public final class ListsViewModel: ObservableObject {
@Published public private(set) var lists = [List]()
@Published public private(set) var creatingList = false
@Published public var alertItem: AlertItem?
public let identityContext: IdentityContext
private let identityContext: IdentityContext
private var cancellables = Set<AnyCancellable>()
public init(identityContext: IdentityContext) {

View file

@ -5,7 +5,7 @@ import Foundation
import ServiceLayer
public final class MediaPreferencesViewModel: ObservableObject {
private let identityContext: IdentityContext
public let identityContext: IdentityContext
public init(identityContext: IdentityContext) {
self.identityContext = identityContext

View file

@ -8,8 +8,8 @@ import ServiceLayer
public final class NotificationTypesPreferencesViewModel: ObservableObject {
@Published public var pushSubscriptionAlerts: PushSubscription.Alerts
@Published public var alertItem: AlertItem?
public let identityContext: IdentityContext
private let identityContext: IdentityContext
private var cancellables = Set<AnyCancellable>()
public init(identityContext: IdentityContext) {

View file

@ -9,9 +9,9 @@ public final class NotificationViewModel: CollectionItemViewModel, ObservableObj
public let accountViewModel: AccountViewModel
public let statusViewModel: StatusViewModel?
public let events: AnyPublisher<AnyPublisher<CollectionItemEvent, Error>, Never>
public let identityContext: IdentityContext
private let notificationService: NotificationService
private let identityContext: IdentityContext
private let eventsSubject = PassthroughSubject<AnyPublisher<CollectionItemEvent, Error>, Never>()
init(notificationService: NotificationService, identityContext: IdentityContext) {

View file

@ -7,8 +7,8 @@ import ServiceLayer
public final class PostingReadingPreferencesViewModel: ObservableObject {
@Published public var preferences: Identity.Preferences
@Published public var alertItem: AlertItem?
public let identityContext: IdentityContext
private let identityContext: IdentityContext
private var cancellables = Set<AnyCancellable>()
public init(identityContext: IdentityContext) {

View file

@ -6,8 +6,7 @@ import ServiceLayer
public final class PreferencesViewModel: ObservableObject {
public let handle: String
public let shouldShowNotificationTypePreferences: Bool
private let identityContext: IdentityContext
public let identityContext: IdentityContext
public init(identityContext: IdentityContext) {
self.identityContext = identityContext

View file

@ -62,6 +62,10 @@ public extension ProfileViewModel {
}
extension ProfileViewModel: CollectionViewModel {
public var identityContext: IdentityContext {
collectionViewModel.value.identityContext
}
public var updates: AnyPublisher<CollectionUpdate, Never> {
collectionViewModel.flatMap(\.updates).eraseToAnyPublisher()
}

View file

@ -19,9 +19,9 @@ public final class StatusViewModel: CollectionItemViewModel, AttachmentsRenderin
@Published public var pollOptionSelections = Set<Int>()
public var configuration = CollectionItem.StatusConfiguration.default
public let events: AnyPublisher<AnyPublisher<CollectionItemEvent, Error>, Never>
public let identityContext: IdentityContext
private let statusService: StatusService
private let identityContext: IdentityContext
private let eventsSubject = PassthroughSubject<AnyPublisher<CollectionItemEvent, Error>, Never>()
init(statusService: StatusService, identityContext: IdentityContext) {

View file

@ -6,13 +6,12 @@ import ViewModels
struct FiltersView: View {
@StateObject var viewModel: FiltersViewModel
@EnvironmentObject var identityContext: IdentityContext
var body: some View {
Form {
Section {
NavigationLink(destination: EditFilterView(
viewModel: .init(filter: .new, identityContext: identityContext))) {
viewModel: .init(filter: .new, identityContext: viewModel.identityContext))) {
Label("add", systemImage: "plus.circle")
}
}
@ -37,7 +36,7 @@ private extension FiltersView {
Section(header: Text(title)) {
ForEach(filters) { filter in
NavigationLink(destination: EditFilterView(
viewModel: .init(filter: filter, identityContext: identityContext))) {
viewModel: .init(filter: filter, identityContext: viewModel.identityContext))) {
HStack {
Text(filter.phrase)
Spacer()

View file

@ -6,7 +6,6 @@ import ViewModels
struct MainNavigationView: UIViewControllerRepresentable {
let viewModelClosure: () -> NavigationViewModel
@EnvironmentObject var rootViewModel: RootViewModel
@EnvironmentObject var identityContext: IdentityContext
func makeUIViewController(context: Context) -> MainNavigationViewController {
MainNavigationViewController(
@ -25,7 +24,6 @@ import PreviewViewModels
struct MainNavigationView_Previews: PreviewProvider {
static var previews: some View {
MainNavigationView { NavigationViewModel(identityContext: .preview) }
.environmentObject(IdentityContext.preview)
.environmentObject(RootViewModel.preview)
}
}

View file

@ -5,9 +5,14 @@ import ViewModels
struct MediaPreferencesView: View {
@StateObject var viewModel: MediaPreferencesViewModel
@EnvironmentObject var identityContext: IdentityContext
@StateObject var identityContext: IdentityContext
@Environment(\.accessibilityReduceMotion) var accessibilityReduceMotion
init(viewModel: MediaPreferencesViewModel) {
_viewModel = StateObject(wrappedValue: viewModel)
_identityContext = StateObject(wrappedValue: viewModel.identityContext)
}
var body: some View {
Form {
if accessibilityReduceMotion {

View file

@ -5,21 +5,20 @@ import ViewModels
struct PreferencesView: View {
@StateObject var viewModel: PreferencesViewModel
@EnvironmentObject var identityContext: IdentityContext
var body: some View {
Form {
Section(header: Text(viewModel.handle)) {
NavigationLink("preferences.posting-reading",
destination: PostingReadingPreferencesView(
viewModel: .init(identityContext: identityContext)))
viewModel: .init(identityContext: viewModel.identityContext)))
NavigationLink("preferences.filters",
destination: FiltersView(
viewModel: .init(identityContext: identityContext)))
viewModel: .init(identityContext: viewModel.identityContext)))
if viewModel.shouldShowNotificationTypePreferences {
NavigationLink("preferences.notification-types",
destination: NotificationTypesPreferencesView(
viewModel: .init(identityContext: identityContext)))
viewModel: .init(identityContext: viewModel.identityContext)))
}
NavigationLink("preferences.muted-users",
destination: TableView(viewModelClosure: viewModel.mutedUsersViewModel)
@ -33,9 +32,10 @@ struct PreferencesView: View {
Section(header: Text("preferences.app")) {
NavigationLink("preferences.media",
destination: MediaPreferencesView(
viewModel: .init(identityContext: identityContext)))
viewModel: .init(identityContext: viewModel.identityContext)))
NavigationLink("preferences.startup-and-syncing",
destination: StartupAndSyncingPreferencesView())
destination: StartupAndSyncingPreferencesView(
identityContext: viewModel.identityContext))
}
}
.navigationTitle("preferences")

View file

@ -14,8 +14,7 @@ struct SecondaryNavigationView: View {
Section {
NavigationLink(
destination: IdentitiesView(viewModel: .init(identityContext: viewModel.identityContext))
.environmentObject(rootViewModel)
.environmentObject(viewModel.identityContext),
.environmentObject(rootViewModel),
label: {
HStack {
KFImage(viewModel.identityContext.identity.image)
@ -55,8 +54,7 @@ struct SecondaryNavigationView: View {
}
Section {
NavigationLink(destination: ListsView(viewModel: .init(identityContext: viewModel.identityContext))
.environmentObject(rootViewModel)
.environmentObject(viewModel.identityContext)) {
.environmentObject(rootViewModel)) {
Label("secondary-navigation.lists", systemImage: "scroll")
}
ForEach([Timeline.favorites, Timeline.bookmarks]) { timeline in
@ -74,8 +72,7 @@ struct SecondaryNavigationView: View {
Section {
NavigationLink(
destination: PreferencesView(viewModel: .init(identityContext: viewModel.identityContext))
.environmentObject(rootViewModel)
.environmentObject(viewModel.identityContext)) {
.environmentObject(rootViewModel)) {
Label("secondary-navigation.preferences", systemImage: "gear")
}
}

View file

@ -4,7 +4,7 @@ import SwiftUI
import ViewModels
struct StartupAndSyncingPreferencesView: View {
@EnvironmentObject var identityContext: IdentityContext
@StateObject var identityContext: IdentityContext
var body: some View {
Form {
@ -46,8 +46,7 @@ import PreviewViewModels
struct StartupAndSyncingPreferencesView_Previews: PreviewProvider {
static var previews: some View {
StartupAndSyncingPreferencesView()
.environmentObject(IdentityContext.preview)
StartupAndSyncingPreferencesView(identityContext: .preview)
}
}
#endif

View file

@ -4,14 +4,12 @@ import SwiftUI
import ViewModels
struct TableView: UIViewControllerRepresentable {
@EnvironmentObject var identityContext: IdentityContext
@EnvironmentObject var rootViewModel: RootViewModel
let viewModelClosure: () -> CollectionViewModel
func makeUIViewController(context: Context) -> TableViewController {
TableViewController(viewModel: viewModelClosure(),
rootViewModel: rootViewModel,
identityContext: identityContext)
rootViewModel: rootViewModel)
}
func updateUIViewController(_ uiViewController: TableViewController, context: Context) {