Commit 80d1b261 authored by Maarten Billemont's avatar Maarten Billemont

Move to a StackView for detail items.

TableViews have an internal scroll view and that gives us a smaller area
to put the detail's views into.  A full-sized StackView allows us to
play with the full height content of the details better.  Here we keep
the search field above the site detail views as much as possible.
parent fd26beaf
Pipeline #44409842 failed with stage
in 9 minutes and 23 seconds
......@@ -5,19 +5,21 @@
import Foundation
class MPSiteDetailViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, MPSiteObserver {
class MPSiteDetailViewController: UIViewController, MPSiteObserver {
let observers = Observers<MPSiteDetailObserver>()
let site: MPSite
let closeButton = MPButton.closeButton()
let tableView = UITableView( frame: .zero, style: .plain )
let items = [ PasswordCounterItem(),
PasswordTypeItem(),
SeparatorItem(),
LoginTypeItem(),
URLItem(),
SeparatorItem(),
InfoItem() ]
let items = [ PasswordCounterItem(),
PasswordTypeItem(),
SeparatorItem(),
LoginTypeItem(),
URLItem(),
SeparatorItem(),
InfoItem() ]
let backgroundView = UIView()
let itemsView = UIStackView()
let closeButton = MPButton.closeButton()
// MARK: - Life
......@@ -35,31 +37,37 @@ class MPSiteDetailViewController: UIViewController, UITableViewDelegate, UITable
override func viewDidLoad() {
// - View
self.closeButton.button.addTarget( self, action: #selector( close ), for: .touchUpInside )
self.backgroundView.layer.cornerRadius = 8
self.backgroundView.layer.shadowRadius = 8
self.backgroundView.layer.shadowOpacity = 0.382
self.itemsView.axis = .vertical
self.itemsView.spacing = 20
for item in self.items {
item.site = self.site
self.itemsView.addArrangedSubview( item.view )
}
self.tableView.delegate = self
self.tableView.dataSource = self
self.tableView.separatorStyle = .none
self.tableView.layer.cornerRadius = 8
self.tableView.registerCell( Cell.self )
let tableViewEffect = UIView( containing: self.tableView, withLayoutMargins: .zero )!
tableViewEffect.layer.shadowRadius = 8
tableViewEffect.layer.shadowOpacity = 0.382
self.closeButton.button.addTarget( self, action: #selector( close ), for: .touchUpInside )
// - Hierarchy
self.view.addSubview( tableViewEffect )
self.view.addSubview( self.backgroundView )
self.backgroundView.addSubview( self.itemsView )
self.view.addSubview( self.closeButton )
// - Layout
ViewConfiguration( view: tableViewEffect )
ViewConfiguration( view: self.backgroundView )
.constrainTo { $1.topAnchor.constraint( equalTo: $0.topAnchor ) }
.constrainTo { $1.leadingAnchor.constraint( equalTo: $0.leadingAnchor ) }
.constrainTo { $1.trailingAnchor.constraint( equalTo: $0.trailingAnchor ) }
.constrainTo { $1.bottomAnchor.constraint( lessThanOrEqualTo: $0.bottomAnchor ) }
.activate()
ViewConfiguration( view: self.itemsView )
.constrainToSuperview()
.activate()
ViewConfiguration( view: self.closeButton )
.constrainTo { $1.centerXAnchor.constraint( equalTo: tableViewEffect.centerXAnchor ) }
.constrainTo { $1.centerYAnchor.constraint( equalTo: tableViewEffect.bottomAnchor ) }
.constrainTo { $1.centerXAnchor.constraint( equalTo: self.backgroundView.centerXAnchor ) }
.constrainTo { $1.centerYAnchor.constraint( equalTo: self.backgroundView.bottomAnchor ) }
.constrainTo { $1.bottomAnchor.constraint( equalTo: $0.bottomAnchor ) }
.activate()
}
......@@ -69,63 +77,16 @@ class MPSiteDetailViewController: UIViewController, UITableViewDelegate, UITable
self.observers.notify { $0.siteDetailShouldDismiss() }
}
// MARK: - UITableViewDelegate
// MARK: - UITableViewDataSource
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = Cell.dequeue( from: tableView, indexPath: indexPath ),
item = self.items[indexPath.item]
item.site = self.site
cell.item = item
return cell
}
// MARK: - MPSiteObserver
func siteDidChange() {
PearlMainQueue {
self.tableView.backgroundColor = self.site.color
self.backgroundView.backgroundColor = self.site.color
}
}
// MARK: - Types
class Cell: UITableViewCell {
var item: Item? {
willSet {
if let item = self.item {
item.view.removeFromSuperview()
}
}
didSet {
if let item = self.item {
self.contentView.addSubview( item.view )
ViewConfiguration( view: item.view )
.constrainToSuperview()
.activate()
}
}
}
required init?(coder aDecoder: NSCoder) {
fatalError( "init(coder:) is not supported for this class" )
}
override init(style: CellStyle, reuseIdentifier: String?) {
super.init( style: style, reuseIdentifier: reuseIdentifier )
self.backgroundColor = .clear
}
}
class Item: MPSiteObserver {
let title: String?
var subitems = [ Item ]()
......
......@@ -97,15 +97,23 @@ class MPSitesViewController: UIViewController, UITextFieldDelegate, MPSiteHeader
ViewConfiguration( view: self.siteDetailView )
.constrainTo { $1.leadingAnchor.constraint( equalTo: self.sitesTableView.leadingAnchor ) }
.constrainTo { $1.trailingAnchor.constraint( equalTo: self.sitesTableView.trailingAnchor ) }
.constrainTo { $1.heightAnchor.constraint( equalTo: self.sitesTableView.heightAnchor ) }
.activate()
ViewConfiguration( view: self.topContainer )
.constrainTo { $1.topAnchor.constraint( greaterThanOrEqualTo: $0.layoutMarginsGuide.topAnchor, constant: 8 ) }
.constrainTo { $1.topAnchor.constraint( greaterThanOrEqualTo: self.siteHeaderView.layoutMarginsGuide.bottomAnchor ) }
.constrainTo { $1.leadingAnchor.constraint( equalTo: $0.layoutMarginsGuide.leadingAnchor, constant: 8 ) }
.constrainTo { $1.trailingAnchor.constraint( equalTo: $0.layoutMarginsGuide.trailingAnchor, constant: -8 ) }
.constrainTo { $1.heightAnchor.constraint( equalToConstant: 50 ) }
.constrainToAll {
[
$1.topAnchor.constraint( greaterThanOrEqualTo: $0.layoutMarginsGuide.topAnchor, constant: 8 ),
$1.topAnchor.constraint( equalTo: $0.layoutMarginsGuide.topAnchor, constant: 8 )
.updatePriority( UILayoutPriority( 500 ) ),
$1.topAnchor.constraint( greaterThanOrEqualTo: self.siteHeaderView.layoutMarginsGuide.bottomAnchor )
.updatePriority( UILayoutPriority( 510 ) ),
$1.bottomAnchor.constraint( lessThanOrEqualTo: self.siteDetailView.topAnchor )
.updatePriority( UILayoutPriority( 520 ) ),
$1.leadingAnchor.constraint( equalTo: $0.layoutMarginsGuide.leadingAnchor, constant: 8 ),
$1.trailingAnchor.constraint( equalTo: $0.layoutMarginsGuide.trailingAnchor, constant: -8 ),
$1.heightAnchor.constraint( equalToConstant: 50 ),
]
}
.activate()
self.siteHeaderConfiguration
......@@ -116,7 +124,7 @@ class MPSitesViewController: UIViewController, UITextFieldDelegate, MPSiteHeader
self.siteDetailConfiguration
.apply( ViewConfiguration( view: self.siteDetailView )
.constrainTo { $1.topAnchor.constraint( equalTo: self.sitesTableView.topAnchor ) }, active: true )
.constrainTo { $1.bottomAnchor.constraint( equalTo: self.sitesTableView.bottomAnchor ) }, active: true )
.apply( ViewConfiguration( view: self.siteDetailView )
.constrainTo { $1.topAnchor.constraint( equalTo: self.sitesTableView.bottomAnchor ) }, active: false )
......@@ -134,9 +142,9 @@ class MPSitesViewController: UIViewController, UITextFieldDelegate, MPSiteHeader
top: max( 0, top - self.sitesTableView.bounds.origin.y ), left: 0, bottom: 0, right: 0 )
// Offset detail view's top margin to make space for the top container.
self.siteDetailController?.tableView.contentInset = UIEdgeInsets(
top: CGRectGetBottom( self.siteDetailView.convert( self.topContainer.bounds, from: self.topContainer ) ).y,
left: 0, bottom: 0, right: 0 )
// self.siteDetailController?.tableView.contentInset = UIEdgeInsets(
// top: CGRectGetBottom( self.siteDetailView.convert( self.topContainer.bounds, from: self.topContainer ) ).y,
// left: 0, bottom: 0, right: 0 )
}
override var preferredStatusBarStyle: UIStatusBarStyle {
......
......@@ -72,6 +72,7 @@ CF_IMPLICIT_BRIDGING_ENABLED
* @param constraintBlock \c $0 superview; \c $1 configuration view
*/
- (instancetype)constrainToUsing:(NSLayoutConstraint *( ^ )(UIView *superview, UIView *view))constraintBlock;
- (instancetype)constrainToAllUsing:(NSArray<NSLayoutConstraint *> *( ^ )(UIView *superview, UIView *view))constraintBlock;
- (instancetype)constrainToView:(UIView *__nullable)view;
- (instancetype)constrainToMarginsOfView:(UIView *__nullable)view;
- (instancetype)constrainToView:(UIView *__nullable)view withMargins:(BOOL)margins forAttributes:(NSLayoutFormatOptions)attributes;
......
......@@ -346,6 +346,14 @@
return [self constrainTo:constraintBlock( self.view.superview, self.view )];
}
- (instancetype)constrainToAllUsing:(NSArray<NSLayoutConstraint *> *( ^ )(UIView *superview, UIView *view))constraintBlock {
for (NSLayoutConstraint *constraint in constraintBlock( self.view.superview, self.view ))
[self constrainTo:constraint];
return self;
}
- (instancetype)constrainToView:(UIView *__nullable)view {
return [self constrainToView:view withMargins:NO forAttributes:
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment