Refactoring

This commit is contained in:
Justin Mazzocchi 2020-09-26 22:54:06 -07:00
parent 7f75b27ce2
commit c23b435408
No known key found for this signature in database
GPG key ID: E223E6937AAFB01C
5 changed files with 85 additions and 63 deletions

View file

@ -17,6 +17,7 @@
D0625E5D250F0B5C00502611 /* StatusContentConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0625E5C250F0B5C00502611 /* StatusContentConfiguration.swift */; };
D0625E5F250F0CFF00502611 /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0625E5E250F0CFF00502611 /* StatusView.swift */; };
D06B492324D4611300642749 /* KingfisherSwiftUI in Frameworks */ = {isa = PBXBuildFile; productRef = D06B492224D4611300642749 /* KingfisherSwiftUI */; };
D06BC5E625202AD90079541D /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06BC5E525202AD90079541D /* ProfileViewController.swift */; };
D0B32F50250B373600311912 /* RegistrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B32F4F250B373600311912 /* RegistrationView.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 */; };
@ -103,6 +104,7 @@
D0625E5E250F0CFF00502611 /* StatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusView.swift; sourceTree = "<group>"; };
D0666A2124C677B400F3F04B /* Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = Tests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
D0666A2524C677B400F3F04B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D06BC5E525202AD90079541D /* ProfileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewController.swift; sourceTree = "<group>"; };
D085C3BB25008DEC008A6C5E /* DB */ = {isa = PBXFileReference; lastKnownFileType = folder; path = DB; 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>"; };
@ -300,6 +302,7 @@
D0C7D43024F76169001EBDBB /* View Controllers */ = {
isa = PBXGroup;
children = (
D06BC5E525202AD90079541D /* ProfileViewController.swift */,
D0F0B12D251A97E400942152 /* TableViewController.swift */,
);
path = "View Controllers";
@ -539,6 +542,7 @@
D0C7D4D524F7616A001EBDBB /* String+Extensions.swift in Sources */,
D0C7D4A224F7616A001EBDBB /* NotificationTypesPreferencesView.swift in Sources */,
D0BEB1F724F9A84B001B0F04 /* LoadingTableFooterView.swift in Sources */,
D06BC5E625202AD90079541D /* ProfileViewController.swift in Sources */,
D01C6FAC252024BD003D0300 /* Array+Extensions.swift in Sources */,
D0C7D4D924F7616A001EBDBB /* KingfisherOptionsInfo+Extensions.swift in Sources */,
D0F0B10E251A868200942152 /* AccountView.swift in Sources */,

View file

@ -0,0 +1,35 @@
// Copyright © 2020 Metabolist. All rights reserved.
import Combine
import UIKit
import ViewModels
final class ProfileViewController: TableViewController {
private let viewModel: ProfileViewModel
private var cancellables = Set<AnyCancellable>()
required init(viewModel: ProfileViewModel) {
self.viewModel = viewModel
super.init(viewModel: viewModel)
}
override func viewDidLoad() {
super.viewDidLoad()
// Initial size is to avoid unsatisfiable constraint warning
let accountHeaderView = AccountHeaderView(frame: .init(origin: .zero, size: .init(width: 100, height: 100)))
accountHeaderView.viewModel = viewModel
viewModel.$accountViewModel
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
accountHeaderView.viewModel = self?.viewModel
self?.sizeTableHeaderFooterViews()
}
.store(in: &cancellables)
tableView.tableHeaderView = accountHeaderView
}
}

View file

@ -124,13 +124,44 @@ extension TableViewController: UITableViewDataSourcePrefetching {
}
}
extension TableViewController {
func sizeTableHeaderFooterViews() {
// https://useyourloaf.com/blog/variable-height-table-view-header/
if let headerView = tableView.tableHeaderView {
let size = headerView.systemLayoutSizeFitting(
CGSize(width: tableView.frame.width, height: .greatestFiniteMagnitude),
withHorizontalFittingPriority: .required,
verticalFittingPriority: .fittingSizeLevel)
if headerView.frame.size.height != size.height {
headerView.frame.size.height = size.height
tableView.tableHeaderView = headerView
tableView.layoutIfNeeded()
}
view.insertSubview(webfingerIndicatorView, aboveSubview: headerView)
}
if let footerView = tableView.tableFooterView {
let size = footerView.systemLayoutSizeFitting(
CGSize(width: tableView.frame.width, height: .greatestFiniteMagnitude),
withHorizontalFittingPriority: .required,
verticalFittingPriority: .fittingSizeLevel)
if footerView.frame.size.height != size.height {
footerView.frame.size.height = size.height
tableView.tableFooterView = footerView
tableView.layoutIfNeeded()
}
}
}
}
private extension TableViewController {
func setupViewModelBindings() {
viewModel.title.sink { [weak self] in self?.navigationItem.title = $0 }.store(in: &cancellables)
viewModel.collectionItems
.sink { [weak self] in self?.update(items: $0) }
.store(in: &cancellables)
viewModel.collectionItems.sink { [weak self] in self?.update(items: $0) }.store(in: &cancellables)
viewModel.navigationEvents.receive(on: DispatchQueue.main).sink { [weak self] in
guard let self = self else { return }
@ -138,8 +169,10 @@ private extension TableViewController {
switch $0 {
case let .share(url):
self.share(url: url)
case let .collectionNavigation(collectionViewModel):
self.show(TableViewController(viewModel: collectionViewModel), sender: self)
case let .collectionNavigation(viewModel):
self.show(TableViewController(viewModel: viewModel), sender: self)
case let .profileNavigation(viewModel):
self.show(ProfileViewController(viewModel: viewModel), sender: self)
case let .urlNavigation(url):
self.present(SFSafariViewController(url: url), animated: true)
case .webfingerStart:
@ -150,33 +183,13 @@ private extension TableViewController {
}
.store(in: &cancellables)
viewModel.loading
.receive(on: RunLoop.main)
.sink { [weak self] in
guard let self = self else { return }
viewModel.loading.receive(on: RunLoop.main).sink { [weak self] in
guard let self = self else { return }
self.tableView.tableFooterView = $0 ? self.loadingTableFooterView : UIView()
self.sizeTableHeaderFooterViews()
}
.store(in: &cancellables)
if let accountsStatusesViewModel = viewModel as? ProfileViewModel {
// Initial size is to avoid unsatisfiable constraint warning
let accountHeaderView = AccountHeaderView(
frame: .init(
origin: .zero,
size: .init(width: 100, height: 100)))
accountHeaderView.viewModel = accountsStatusesViewModel
accountsStatusesViewModel.$accountViewModel
.dropFirst()
.receive(on: DispatchQueue.main)
.sink { [weak self] _ in
accountHeaderView.viewModel = accountsStatusesViewModel
self?.sizeTableHeaderFooterViews()
}
.store(in: &cancellables)
tableView.tableHeaderView = accountHeaderView
self.tableView.tableFooterView = $0 ? self.loadingTableFooterView : UIView()
self.sizeTableHeaderFooterViews()
}
.store(in: &cancellables)
}
func update(items: [[CollectionItem]]) {
@ -212,35 +225,4 @@ private extension TableViewController {
present(activityViewController, animated: true, completion: nil)
}
func sizeTableHeaderFooterViews() {
// https://useyourloaf.com/blog/variable-height-table-view-header/
if let headerView = tableView.tableHeaderView {
let size = headerView.systemLayoutSizeFitting(
CGSize(width: tableView.frame.width, height: .greatestFiniteMagnitude),
withHorizontalFittingPriority: .required,
verticalFittingPriority: .fittingSizeLevel)
if headerView.frame.size.height != size.height {
headerView.frame.size.height = size.height
tableView.tableHeaderView = headerView
tableView.layoutIfNeeded()
}
view.insertSubview(webfingerIndicatorView, aboveSubview: headerView)
}
if let footerView = tableView.tableFooterView {
let size = footerView.systemLayoutSizeFitting(
CGSize(width: tableView.frame.width, height: .greatestFiniteMagnitude),
withHorizontalFittingPriority: .required,
verticalFittingPriority: .fittingSizeLevel)
if footerView.frame.size.height != size.height {
footerView.frame.size.height = size.height
tableView.tableFooterView = footerView
tableView.layoutIfNeeded()
}
}
}
}

View file

@ -74,7 +74,7 @@ extension AccountListViewModel: CollectionViewModel {
profileService = navigationService.profileService(id: item.id)
}
navigationEventsSubject.send(.collectionNavigation(ProfileViewModel(profileService: profileService)))
navigationEventsSubject.send(.profileNavigation(ProfileViewModel(profileService: profileService)))
default:
break
}

View file

@ -4,6 +4,7 @@ import Foundation
public enum NavigationEvent {
case collectionNavigation(CollectionViewModel)
case profileNavigation(ProfileViewModel)
case urlNavigation(URL)
case share(URL)
case webfingerStart
@ -22,7 +23,7 @@ extension NavigationEvent {
case let .statusList(statusListService):
self = .collectionNavigation(StatusListViewModel(statusListService: statusListService))
case let .profile(profileService):
self = .collectionNavigation(ProfileViewModel(profileService: profileService))
self = .profileNavigation(ProfileViewModel(profileService: profileService))
case .webfingerStart:
self = .webfingerStart
case .webfingerEnd: