Refactoring
This commit is contained in:
parent
7f75b27ce2
commit
c23b435408
|
@ -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 */,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue