Commit f3a049c3 by Daniel Dahan

working NavigationBarView with orientation changes on iPad

parent e85b4f14
......@@ -55,11 +55,6 @@ class AppSearchBarViewController: SearchBarViewController {
sideNavigationViewController?.enabled = false
}
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
searchBarView.textField.becomeFirstResponder()
}
/// Toggle SideSearchViewController left UIViewController.
internal func handleBackButton() {
searchBarView.textField.resignFirstResponder()
......@@ -84,8 +79,8 @@ class AppSearchBarViewController: SearchBarViewController {
var image = UIImage(named: "ic_close_white")?.imageWithRenderingMode(.AlwaysTemplate)
let clearButton: FlatButton = FlatButton()
clearButton.pulseColor = MaterialColor.grey.darken4
clearButton.pulseScale = false
clearButton.pulseColor = MaterialColor.grey.darken4
clearButton.tintColor = MaterialColor.grey.darken4
clearButton.setImage(image, forState: .Normal)
clearButton.setImage(image, forState: .Highlighted)
......@@ -93,8 +88,8 @@ class AppSearchBarViewController: SearchBarViewController {
// Back button.
image = UIImage(named: "ic_arrow_back_white")?.imageWithRenderingMode(.AlwaysTemplate)
let backButton: FlatButton = FlatButton()
backButton.pulseColor = MaterialColor.grey.darken4
backButton.pulseScale = false
backButton.pulseColor = MaterialColor.grey.darken4
backButton.tintColor = MaterialColor.grey.darken4
backButton.setImage(image, forState: .Normal)
backButton.setImage(image, forState: .Highlighted)
......@@ -103,14 +98,13 @@ class AppSearchBarViewController: SearchBarViewController {
// More button.
image = UIImage(named: "ic_more_horiz_white")?.imageWithRenderingMode(.AlwaysTemplate)
let moreButton: FlatButton = FlatButton()
moreButton.pulseColor = MaterialColor.grey.darken4
moreButton.pulseScale = false
moreButton.pulseColor = MaterialColor.grey.darken4
moreButton.tintColor = MaterialColor.grey.darken4
moreButton.setImage(image, forState: .Normal)
moreButton.setImage(image, forState: .Highlighted)
moreButton.addTarget(self, action: "handleMoreButton", forControlEvents: .TouchUpInside)
searchBarView.delegate = self
searchBarView.placeholder = "Search"
searchBarView.tintColor = MaterialColor.grey.darken4
searchBarView.textColor = MaterialColor.grey.darken4
......@@ -136,7 +130,6 @@ extension AppSearchBarViewController: TextFieldDelegate {
extension AppSearchBarViewController: SideNavigationViewControllerDelegate {
func sideNavigationViewDidClose(sideNavigationViewController: SideNavigationViewController, position: SideNavigationPosition) {
searchBarView.textField.becomeFirstResponder()
sideNavigationViewController.enabled = false
}
}
......@@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
9656264C1C879AE0004ADEF7 /* Material.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9656264B1C879AE0004ADEF7 /* Material.framework */; };
9656264D1C879AE0004ADEF7 /* Material.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9656264B1C879AE0004ADEF7 /* Material.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
96A71F081C718F8800C0C4AE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96A71F071C718F8800C0C4AE /* AppDelegate.swift */; };
96A71F0A1C718F8800C0C4AE /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96A71F091C718F8800C0C4AE /* ViewController.swift */; };
96A71F0F1C718F8800C0C4AE /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 96A71F0E1C718F8800C0C4AE /* Assets.xcassets */; };
......@@ -20,6 +22,7 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
9656264D1C879AE0004ADEF7 /* Material.framework in Embed Frameworks */,
);
name = "Embed Frameworks";
runOnlyForDeploymentPostprocessing = 0;
......@@ -27,6 +30,7 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
9656264B1C879AE0004ADEF7 /* Material.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; name = Material.framework; path = "/Users/danieldahan/Library/Developer/Xcode/DerivedData/Material-hbpnflxhoouqxebjcyhbbhqyesjd/Build/Products/Debug-iphoneos/Material.framework"; sourceTree = "<absolute>"; };
96A71F041C718F8800C0C4AE /* SearchBarView.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = SearchBarView.app; sourceTree = BUILT_PRODUCTS_DIR; };
96A71F071C718F8800C0C4AE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
96A71F091C718F8800C0C4AE /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
......@@ -40,6 +44,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9656264C1C879AE0004ADEF7 /* Material.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
......@@ -49,6 +54,7 @@
96A71EFB1C718F8800C0C4AE = {
isa = PBXGroup;
children = (
9656264B1C879AE0004ADEF7 /* Material.framework */,
96A71F061C718F8800C0C4AE /* SearchBarView */,
96A71F051C718F8800C0C4AE /* Products */,
);
......
......@@ -37,7 +37,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame: MaterialDevice.bounds)
window = UIWindow(frame: UIScreen.mainScreen().bounds)
window!.rootViewController = ViewController()
window!.makeKeyAndVisible()
return true
......
......@@ -57,8 +57,8 @@ class ViewController: UIViewController {
var image = UIImage(named: "ic_close_white")?.imageWithRenderingMode(.AlwaysTemplate)
let clearButton: FlatButton = FlatButton()
clearButton.pulseColor = MaterialColor.blueGrey.darken4
clearButton.pulseScale = false
clearButton.pulseColor = MaterialColor.blueGrey.darken4
clearButton.tintColor = MaterialColor.blueGrey.darken4
clearButton.setImage(image, forState: .Normal)
clearButton.setImage(image, forState: .Highlighted)
......@@ -66,8 +66,8 @@ class ViewController: UIViewController {
// Back button.
image = UIImage(named: "ic_arrow_back_white")?.imageWithRenderingMode(.AlwaysTemplate)
let backButton: FlatButton = FlatButton()
backButton.pulseColor = MaterialColor.blueGrey.darken4
backButton.pulseScale = false
backButton.pulseColor = MaterialColor.blueGrey.darken4
backButton.tintColor = MaterialColor.blueGrey.darken4
backButton.setImage(image, forState: .Normal)
backButton.setImage(image, forState: .Highlighted)
......@@ -78,8 +78,8 @@ class ViewController: UIViewController {
// More button.
image = UIImage(named: "ic_more_horiz_white")?.imageWithRenderingMode(.AlwaysTemplate)
let moreButton: FlatButton = FlatButton()
moreButton.pulseColor = MaterialColor.blueGrey.darken4
moreButton.pulseScale = false
moreButton.pulseColor = MaterialColor.blueGrey.darken4
moreButton.tintColor = MaterialColor.blueGrey.darken4
moreButton.setImage(image, forState: .Normal)
moreButton.setImage(image, forState: .Highlighted)
......
......@@ -54,7 +54,7 @@ public class ControlView : MaterialView {
/// A preset wrapper around spacing.
public var spacingPreset: MaterialSpacing = .None {
didSet {
grid.spacing = MaterialSpacingToValue(spacingPreset)
spacing = MaterialSpacingToValue(spacingPreset)
}
}
......@@ -109,7 +109,7 @@ public class ControlView : MaterialView {
- Parameter rightControls: An Array of UIControls that go on the right side.
*/
public convenience init?(leftControls: Array<UIControl>? = nil, rightControls: Array<UIControl>? = nil) {
self.init(frame: CGRectNull)
self.init(frame: CGRectZero)
prepareProperties(leftControls, rightControls: rightControls)
}
......@@ -125,13 +125,10 @@ public class ControlView : MaterialView {
/// Reloads the view.
public func reloadView() {
// clear constraints so new ones do not conflict
removeConstraints(constraints)
for v in subviews {
if v != contentView {
v.removeFromSuperview()
}
}
if 0 < width {
// Size of single grid column.
if let g: CGFloat = width / CGFloat(0 < grid.axis.columns ? grid.axis.columns : 1) {
......@@ -154,6 +151,7 @@ public class ControlView : MaterialView {
}
}
addSubview(contentView)
grid.views?.append(contentView)
// rightControls
......@@ -193,7 +191,6 @@ public class ControlView : MaterialView {
/// Prepares the contentView.
public func prepareContentView() {
contentView.backgroundColor = nil
addSubview(contentView)
}
/**
......
......@@ -180,7 +180,15 @@ public class MaterialButton : UIButton {
}
/// Enables automatic shadowPath sizing.
public var shadowPathAutoSizeEnabled: Bool = false
public var shadowPathAutoSizeEnabled: Bool = false {
didSet {
if shadowPathAutoSizeEnabled {
layoutShadowPath()
} else {
shadowPath = nil
}
}
}
/**
A property that sets the shadowOffset, shadowOpacity, and shadowRadius
......
......@@ -235,7 +235,15 @@ public class MaterialCollectionViewCell : UICollectionViewCell {
}
/// Enables automatic shadowPath sizing.
public var shadowPathAutoSizeEnabled: Bool = false
public var shadowPathAutoSizeEnabled: Bool = false {
didSet {
if shadowPathAutoSizeEnabled {
layoutShadowPath()
} else {
shadowPath = nil
}
}
}
/**
A property that sets the shadowOffset, shadowOpacity, and shadowRadius
......
......@@ -155,7 +155,15 @@ public class MaterialLayer : CAShapeLayer {
}
/// Enables automatic shadowPath sizing.
public var shadowPathAutoSizeEnabled: Bool = false
public var shadowPathAutoSizeEnabled: Bool = false {
didSet {
if shadowPathAutoSizeEnabled {
layoutShadowPath()
} else {
shadowPath = nil
}
}
}
/**
A property that sets the shadowOffset, shadowOpacity, and shadowRadius
......
......@@ -167,24 +167,6 @@ public class MaterialSwitch: UIControl {
}
}
public override var selected: Bool {
get {
return .On == internalSwitchState
}
set(value) {
setOn(value, animated: true)
}
}
public override var highlighted: Bool {
get {
return .On == internalSwitchState
}
set(value) {
setOn(value, animated: true)
}
}
/// A boolean indicating if the switch is on or not.
public var on: Bool {
get {
......@@ -195,13 +177,6 @@ public class MaterialSwitch: UIControl {
}
}
public override var state: UIControlState {
if enabled {
return selected ? [.Selected, .Highlighted] : [.Normal]
}
return selected ? [.Selected, .Highlighted, .Disabled] : [.Normal, .Disabled]
}
/// MaterialSwitch state.
public var switchState: MaterialSwitchState {
get {
......
......@@ -173,7 +173,15 @@ public class MaterialTableViewCell: UITableViewCell {
}
/// Enables automatic shadowPath sizing.
public var shadowPathAutoSizeEnabled: Bool = false
public var shadowPathAutoSizeEnabled: Bool = false {
didSet {
if shadowPathAutoSizeEnabled {
layoutShadowPath()
} else {
shadowPath = nil
}
}
}
/**
A property that sets the shadowOffset, shadowOpacity, and shadowRadius
......
......@@ -223,7 +223,15 @@ public class MaterialView : UIView {
}
/// Enables automatic shadowPath sizing.
public var shadowPathAutoSizeEnabled: Bool = false
public var shadowPathAutoSizeEnabled: Bool = false {
didSet {
if shadowPathAutoSizeEnabled {
layoutShadowPath()
} else {
shadowPath = nil
}
}
}
/**
A property that sets the shadowOffset, shadowOpacity, and shadowRadius
......
......@@ -56,6 +56,11 @@ public class NavigationBarView : StatusBarView {
}
}
/// A convenience initializer.
public convenience init() {
self.init(frame: CGRectZero)
}
/**
A convenience initializer with parameter settings.
- Parameter titleLabel: UILabel for the title.
......@@ -64,7 +69,7 @@ public class NavigationBarView : StatusBarView {
- Parameter rightControls: An Array of UIControls that go on the right side.
*/
public convenience init?(titleLabel: UILabel? = nil, detailLabel: UILabel? = nil, leftControls: Array<UIControl>? = nil, rightControls: Array<UIControl>? = nil) {
self.init(frame: CGRectMake(0, 0, MaterialDevice.bounds.width, 64))
self.init(frame: CGRectZero)
prepareProperties(titleLabel, detailLabel: detailLabel, leftControls: leftControls, rightControls: rightControls)
}
......@@ -102,6 +107,7 @@ public class NavigationBarView : StatusBarView {
/// Reloads the view.
public override func reloadView() {
super.reloadView()
if 0 < width {
contentView.grid.views = []
if let v: UILabel = titleLabel {
contentView.grid.views?.append(v)
......@@ -111,10 +117,6 @@ public class NavigationBarView : StatusBarView {
}
contentView.grid.reloadLayout()
}
/// Called when the NavigationBarView changes size.
public override func statusBarViewDidChangeLayout() {
(delegate as? NavigationBarViewDelegate)?.navigationBarViewDidChangeLayout?(self)
}
/**
......
......@@ -65,6 +65,36 @@ public protocol NavigationBarViewControllerDelegate : MaterialDelegate {
@objc(NavigationBarViewController)
public class NavigationBarViewController: StatusBarViewController {
/// The height of the StatusBar.
public override var heightForStatusBar: CGFloat {
get {
return navigationBarView.heightForStatusBar
}
set(value) {
navigationBarView.heightForStatusBar = value
}
}
/// The height when in Portrait orientation mode.
public override var heightForPortraitOrientation: CGFloat {
get {
return navigationBarView.heightForPortraitOrientation
}
set(value) {
navigationBarView.heightForPortraitOrientation = value
}
}
/// The height when in Landscape orientation mode.
public override var heightForLandscapeOrientation: CGFloat {
get {
return navigationBarView.heightForLandscapeOrientation
}
set(value) {
navigationBarView.heightForLandscapeOrientation = value
}
}
/// Internal reference to the floatingViewController.
private var internalFloatingViewController: UIViewController?
......
......@@ -82,7 +82,13 @@ public class SearchBarView : StatusBarView {
/// A convenience initializer.
public convenience init() {
self.init(frame: CGRectMake(0, 0, MaterialDevice.bounds.width, 64))
self.init(frame: CGRectZero)
}
public override func reloadView() {
super.reloadView()
contentView.grid.views = [textField]
textField.reloadView()
}
/**
......@@ -97,17 +103,11 @@ public class SearchBarView : StatusBarView {
prepareTextField()
}
/// Called when the SearchBarView changes size.
public override func statusBarViewDidChangeLayout() {
(delegate as? SearchBarViewDelegate)?.searchBarViewDidChangeLayout?(self)
}
/// Prepares the textField.
private func prepareTextField() {
textField.placeholder = "Search"
textField.backgroundColor = MaterialColor.clear
textField.clearButtonMode = .WhileEditing
contentView.addSubview(textField)
contentView.grid.views = [textField]
}
}
......@@ -49,14 +49,39 @@ public extension UIViewController {
}
public class SearchBarViewController: StatusBarViewController {
/// Reference to the SearchBarView.
public private(set) lazy var searchBarView: SearchBarView = SearchBarView()
/// The height of the StatusBar.
public override var heightForStatusBar: CGFloat {
get {
return searchBarView.heightForStatusBar
}
set(value) {
searchBarView.heightForStatusBar = value
}
}
public override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
layoutSubviews()
/// The height when in Portrait orientation mode.
public override var heightForPortraitOrientation: CGFloat {
get {
return searchBarView.heightForPortraitOrientation
}
set(value) {
searchBarView.heightForPortraitOrientation = value
}
}
/// The height when in Landscape orientation mode.
public override var heightForLandscapeOrientation: CGFloat {
get {
return searchBarView.heightForLandscapeOrientation
}
set(value) {
searchBarView.heightForLandscapeOrientation = value
}
}
/// Reference to the SearchBarView.
public private(set) lazy var searchBarView: SearchBarView = SearchBarView()
/**
Prepares the view instance when intialized. When subclassing,
it is recommended to override the prepareView method
......@@ -71,22 +96,7 @@ public class SearchBarViewController: StatusBarViewController {
/// Prepares the SearchBarView.
private func prepareSearchBarView() {
searchBarView.delegate = self
searchBarView.zPosition = 1000
view.addSubview(searchBarView)
}
/// Layout subviews.
private func layoutSubviews() {
let size: CGSize = MaterialDevice.bounds.size
let h: CGFloat = UIApplication.sharedApplication().statusBarFrame.size.height
mainViewController.view.frame = CGRectMake(0, searchBarView.height, size.width, size.height - searchBarView.height - (20 >= h ? 0 : h - 20))
}
}
extension SearchBarViewController : SearchBarViewDelegate {
/// Monitor layout changes.
public func searchBarViewDidChangeLayout(searchBarView: SearchBarView) {
layoutSubviews()
}
}
......@@ -373,7 +373,6 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
}
if animated {
v.shadowPath = nil
v.shadowPathAutoSizeEnabled = false
if hidden {
......@@ -406,7 +405,6 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
v.position.x = -v.width / 2
mainViewController.view.alpha = 1
} else {
v.shadowPath = nil
v.shadowPathAutoSizeEnabled = false
showView(v)
......@@ -439,7 +437,6 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
}
if animated {
v.shadowPath = nil
v.shadowPathAutoSizeEnabled = false
if hidden {
......@@ -472,7 +469,6 @@ public class SideNavigationViewController: UIViewController, UIGestureRecognizer
v.position.x = view.bounds.width + v.width / 2
mainViewController.view.alpha = 1
} else {
v.shadowPath = nil
v.shadowPathAutoSizeEnabled = false
showView(v)
......
......@@ -31,8 +31,14 @@
import UIKit
public class StatusBarView : ControlView {
/// Tracks the old frame size.
private var oldFrame: CGRect?
/// The height of the StatusBar.
public var heightForStatusBar: CGFloat = 20
/// The height when in Portrait orientation mode.
public var heightForPortraitOrientation: CGFloat = 64
/// The height when in Landscape orientation mode.
public var heightForLandscapeOrientation: CGFloat = 44
/// Device status bar style.
public var statusBarStyle: UIStatusBarStyle = UIApplication.sharedApplication().statusBarStyle {
......@@ -41,46 +47,45 @@ public class StatusBarView : ControlView {
}
}
/// A convenience initializer.
public convenience init() {
self.init(frame: CGRectZero)
}
/**
A convenience initializer with parameter settings.
- Parameter leftControls: An Array of UIControls that go on the left side.
- Parameter rightControls: An Array of UIControls that go on the right side.
*/
public convenience init?(leftControls: Array<UIControl>? = nil, rightControls: Array<UIControl>? = nil) {
self.init(frame: CGRectMake(0, 0, MaterialDevice.width, 64))
self.init(frame: CGRectZero)
prepareProperties(leftControls, rightControls: rightControls)
}
/// A convenience initializer.
public convenience init() {
self.init(frame: CGRectMake(0, 0, MaterialDevice.width, 64))
}
public override func layoutSubviews() {
super.layoutSubviews()
// Ensures a width.
if 1 > width {
width = MaterialDevice.width
}
grid.axis.columns = Int(width / 48)
// General alignment.
if .iPhone == MaterialDevice.type && MaterialDevice.landscape {
grid.contentInset.top = 8
height = 44
height = heightForLandscapeOrientation
} else {
grid.contentInset.top = 28
height = 64
grid.contentInset.top = heightForStatusBar + 8
height = heightForPortraitOrientation
}
reloadView()
if frame.origin.x != oldFrame!.origin.x || frame.origin.y != oldFrame!.origin.y || frame.width != oldFrame!.width || frame.height != oldFrame!.height {
oldFrame = frame
if nil != delegate {
statusBarViewDidChangeLayout()
}
}
}
public override func intrinsicContentSize() -> CGSize {
return CGSizeMake(MaterialDevice.width, .iPhone == MaterialDevice.type && MaterialDevice.landscape ? 44 : 64)
return CGSizeMake(MaterialDevice.width, .iPhone == MaterialDevice.type && MaterialDevice.landscape ? heightForLandscapeOrientation : heightForPortraitOrientation)
}
/**
......@@ -93,12 +98,8 @@ public class StatusBarView : ControlView {
public override func prepareView() {
super.prepareView()
depth = .Depth1
oldFrame = frame
grid.spacingPreset = .Spacing2
grid.contentInsetPreset = .Square2
spacingPreset = .Spacing2
contentInsetPreset = .Square2
autoresizingMask = .FlexibleWidth
}
/// Chaining method for subclasses to offer delegation or other useful features.
public func statusBarViewDidChangeLayout() {}
}
......@@ -31,6 +31,15 @@
import UIKit
public class StatusBarViewController: UIViewController {
/// The height of the StatusBar.
public var heightForStatusBar: CGFloat = 20
/// The height when in Portrait orientation mode.
public var heightForPortraitOrientation: CGFloat = 64
/// The height when in Landscape orientation mode.
public var heightForLandscapeOrientation: CGFloat = 44
/**
A Boolean property used to enable and disable interactivity
with the mainViewController.
......@@ -114,15 +123,15 @@ public class StatusBarViewController: UIViewController {
/// Layout subviews.
private func layoutSubviews() {
let size: CGSize = MaterialDevice.bounds.size
let h: CGFloat = UIApplication.sharedApplication().statusBarFrame.size.height
let h: CGFloat = MaterialDevice.height
let q: CGFloat = UIApplication.sharedApplication().statusBarFrame.size.height
if .iPhone == MaterialDevice.type && MaterialDevice.landscape {
mainViewController.view.frame.origin.y = 44
mainViewController.view.frame.size.height = size.height - (20 >= h ? 44 : h - 64)
mainViewController.view.frame.origin.y = heightForLandscapeOrientation
mainViewController.view.frame.size.height = h - (heightForStatusBar >= q ? heightForLandscapeOrientation : q - heightForStatusBar - heightForLandscapeOrientation)
} else {
mainViewController.view.frame.origin.y = 64
mainViewController.view.frame.size.height = size.height - (20 >= h ? 64 : h - 84)
mainViewController.view.frame.origin.y = heightForPortraitOrientation
mainViewController.view.frame.size.height = h - (heightForStatusBar >= q ? heightForPortraitOrientation : q - heightForStatusBar - heightForPortraitOrientation)
}
}
......
......@@ -159,7 +159,15 @@ public class TextField : UITextField {
}
/// Enables automatic shadowPath sizing.
public var shadowPathAutoSizeEnabled: Bool = false
public var shadowPathAutoSizeEnabled: Bool = false {
didSet {
if shadowPathAutoSizeEnabled {
layoutShadowPath()
} else {
shadowPath = nil
}
}
}
/**
A property that sets the shadowOffset, shadowOpacity, and shadowRadius
......
......@@ -161,7 +161,15 @@ public class TextView: UITextView {
}
/// Enables automatic shadowPath sizing.
public var shadowPathAutoSizeEnabled: Bool = false
public var shadowPathAutoSizeEnabled: Bool = false {
didSet {
if shadowPathAutoSizeEnabled {
layoutShadowPath()
} else {
shadowPath = nil
}
}
}
/**
A property that sets the shadowOffset, shadowOpacity, and shadowRadius
......
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