mirror of
https://github.com/metabolist/metatext.git
synced 2024-09-28 22:32:04 +00:00
Refactoring
This commit is contained in:
parent
7f75b27ce2
commit
c23b435408
5 changed files with 85 additions and 63 deletions
|
@ -17,6 +17,7 @@
|
||||||
D0625E5D250F0B5C00502611 /* StatusContentConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0625E5C250F0B5C00502611 /* StatusContentConfiguration.swift */; };
|
D0625E5D250F0B5C00502611 /* StatusContentConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0625E5C250F0B5C00502611 /* StatusContentConfiguration.swift */; };
|
||||||
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 */; };
|
||||||
|
D06BC5E625202AD90079541D /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D06BC5E525202AD90079541D /* ProfileViewController.swift */; };
|
||||||
D0B32F50250B373600311912 /* RegistrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B32F4F250B373600311912 /* RegistrationView.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 */; };
|
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 */; };
|
||||||
|
@ -103,6 +104,7 @@
|
||||||
D0625E5E250F0CFF00502611 /* StatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusView.swift; sourceTree = "<group>"; };
|
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; };
|
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>"; };
|
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>"; };
|
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>"; };
|
||||||
|
@ -300,6 +302,7 @@
|
||||||
D0C7D43024F76169001EBDBB /* View Controllers */ = {
|
D0C7D43024F76169001EBDBB /* View Controllers */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
D06BC5E525202AD90079541D /* ProfileViewController.swift */,
|
||||||
D0F0B12D251A97E400942152 /* TableViewController.swift */,
|
D0F0B12D251A97E400942152 /* TableViewController.swift */,
|
||||||
);
|
);
|
||||||
path = "View Controllers";
|
path = "View Controllers";
|
||||||
|
@ -539,6 +542,7 @@
|
||||||
D0C7D4D524F7616A001EBDBB /* String+Extensions.swift in Sources */,
|
D0C7D4D524F7616A001EBDBB /* String+Extensions.swift in Sources */,
|
||||||
D0C7D4A224F7616A001EBDBB /* NotificationTypesPreferencesView.swift in Sources */,
|
D0C7D4A224F7616A001EBDBB /* NotificationTypesPreferencesView.swift in Sources */,
|
||||||
D0BEB1F724F9A84B001B0F04 /* LoadingTableFooterView.swift in Sources */,
|
D0BEB1F724F9A84B001B0F04 /* LoadingTableFooterView.swift in Sources */,
|
||||||
|
D06BC5E625202AD90079541D /* ProfileViewController.swift in Sources */,
|
||||||
D01C6FAC252024BD003D0300 /* Array+Extensions.swift in Sources */,
|
D01C6FAC252024BD003D0300 /* Array+Extensions.swift in Sources */,
|
||||||
D0C7D4D924F7616A001EBDBB /* KingfisherOptionsInfo+Extensions.swift in Sources */,
|
D0C7D4D924F7616A001EBDBB /* KingfisherOptionsInfo+Extensions.swift in Sources */,
|
||||||
D0F0B10E251A868200942152 /* AccountView.swift in Sources */,
|
D0F0B10E251A868200942152 /* AccountView.swift in Sources */,
|
||||||
|
|
35
View Controllers/ProfileViewController.swift
Normal file
35
View Controllers/ProfileViewController.swift
Normal 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
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 {
|
private extension TableViewController {
|
||||||
func setupViewModelBindings() {
|
func setupViewModelBindings() {
|
||||||
viewModel.title.sink { [weak self] in self?.navigationItem.title = $0 }.store(in: &cancellables)
|
viewModel.title.sink { [weak self] in self?.navigationItem.title = $0 }.store(in: &cancellables)
|
||||||
|
|
||||||
viewModel.collectionItems
|
viewModel.collectionItems.sink { [weak self] in self?.update(items: $0) }.store(in: &cancellables)
|
||||||
.sink { [weak self] in self?.update(items: $0) }
|
|
||||||
.store(in: &cancellables)
|
|
||||||
|
|
||||||
viewModel.navigationEvents.receive(on: DispatchQueue.main).sink { [weak self] in
|
viewModel.navigationEvents.receive(on: DispatchQueue.main).sink { [weak self] in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
@ -138,8 +169,10 @@ private extension TableViewController {
|
||||||
switch $0 {
|
switch $0 {
|
||||||
case let .share(url):
|
case let .share(url):
|
||||||
self.share(url: url)
|
self.share(url: url)
|
||||||
case let .collectionNavigation(collectionViewModel):
|
case let .collectionNavigation(viewModel):
|
||||||
self.show(TableViewController(viewModel: collectionViewModel), sender: self)
|
self.show(TableViewController(viewModel: viewModel), sender: self)
|
||||||
|
case let .profileNavigation(viewModel):
|
||||||
|
self.show(ProfileViewController(viewModel: viewModel), sender: self)
|
||||||
case let .urlNavigation(url):
|
case let .urlNavigation(url):
|
||||||
self.present(SFSafariViewController(url: url), animated: true)
|
self.present(SFSafariViewController(url: url), animated: true)
|
||||||
case .webfingerStart:
|
case .webfingerStart:
|
||||||
|
@ -150,33 +183,13 @@ private extension TableViewController {
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.store(in: &cancellables)
|
||||||
|
|
||||||
viewModel.loading
|
viewModel.loading.receive(on: RunLoop.main).sink { [weak self] in
|
||||||
.receive(on: RunLoop.main)
|
|
||||||
.sink { [weak self] in
|
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
|
||||||
self.tableView.tableFooterView = $0 ? self.loadingTableFooterView : UIView()
|
self.tableView.tableFooterView = $0 ? self.loadingTableFooterView : UIView()
|
||||||
self.sizeTableHeaderFooterViews()
|
self.sizeTableHeaderFooterViews()
|
||||||
}
|
}
|
||||||
.store(in: &cancellables)
|
.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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func update(items: [[CollectionItem]]) {
|
func update(items: [[CollectionItem]]) {
|
||||||
|
@ -212,35 +225,4 @@ private extension TableViewController {
|
||||||
|
|
||||||
present(activityViewController, animated: true, completion: nil)
|
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)
|
profileService = navigationService.profileService(id: item.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationEventsSubject.send(.collectionNavigation(ProfileViewModel(profileService: profileService)))
|
navigationEventsSubject.send(.profileNavigation(ProfileViewModel(profileService: profileService)))
|
||||||
default:
|
default:
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import Foundation
|
||||||
|
|
||||||
public enum NavigationEvent {
|
public enum NavigationEvent {
|
||||||
case collectionNavigation(CollectionViewModel)
|
case collectionNavigation(CollectionViewModel)
|
||||||
|
case profileNavigation(ProfileViewModel)
|
||||||
case urlNavigation(URL)
|
case urlNavigation(URL)
|
||||||
case share(URL)
|
case share(URL)
|
||||||
case webfingerStart
|
case webfingerStart
|
||||||
|
@ -22,7 +23,7 @@ extension NavigationEvent {
|
||||||
case let .statusList(statusListService):
|
case let .statusList(statusListService):
|
||||||
self = .collectionNavigation(StatusListViewModel(statusListService: statusListService))
|
self = .collectionNavigation(StatusListViewModel(statusListService: statusListService))
|
||||||
case let .profile(profileService):
|
case let .profile(profileService):
|
||||||
self = .collectionNavigation(ProfileViewModel(profileService: profileService))
|
self = .profileNavigation(ProfileViewModel(profileService: profileService))
|
||||||
case .webfingerStart:
|
case .webfingerStart:
|
||||||
self = .webfingerStart
|
self = .webfingerStart
|
||||||
case .webfingerEnd:
|
case .webfingerEnd:
|
||||||
|
|
Loading…
Reference in a new issue