Marino Faggiana 6 năm trước cách đây
mục cha
commit
e2aaf0eaf2

+ 26 - 0
Nextcloud.xcodeproj/project.pbxproj

@@ -279,6 +279,10 @@
 		F750374D1DBFA91A008FB480 /* ALView+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = F75037441DBFA91A008FB480 /* ALView+PureLayout.m */; };
 		F750374F1DBFA91A008FB480 /* NSArray+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = F75037461DBFA91A008FB480 /* NSArray+PureLayout.m */; };
 		F75037511DBFA91A008FB480 /* NSLayoutConstraint+PureLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = F75037481DBFA91A008FB480 /* NSLayoutConstraint+PureLayout.m */; };
+		F754EEC921772B6100BB1CDF /* DropdownItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = F754EEC421772B6100BB1CDF /* DropdownItem.swift */; };
+		F754EECA21772B6100BB1CDF /* DropUpMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F754EEC521772B6100BB1CDF /* DropUpMenu.swift */; };
+		F754EECB21772B6100BB1CDF /* DropdownMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = F754EEC721772B6100BB1CDF /* DropdownMenu.swift */; };
+		F754EECC21772B6100BB1CDF /* SectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = F754EEC821772B6100BB1CDF /* SectionHeader.swift */; };
 		F755BD9B20594AC7008C5FBB /* NCService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F755BD9A20594AC7008C5FBB /* NCService.swift */; };
 		F758B3E1212C4A6C00515F55 /* PDFPageRenderable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F758B3D9212C4A6C00515F55 /* PDFPageRenderable.swift */; };
 		F758B3E2212C4A6C00515F55 /* DPIType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F758B3DA212C4A6C00515F55 /* DPIType.swift */; };
@@ -1113,6 +1117,11 @@
 		F7540F2A1D5B238600C3FFA8 /* x509.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x509.h; sourceTree = "<group>"; };
 		F7540F2B1D5B238600C3FFA8 /* x509_vfy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x509_vfy.h; sourceTree = "<group>"; };
 		F7540F2C1D5B238600C3FFA8 /* x509v3.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x509v3.h; sourceTree = "<group>"; };
+		F754EEC421772B6100BB1CDF /* DropdownItem.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropdownItem.swift; sourceTree = "<group>"; };
+		F754EEC521772B6100BB1CDF /* DropUpMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropUpMenu.swift; sourceTree = "<group>"; };
+		F754EEC621772B6100BB1CDF /* DropdownMenu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DropdownMenu.h; sourceTree = "<group>"; };
+		F754EEC721772B6100BB1CDF /* DropdownMenu.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DropdownMenu.swift; sourceTree = "<group>"; };
+		F754EEC821772B6100BB1CDF /* SectionHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SectionHeader.swift; sourceTree = "<group>"; };
 		F755BD9A20594AC7008C5FBB /* NCService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NCService.swift; sourceTree = "<group>"; };
 		F758B3D9212C4A6C00515F55 /* PDFPageRenderable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PDFPageRenderable.swift; sourceTree = "<group>"; };
 		F758B3DA212C4A6C00515F55 /* DPIType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DPIType.swift; sourceTree = "<group>"; };
@@ -2341,6 +2350,18 @@
 			path = openssl;
 			sourceTree = "<group>";
 		};
+		F754EEC321772B6100BB1CDF /* DropdownMenu */ = {
+			isa = PBXGroup;
+			children = (
+				F754EEC421772B6100BB1CDF /* DropdownItem.swift */,
+				F754EEC521772B6100BB1CDF /* DropUpMenu.swift */,
+				F754EEC621772B6100BB1CDF /* DropdownMenu.h */,
+				F754EEC721772B6100BB1CDF /* DropdownMenu.swift */,
+				F754EEC821772B6100BB1CDF /* SectionHeader.swift */,
+			);
+			path = DropdownMenu;
+			sourceTree = "<group>";
+		};
 		F758B3D8212C4A6C00515F55 /* PDFGenerator */ = {
 			isa = PBXGroup;
 			children = (
@@ -3294,6 +3315,7 @@
 			children = (
 				F72AAEC11E5C60C700BB17E1 /* AHKActionSheet */,
 				F73CC0571E813DFF006E3047 /* BKPasscodeView */,
+				F754EEC321772B6100BB1CDF /* DropdownMenu */,
 				F7F54CAD1E5B14C700E19C62 /* MWPhotoBrowser */,
 				F7B4F1C51F44356F00B53B42 /* NCUchardet */,
 				F762CB7B1EACB81000B38484 /* REMenu */,
@@ -4060,6 +4082,7 @@
 				F70022A41EC4C9100080073F /* AFNetworkReachabilityManager.m in Sources */,
 				F762CAFD1EACB66200B38484 /* XLFormInlineSelectorCell.m in Sources */,
 				F77B0DF21D118A16002130FE /* CCUploadFromOtherUpp.m in Sources */,
+				F754EECB21772B6100BB1CDF /* DropdownMenu.swift in Sources */,
 				F758B450212C516300515F55 /* RectangleDetector.swift in Sources */,
 				F77B0DF41D118A16002130FE /* CCMain.m in Sources */,
 				F7E9C41B20F4CA870040CF18 /* CCTransfers.m in Sources */,
@@ -4073,6 +4096,7 @@
 				F73B4F041F470D9100BBEE4B /* nsBig5Prober.cpp in Sources */,
 				F73B4EEF1F470D9100BBEE4B /* CharDistribution.cpp in Sources */,
 				F7B0C0CD1EE7E7750033AC24 /* CCSynchronize.m in Sources */,
+				F754EEC921772B6100BB1CDF /* DropdownItem.swift in Sources */,
 				F77B0DFF1D118A16002130FE /* OCNetworking.m in Sources */,
 				F7622FC82175FCC0000383FF /* ActionSheetOkButton.swift in Sources */,
 				F758B440212C516300515F55 /* CaptureSessionManager.swift in Sources */,
@@ -4086,6 +4110,7 @@
 				F762CB041EACB66200B38484 /* XLFormSwitchCell.m in Sources */,
 				F712AC9E2175E56F0061158E /* CTAssetThumbnailOverlay.m in Sources */,
 				F73B4F0F1F470D9100BBEE4B /* nsMBCSSM.cpp in Sources */,
+				F754EECA21772B6100BB1CDF /* DropUpMenu.swift in Sources */,
 				F712ACA52175E56F0061158E /* CTAssetThumbnailView.m in Sources */,
 				F77B0E031D118A16002130FE /* CCShareInfoCMOC.m in Sources */,
 				F77B0E041D118A16002130FE /* UIImage+animatedGIF.m in Sources */,
@@ -4272,6 +4297,7 @@
 				F762CB121EACB66200B38484 /* UIView+XLFormAdditions.m in Sources */,
 				F70BFC7420E0FA7D00C67599 /* NCUtility.swift in Sources */,
 				F73CC06F1E813DFF006E3047 /* BKPasscodeInputView.m in Sources */,
+				F754EECC21772B6100BB1CDF /* SectionHeader.swift in Sources */,
 				F73CC0751E813DFF006E3047 /* BKPasscodeViewController.m in Sources */,
 				F750374D1DBFA91A008FB480 /* ALView+PureLayout.m in Sources */,
 				F7659A2E1DC0B72F004860C4 /* EARestrictedScrollView.m in Sources */,

BIN
iOSClient/Images.xcassets/trash.imageset/trash.png


BIN
iOSClient/Images.xcassets/trash.imageset/trash@2x.png


BIN
iOSClient/Images.xcassets/trash.imageset/trash@3x.png


+ 285 - 0
iOSClient/Library/DropdownMenu/DropUpMenu.swift

@@ -0,0 +1,285 @@
+//
+//  DropUpMenu.swift
+//  DropUpMenu
+//
+//  Created by Suric on 16/8/11.
+//  Copyright © 2016年 teambition. All rights reserved.
+//
+
+import UIKit
+
+public protocol DropUpMenuDelegate: class {
+    func dropUpMenu(_ dropUpMenu: DropUpMenu, cellForRowAt indexPath: IndexPath) -> UITableViewCell?
+    func dropUpMenu(_ dropUpMenu: DropUpMenu, didSelectRowAt indexPath: IndexPath)
+    func dropUpMenuCancel(_ dropUpMenu: DropUpMenu)
+    func dropUpMenuWillDismiss(_ dropUpMenu: DropUpMenu)
+    func dropUpMenuWillShow(_ dropUpMenu: DropUpMenu)
+}
+
+public extension DropUpMenuDelegate {
+    func dropUpMenu(_ dropUpMenu: DropUpMenu, cellForRowAt indexPath: IndexPath) -> UITableViewCell? {
+        return nil
+    }
+    
+    func dropUpMenu(_ dropUpMenu: DropUpMenu, didSelectRowAt indexPath: IndexPath) { }
+    
+    func dropUpMenuCancel(_ dropUpMenu: DropUpMenu) { }
+  
+    func dropUpMenuWillDismiss(_ dropUpMenu: DropUpMenu) { }
+  
+    func dropUpMenuWillShow(_ dropUpMenu: DropUpMenu) { }
+}
+
+private let screenRect = UIScreen.main.bounds
+
+open class DropUpMenu: UIView {
+    fileprivate var items: [DropdownItem] = []
+    fileprivate var selectedRow: Int
+    open var tableView: UITableView!
+    fileprivate var barCoverView: UIView!
+    fileprivate var isShow = false
+    fileprivate var addedWindow: UIWindow?
+    fileprivate var windowRootView: UIView?
+    fileprivate lazy var tapGestureRecognizer: UITapGestureRecognizer = {
+        return UITapGestureRecognizer(target: self, action: #selector(self.hideMenu))
+    }()
+    
+    open weak var delegate: DropUpMenuDelegate?
+    
+    open var animateDuration: TimeInterval = 0.25
+    
+    open var backgroudBeginColor: UIColor = UIColor.black.withAlphaComponent(0)
+    open var backgroudEndColor = UIColor(white: 0, alpha: 0.4)
+    
+    open var rowHeight: CGFloat = 50
+    open var tableViewHeight: CGFloat = 0
+    open var defaultBottonMargin: CGFloat = 150
+    
+    open var textColor: UIColor = UIColor(red: 56.0/255.0, green: 56.0/255.0, blue: 56.0/255.0, alpha: 1.0)
+    open var highlightColor: UIColor = UIColor(red: 3.0/255.0, green: 169.0/255.0, blue: 244.0/255.0, alpha: 1.0)
+    open var tableViewBackgroundColor: UIColor = UIColor(red: 242.0/255.0, green: 242.0/255.0, blue: 242.0/255.0, alpha: 1.0) {
+        didSet {
+            tableView.backgroundColor = tableViewBackgroundColor
+        }
+    }
+    open var tableViewSeperatorColor = UIColor(red: 217.0/255.0, green: 217.0/255.0, blue: 217.0/255.0, alpha: 1.0) {
+        didSet {
+            tableView.separatorColor = tableViewSeperatorColor
+        }
+    }
+    open var cellBackgroundColor = UIColor.white
+
+    open var displaySelected: Bool = true
+    open var bottomOffsetY: CGFloat = 0
+    
+    required public init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    public init(items: [DropdownItem], selectedRow: Int = 0, bottomOffsetY: CGFloat = 0) {
+        self.items = items
+        self.selectedRow = selectedRow
+        self.bottomOffsetY = bottomOffsetY
+        
+        let frame = CGRect(x: 0, y: 0, width: screenRect.width, height: screenRect.height - bottomOffsetY)
+        super.init(frame: frame)
+        
+        clipsToBounds = true
+        setupGestureView()
+        initTableView()
+    }
+    
+    fileprivate func setupGestureView() {
+        let gestureView = UIView()
+        gestureView.backgroundColor = UIColor.clear
+        addSubview(gestureView)
+        gestureView.translatesAutoresizingMaskIntoConstraints = false
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: gestureView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: gestureView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: gestureView, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: gestureView, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1.0, constant: 0)])
+        
+        gestureView.addGestureRecognizer(tapGestureRecognizer)
+    }
+    
+    fileprivate func initTableView() {
+        tableView = UITableView(frame: CGRect.zero, style: .grouped)
+        tableView?.delegate = self
+        tableView?.dataSource = self
+        tableView.estimatedSectionHeaderHeight = 0
+        tableView.estimatedSectionFooterHeight = 0
+        addSubview(tableView)
+    }
+    
+    fileprivate func layoutTableView() {
+        tableViewHeight = CGFloat(items.count) * rowHeight
+        let maxHeight = UIScreen.main.bounds.height - bottomOffsetY
+        if tableViewHeight > maxHeight {
+            tableViewHeight = maxHeight
+        }
+        
+        tableView.translatesAutoresizingMaskIntoConstraints = false
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: tableView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant:0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: tableView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: tableViewHeight)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: tableView, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: tableView, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1.0, constant: 0)])
+    }
+    
+    fileprivate func setupBottomSeperatorView() {
+        let seperatorView = UIView()
+        seperatorView.backgroundColor = tableViewSeperatorColor
+        addSubview(seperatorView)
+        seperatorView.translatesAutoresizingMaskIntoConstraints = false
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: seperatorView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: seperatorView, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: seperatorView, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: seperatorView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 0.5)])
+    }
+    
+    fileprivate func setupBottomCoverView(on view: UIView) {
+        barCoverView = UIView()
+        barCoverView.backgroundColor = UIColor.clear
+        barCoverView.translatesAutoresizingMaskIntoConstraints = false
+        view.addSubview(barCoverView)
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: barCoverView, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: barCoverView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: bottomOffsetY)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: barCoverView, attribute: .left, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: barCoverView, attribute: .right, relatedBy: .equal, toItem: view, attribute: .right, multiplier: 1.0, constant: 0)])
+        barCoverView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(hideMenu)))
+    }
+    
+    open func showMenu() {
+        delegate?.dropUpMenuWillShow(self)
+        if isShow {
+            hideMenu()
+            return
+        }
+        isShow = true
+        
+        layoutTableView()
+        setupBottomSeperatorView()
+        
+        if let rootView = UIApplication.shared.keyWindow {
+            windowRootView = rootView
+        } else {
+            addedWindow = UIWindow(frame: UIScreen.main.bounds)
+            addedWindow?.rootViewController = UIViewController()
+            addedWindow?.isHidden = false
+            addedWindow?.makeKeyAndVisible()
+            windowRootView = addedWindow!
+        }
+        setupBottomCoverView(on: windowRootView!)
+        windowRootView?.addSubview(self)
+        
+        translatesAutoresizingMaskIntoConstraints = false
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: self, attribute: .top, relatedBy: .equal, toItem: windowRootView, attribute: .top, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: self, attribute: .bottom, relatedBy: .equal, toItem: windowRootView, attribute: .bottom, multiplier: 1.0, constant: -bottomOffsetY)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: self, attribute: .left, relatedBy: .equal, toItem: windowRootView, attribute: .left, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: self, attribute: .right, relatedBy: .equal, toItem: windowRootView, attribute: .right, multiplier: 1.0, constant: 0)])
+        
+        backgroundColor = backgroudBeginColor
+        self.tableView.frame.origin.y = screenRect.height - bottomOffsetY
+        UIView.animate(withDuration: animateDuration, delay: 0, options: UIView.AnimationOptions(rawValue: 7<<16), animations: {
+            self.backgroundColor = self.backgroudEndColor
+            self.tableView.frame.origin.y = screenRect.height - self.bottomOffsetY - self.tableViewHeight
+            }, completion: nil)
+    }
+    
+    @objc open func hideMenu(isSelectAction: Bool = false) {
+        delegate?.dropUpMenuWillDismiss(self)
+        UIView.animate(withDuration: animateDuration, animations: {
+            self.backgroundColor = self.backgroudBeginColor
+            self.tableView.frame.origin.y = screenRect.height - self.bottomOffsetY
+        }, completion: { (finished) in
+            if !isSelectAction {
+                self.delegate?.dropUpMenuCancel(self)
+            }
+
+            self.barCoverView.removeFromSuperview()
+            self.removeFromSuperview()
+            self.isShow = false
+            
+            if let _ = self.addedWindow {
+                self.addedWindow?.isHidden = true
+                UIApplication.shared.keyWindow?.makeKey()
+            }
+        }) 
+    }
+}
+
+extension DropUpMenu: UITableViewDataSource {
+    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return items.count
+    }
+    
+    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        if let customCell = delegate?.dropUpMenu(self, cellForRowAt: indexPath) {
+            return customCell
+        }
+        
+        let item = items[(indexPath as NSIndexPath).row]
+        let cell = UITableViewCell(style: .default, reuseIdentifier: "dropUpMenuCell")
+        
+        switch item.style {
+        case .default:
+            cell.textLabel?.textColor = textColor
+            if let image = item.image {
+                cell.imageView?.image = image
+            }
+        case .highlight:
+            cell.textLabel?.textColor = highlightColor
+            if let image = item.image {
+                let highlightImage = image.withRenderingMode(.alwaysTemplate)
+                cell.imageView?.image = highlightImage
+                cell.imageView?.tintColor = highlightColor
+            }
+        }
+        
+        cell.textLabel?.text = item.title
+        cell.tintColor = highlightColor
+        cell.backgroundColor = cellBackgroundColor
+        
+        if displaySelected && (indexPath as NSIndexPath).row == selectedRow {
+            cell.accessoryType = .checkmark
+        } else {
+            cell.accessoryType = .none
+        }
+        
+        if let accesoryImage = item.accessoryImage {
+            cell.accessoryView = UIImageView(image: accesoryImage)
+        }
+        
+        return cell
+    }
+}
+
+extension DropUpMenu: UITableViewDelegate {
+    public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
+        return rowHeight
+    }
+
+    public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
+        return CGFloat.leastNonzeroMagnitude
+    }
+    
+    public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
+        return CGFloat.leastNormalMagnitude
+    }
+    
+    public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        if displaySelected {
+            let item = items[(indexPath as NSIndexPath).row]
+            if item.accessoryImage  == nil {
+                let previousSelectedcell = tableView.cellForRow(at: IndexPath(row: selectedRow, section: 0))
+                previousSelectedcell?.accessoryType = .none
+                selectedRow = (indexPath as NSIndexPath).row
+                let cell = tableView.cellForRow(at: indexPath)
+                cell?.accessoryType = .checkmark
+            }
+        }
+        tableView.deselectRow(at: indexPath, animated: true)
+        hideMenu(isSelectAction: true)
+        delegate?.dropUpMenu(self, didSelectRowAt: indexPath)
+    }
+}
+

+ 38 - 0
iOSClient/Library/DropdownMenu/DropdownItem.swift

@@ -0,0 +1,38 @@
+//
+//  DropdownItem.swift
+//  DropdownMenu
+//
+//  Created by Suric on 16/5/27.
+//  Copyright © 2016年 teambition. All rights reserved.
+//
+
+import UIKit
+
+public enum DropdownItemStyle: Int {
+    case `default`
+    case highlight
+}
+
+open class DropdownItem {
+    open var image: UIImage?
+    open var title: String
+    open var style: DropdownItemStyle
+    open var accessoryImage: UIImage?
+
+    public init(image: UIImage? = nil, title: String, style: DropdownItemStyle = .default, accessoryImage: UIImage? = nil) {
+        self.image = image
+        self.title = title
+        self.style = style
+        self.accessoryImage = accessoryImage
+    }
+}
+
+public struct DropdownSection {
+    public var sectionIdentifier: String
+    public var items: [DropdownItem]
+
+    public init (sectionIdentifier: String, items: [DropdownItem]) {
+        self.items = items
+        self.sectionIdentifier = sectionIdentifier
+    }
+}

+ 19 - 0
iOSClient/Library/DropdownMenu/DropdownMenu.h

@@ -0,0 +1,19 @@
+//
+//  DropdownMenu.h
+//  DropdownMenu
+//
+//  Created by Suric on 16/5/26.
+//  Copyright © 2016年 teambition. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+//! Project version number for DropdownMenu.
+FOUNDATION_EXPORT double DropdownMenuVersionNumber;
+
+//! Project version string for DropdownMenu.
+FOUNDATION_EXPORT const unsigned char DropdownMenuVersionString[];
+
+// In this header, you should import all the public headers of your framework using statements like #import <DropdownMenu/PublicHeader.h>
+
+

+ 406 - 0
iOSClient/Library/DropdownMenu/DropdownMenu.swift

@@ -0,0 +1,406 @@
+//
+//  DropdownMenu.swift
+//  DropdownMenu
+//
+//  Created by Suric on 16/5/26.
+//  Copyright © 2016年 teambition. All rights reserved.
+//
+
+import UIKit
+
+public protocol DropdownMenuDelegate: class {
+    func dropdownMenu(_ dropdownMenu: DropdownMenu, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
+    func dropdownMenu(_ dropdownMenu: DropdownMenu, cellForRowAt indexPath: IndexPath) -> UITableViewCell?
+    func dropdownMenu(_ dropdownMenu: DropdownMenu, didSelectRowAt indexPath: IndexPath)
+    func dropdownMenu(_ dropdownMenu: DropdownMenu, shouldUpdateSelectionAt indexPath: IndexPath) -> Bool
+    func dropdownMenuCancel(_ dropdownMenu: DropdownMenu)
+    func dropdownMenuWillDismiss(_ dropdownMenu: DropdownMenu)
+    func dropdownMenuWillShow(_ dropdownMenu: DropdownMenu)
+}
+
+public extension DropdownMenuDelegate {
+    func dropdownMenu(_ dropdownMenu: DropdownMenu, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { }
+    func dropdownMenu(_ dropdownMenu: DropdownMenu, cellForRowAt indexPath: IndexPath) -> UITableViewCell? { return nil }
+    func dropdownMenu(_ dropdownMenu: DropdownMenu, didSelectRowAt indexPath: IndexPath) { }
+    func dropdownMenu(_ dropdownMenu: DropdownMenu, shouldUpdateSelectionAt indexPath: IndexPath) -> Bool { return true }
+    func dropdownMenuCancel(_ dropdownMenu: DropdownMenu) { }
+    func dropdownMenuWillDismiss(_ dropdownMenu: DropdownMenu) { }
+    func dropdownMenuWillShow(_ dropdownMenu: DropdownMenu) { }
+}
+
+open class DropdownMenu: UIView {
+    fileprivate weak var navigationController: UINavigationController!
+   
+    fileprivate var sections: [DropdownSection] = []
+    fileprivate var selectedIndexPath: IndexPath
+    
+    open var tableView: UITableView!
+    fileprivate var barCoverView: UIView?
+    open var isShow = false
+    fileprivate var addedWindow: UIWindow?
+    fileprivate var windowRootView: UIView?
+    fileprivate var topConstraint: NSLayoutConstraint?
+    fileprivate var navigationBarCoverViewHeightConstraint: NSLayoutConstraint?
+    fileprivate let iPhoneXPortraitTopOffset: CGFloat = 88.0
+    fileprivate let portraitTopOffset: CGFloat = 64.0
+    fileprivate let landscapeTopOffset: CGFloat = 32.0
+    fileprivate var topLayoutConstraintConstant: CGFloat {
+        var offset: CGFloat = 0
+        if !navigationController.isNavigationBarHidden {
+          offset = navigationController.navigationBar.frame.height + navigationController.navigationBar.frame.origin.y
+        }
+        return offset + topOffsetY
+    }
+    
+    open weak var delegate: DropdownMenuDelegate?
+    open var animateDuration: TimeInterval = 0.25
+    open var backgroudBeginColor: UIColor = UIColor.black.withAlphaComponent(0)
+    open var backgroudEndColor = UIColor(white: 0, alpha: 0.4)
+    open var rowHeight: CGFloat = 50
+    open var sectionHeaderHeight: CGFloat = 44
+    open var tableViewHeight: CGFloat = 0
+    open var defaultBottonMargin: CGFloat = 0
+    open var topOffsetY: CGFloat = 0
+    
+    open var textFont: UIFont = UIFont.systemFont(ofSize: 15.0)
+    open var textColor: UIColor = UIColor(red: 56.0/255.0, green: 56.0/255.0, blue: 56.0/255.0, alpha: 1.0)
+    open var highlightColor: UIColor = UIColor(red: 3.0/255.0, green: 169.0/255.0, blue: 244.0/255.0, alpha: 1.0)
+    open var tableViewBackgroundColor: UIColor = UIColor(red: 242.0/255.0, green: 242.0/255.0, blue: 242.0/255.0, alpha: 1.0) {
+        didSet {
+            tableView.backgroundColor = tableViewBackgroundColor
+        }
+    }
+    open var separatorStyle: UITableViewCell.SeparatorStyle = .singleLine {
+        didSet {
+            tableView.separatorStyle = separatorStyle
+        }
+    }
+    open var tableViewSeperatorColor = UIColor(red: 217.0/255.0, green: 217.0/255.0, blue: 217.0/255.0, alpha: 1.0) {
+        didSet {
+            tableView.separatorColor = tableViewSeperatorColor
+        }
+    }
+    open var zeroInsetSeperatorIndexPaths: [IndexPath] = []
+    
+    open var cellBackgroundColor = UIColor.white
+    
+    open var displaySelected: Bool = true
+    open var displaySectionHeader: Bool = false
+    open var displayNavigationBarCoverView: Bool = true
+    
+    // section header sytle
+    open var sectionHeaderStyle: SectionHeaderStyle = SectionHeaderStyle()
+    
+    required public init?(coder aDecoder: NSCoder) {
+        fatalError("init(coder:) has not been implemented")
+    }
+    
+    public init(navigationController: UINavigationController, items: [DropdownItem], selectedRow: Int = 0) {
+        self.navigationController = navigationController
+        self.sections = [DropdownSection(sectionIdentifier: "", items: items)]
+        self.selectedIndexPath = IndexPath(row: selectedRow, section: 0)
+        
+        super.init(frame: CGRect.zero)
+        
+        clipsToBounds = true
+        setupGestureView()
+        initTableView()
+        
+        NotificationCenter.default.addObserver(self, selector: #selector(self.updateForOrientationChange(_:)), name: UIApplication.didChangeStatusBarOrientationNotification, object: nil)
+    }
+    
+    public init(navigationController: UINavigationController, sections: [DropdownSection], selectedIndexPath: IndexPath = IndexPath(row: 0, section: 0), dispalySectionHeader: Bool = true, sectionHeaderStyle: SectionHeaderStyle = SectionHeaderStyle()) {
+        self.navigationController = navigationController
+        self.sections = sections
+        self.selectedIndexPath = selectedIndexPath
+        self.displaySectionHeader = dispalySectionHeader
+        
+        super.init(frame: CGRect.zero)
+        
+        clipsToBounds = true
+        setupGestureView()
+        initTableView()
+        
+        NotificationCenter.default.addObserver(self, selector: #selector(self.updateForOrientationChange(_:)), name: UIApplication.didChangeStatusBarOrientationNotification, object: nil)
+    }
+    
+    deinit {
+        NotificationCenter.default.removeObserver(self)
+    }
+    
+    @objc func updateForOrientationChange(_ nofication: Notification) {
+        print("UIApplicationWillChangeStatusBarOrientation")
+        var insetTop: CGFloat = 0
+        if #available(iOS 11.0, *) {
+            insetTop = UIApplication.shared.keyWindow!.safeAreaInsets.top
+        }
+        
+        if let _ = (nofication as NSNotification).userInfo?[UIApplication.statusBarOrientationUserInfoKey] as? Int {
+            var topOffset = navigationController.navigationBar.frame.height + insetTop
+            /*
+            var topOffset: CGFloat = 0
+            switch oriention {
+            case UIInterfaceOrientation.landscapeLeft.rawValue, UIInterfaceOrientation.landscapeRight.rawValue:
+                if UIDevice.current.userInterfaceIdiom == .phone {
+                    topOffset = navigationController.navigationBar.frame.height + insetTop
+                } else {
+                    topOffset = navigationController.navigationBar.frame.height + insetTop
+                }
+                
+            case UIInterfaceOrientation.portrait.rawValue, UIInterfaceOrientation.portraitUpsideDown.rawValue:
+                topOffset = navigationController.navigationBar.frame.height + insetTop
+            
+            default:
+                break
+            }
+            */
+            topOffset = topOffset + topOffsetY
+            topConstraint?.constant = topOffset
+            navigationBarCoverViewHeightConstraint?.constant = topOffset
+            UIView.animate(withDuration: 0.1, animations: {
+//                self.windowRootView?.layoutIfNeeded()
+            })
+        }
+    }
+    
+    fileprivate func setupGestureView() {
+        let gestureView = UIView()
+        gestureView.backgroundColor = UIColor.clear
+        addSubview(gestureView)
+        gestureView.translatesAutoresizingMaskIntoConstraints = false
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: gestureView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: gestureView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: gestureView, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: gestureView, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1.0, constant: 0)])
+        
+        gestureView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(hideMenu)))
+    }
+    
+    fileprivate func initTableView() {
+        tableView = UITableView(frame: CGRect.zero, style: .grouped)
+        tableView.separatorStyle = separatorStyle
+        tableView.delegate = self
+        tableView.dataSource = self
+        tableView.estimatedSectionFooterHeight = 0
+        tableView.estimatedSectionHeaderHeight = 0
+        addSubview(tableView)
+    }
+    
+    fileprivate func layoutTableView() {
+        tableView.translatesAutoresizingMaskIntoConstraints = false
+
+        tableViewHeight = tableviewHeight()
+        
+        let maxHeight = navigationController.view.frame.height - topLayoutConstraintConstant - defaultBottonMargin
+        
+        if tableViewHeight > maxHeight {
+            if displaySectionHeader {
+                tableViewHeight = maxHeight
+            } else {
+                tableViewHeight = round(maxHeight / rowHeight) * rowHeight
+            }
+        }
+        
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: tableView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant:0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: tableView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: tableViewHeight)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: tableView, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: tableView, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1.0, constant: 0)])
+    }
+    
+    fileprivate func setupTopSeperatorView() {
+        let seperatorView = UIView()
+        seperatorView.backgroundColor = tableViewSeperatorColor
+        addSubview(seperatorView)
+        seperatorView.translatesAutoresizingMaskIntoConstraints = false
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: seperatorView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: seperatorView, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: seperatorView, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: seperatorView, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: 0.5)])
+    }
+    
+    fileprivate func setupNavigationBarCoverView(on view: UIView) {
+        barCoverView = UIView()
+        barCoverView?.backgroundColor = UIColor.clear
+        view.addSubview(barCoverView!)
+        barCoverView?.translatesAutoresizingMaskIntoConstraints = false
+        
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: barCoverView!, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: 0)])
+        navigationBarCoverViewHeightConstraint = NSLayoutConstraint.init(item: barCoverView!, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1.0, constant: topLayoutConstraintConstant)
+        NSLayoutConstraint.activate([navigationBarCoverViewHeightConstraint!])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: barCoverView!, attribute: .left, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: barCoverView!, attribute: .right, relatedBy: .equal, toItem: view, attribute: .right, multiplier: 1.0, constant: 0)])
+        barCoverView?.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(hideMenu)))
+    }
+    
+    fileprivate func tableviewHeight() -> CGFloat {
+        var height: CGFloat = 0
+        if displaySectionHeader {
+            height += sectionHeaderHeight * CGFloat(sections.count)
+        }
+        for section in sections {
+            height += CGFloat(section.items.count) * rowHeight
+        }
+        return height
+    }
+    
+    open func showMenu(isOnNavigaitionView: Bool = false) {
+        delegate?.dropdownMenuWillShow(self)
+        if isShow {
+            hideMenu()
+            return
+        }
+        
+        isShow = true
+        
+        layoutTableView()
+        setupTopSeperatorView()
+        
+        addedWindow = UIWindow(frame: self.navigationController.view.bounds)
+        addedWindow?.rootViewController = UIViewController()
+        addedWindow?.isHidden = false
+        addedWindow?.makeKeyAndVisible()
+        windowRootView = addedWindow!
+
+        if displayNavigationBarCoverView {
+            setupNavigationBarCoverView(on: windowRootView!)
+        }
+        
+        windowRootView?.addSubview(self)
+        
+        translatesAutoresizingMaskIntoConstraints = false
+        topConstraint = NSLayoutConstraint.init(item: self, attribute: .top, relatedBy: .equal, toItem: windowRootView, attribute: .top, multiplier: 1.0, constant: topLayoutConstraintConstant)
+        NSLayoutConstraint.activate([topConstraint!])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: self, attribute: .bottom, relatedBy: .equal, toItem: windowRootView, attribute: .bottom, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: self, attribute: .left, relatedBy: .equal, toItem: windowRootView, attribute: .left, multiplier: 1.0, constant: 0)])
+        NSLayoutConstraint.activate([NSLayoutConstraint.init(item: self, attribute: .right, relatedBy: .equal, toItem: windowRootView, attribute: .right, multiplier: 1.0, constant: 0)])
+        
+        backgroundColor = backgroudBeginColor
+        self.tableView.frame.origin.y = -self.tableViewHeight
+        UIView.animate(withDuration: animateDuration, delay: 0, options: UIView.AnimationOptions(rawValue: 7<<16), animations: {
+            self.backgroundColor = self.backgroudEndColor
+            self.tableView.frame.origin.y = 0
+        }, completion: nil)
+    }
+    
+    @objc open func hideMenu(isSelectAction: Bool = false) {
+        delegate?.dropdownMenuWillDismiss(self)
+        UIView.animate(withDuration: animateDuration, animations: {
+            self.backgroundColor = self.backgroudBeginColor
+            self.tableView.frame.origin.y = -self.tableViewHeight
+        }, completion: { (finished) in
+            if !isSelectAction {
+                self.delegate?.dropdownMenuCancel(self)
+            }
+            self.barCoverView?.removeFromSuperview()
+            self.removeFromSuperview()
+            self.isShow = false
+            
+            if let _ = self.addedWindow {
+                self.addedWindow?.isHidden = true
+                UIApplication.shared.keyWindow?.makeKey()
+            }
+        })
+    }
+}
+
+extension DropdownMenu: UITableViewDataSource {
+    public func numberOfSections(in tableView: UITableView) -> Int {
+        return sections.count
+    }
+    
+    public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
+        return sections[section].items.count
+    }
+    
+    public func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
+        delegate?.dropdownMenu(self, willDisplay: cell, forRowAt: indexPath)
+    }
+    
+    public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
+        if let customCell = delegate?.dropdownMenu(self, cellForRowAt: indexPath) {
+            return customCell
+        }
+        
+        let item = sections[indexPath.section].items[indexPath.row]
+        let cell = UITableViewCell(style: .default, reuseIdentifier: "dropdownMenuCell")
+        
+        switch item.style {
+        case .default:
+            cell.textLabel?.textColor = textColor
+            if let image = item.image {
+                cell.imageView?.image = image
+            }
+        case .highlight:
+            cell.textLabel?.textColor = highlightColor
+            if let image = item.image {
+                let highlightImage = image.withRenderingMode(.alwaysTemplate)
+                cell.imageView?.image = highlightImage
+                cell.imageView?.tintColor = highlightColor
+            }
+        }
+        
+        cell.textLabel?.text = item.title
+        cell.textLabel?.font = textFont
+        cell.tintColor = highlightColor
+        cell.backgroundColor = cellBackgroundColor
+        
+        if displaySelected && indexPath == selectedIndexPath {
+            cell.accessoryType = .checkmark
+        } else {
+            cell.accessoryType = .none
+        }
+        
+        if let accesoryImage = item.accessoryImage {
+            cell.accessoryView = UIImageView(image: accesoryImage)
+        }
+        
+        if zeroInsetSeperatorIndexPaths.contains(indexPath) {
+            cell.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
+        } else {
+            cell.separatorInset = UIEdgeInsets(top: 0, left: tableView.layoutMargins.left, bottom: 0, right: 0)
+        }
+        
+        return cell
+    }
+    
+    public func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
+        return displaySectionHeader ? sections[section].sectionIdentifier : nil
+    }
+}
+
+extension DropdownMenu: UITableViewDelegate {
+    public func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
+        return rowHeight
+    }
+    
+    public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
+        return displaySectionHeader ? sectionHeaderHeight : CGFloat.leastNormalMagnitude
+    }
+    
+    public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
+        return CGFloat.leastNormalMagnitude
+    }
+    
+    public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
+        let shouldUpdateSelection = delegate?.dropdownMenu(self, shouldUpdateSelectionAt: indexPath) ?? true
+        if displaySelected && shouldUpdateSelection {
+            let item = sections[indexPath.section].items[indexPath.row]
+            if item.accessoryImage  == nil {
+                let previousSelectedcell = tableView.cellForRow(at: selectedIndexPath)
+                previousSelectedcell?.accessoryType = .none
+                selectedIndexPath = indexPath
+                let cell = tableView.cellForRow(at: indexPath)
+                cell?.accessoryType = .checkmark
+            }
+        }
+        tableView.deselectRow(at: indexPath, animated: true)
+        hideMenu(isSelectAction: true)
+        delegate?.dropdownMenu(self, didSelectRowAt: indexPath)
+    }
+    
+    public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
+        let sectionHeader = SectionHeader(style: sectionHeaderStyle)
+        sectionHeader.titleLabel.text = sections[section].sectionIdentifier
+        return sectionHeader
+    }
+}

+ 76 - 0
iOSClient/Library/DropdownMenu/SectionHeader.swift

@@ -0,0 +1,76 @@
+//
+//  SectionHeader.swift
+//  DropdownMenu
+//
+//  Created by WangWei on 2016/10/9.
+//  Copyright © 2016年 teambition. All rights reserved.
+//
+
+open class SectionHeader: UIView {
+    var titleLabel: UILabel!
+    var style: SectionHeaderStyle = SectionHeaderStyle()
+
+    convenience init(style: SectionHeaderStyle) {
+        self.init(frame: CGRect.zero)
+        self.style = style
+        commonInit()
+    }
+
+    override init(frame: CGRect) {
+        super.init(frame: frame)
+    }
+    
+    required public init?(coder aDecoder: NSCoder) {
+        super.init(coder: aDecoder)
+    }
+
+    func commonInit() {
+        titleLabel = UILabel()
+        titleLabel.translatesAutoresizingMaskIntoConstraints = false
+        titleLabel.font = style.font
+        titleLabel.textColor = style.textColor
+        backgroundColor = style.backgroundColor
+        addSubview(titleLabel)
+        updateTitleLabelConstraint()
+    }
+
+    func updateTitleLabelConstraint() {
+        if #available(iOS 11.0, *) {
+            let leftConstraint = NSLayoutConstraint(item: titleLabel, attribute: .left, relatedBy: .equal, toItem: safeAreaLayoutGuide, attribute: .left, multiplier: 1.0, constant: style.bottomPadding)
+            NSLayoutConstraint.activate([leftConstraint])
+        } else {
+            // Fallback on earlier versions
+            let constraints =  NSLayoutConstraint.constraints(withVisualFormat: "H:|-leftPadding-[titleLabel]->=20-|", options: [], metrics: ["leftPadding": style.leftPadding], views: ["titleLabel": titleLabel])
+            addConstraints(constraints)
+        }
+        if style.shouldTitleCenterVertically {
+            let centerY = NSLayoutConstraint(item: titleLabel, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1.0, constant: 0)
+            addConstraint(centerY)
+        } else {
+            let vConstraints = NSLayoutConstraint(item: titleLabel, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: style.bottomPadding)
+            addConstraint(vConstraints)
+        }
+    }
+}
+
+
+public struct SectionHeaderStyle {
+    
+    /// leftPadding for title label, default is `20`
+    public var leftPadding: CGFloat = 20
+    /// bottom padding for title label, default is `10`,
+    /// will be ignored when `shouldTitleCenterVertically` is `true`
+    public var bottomPadding: CGFloat = 10
+    /// should title label center in axis Y, default is `true`
+    public var shouldTitleCenterVertically: Bool = true
+
+    /// title label font, default is `UIFont.systemFont(ofSize: 14)`
+    public var font: UIFont = UIFont.systemFont(ofSize: 14)
+    /// title label textColor, default is A6A6A6
+    public var textColor: UIColor = UIColor(red: 166.0/255.0, green: 166.0/255.0, blue: 166.0/255.0, alpha: 1.0)
+    /// backgroundColor for header, default is F2F2F2
+    public var backgroundColor: UIColor = UIColor(red: 242.0/255.0, green: 242.0/255.0, blue: 242.0/255.0, alpha: 1.0)
+
+    public init() {
+    }
+}

+ 9 - 7
iOSClient/Supporting Files/en.lproj/Localizable.strings

@@ -603,17 +603,19 @@
 // Trah
 
 "_trash_view_"                      = "Deleted files";
+"_trash_restore_all_"               = "Restore all files";
+"_trash_delete_all_"                = "Empty trash";
 
 // Intro
 
-"_intro_1_title_"       = "Keep your data secure and under your control";
-"_intro_2_title_"       = "Secure collaboration & file exchange";
-"_intro_3_title_"       = "Easy-to-use web mail, calendering & contacts";
-"_intro_4_title_"       = "Screensharing, online meetings & web conferences";
+"_intro_1_title_"                   = "Keep your data secure and under your control";
+"_intro_2_title_"                   = "Secure collaboration & file exchange";
+"_intro_3_title_"                   = "Easy-to-use web mail, calendering & contacts";
+"_intro_4_title_"                   = "Screensharing, online meetings & web conferences";
 
-"_log_in_"              = "Log in";
-"_sign_up_"             = "Sign up with provider";
-"_host_your_own_server" = "Host your own server";
+"_log_in_"                          = "Log in";
+"_sign_up_"                         = "Sign up with provider";
+"_host_your_own_server"             = "Host your own server";
 
 // Error
 

+ 22 - 5
iOSClient/Trash/NCTrash.swift

@@ -8,7 +8,7 @@
 
 import Foundation
 
-class NCTrash: UIViewController , UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UIGestureRecognizerDelegate, NCTrashListDelegate, NCTrashGridDelegate, NCTrashHeaderMenuDelegate {
+class NCTrash: UIViewController , UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, UIGestureRecognizerDelegate, NCTrashListDelegate, NCTrashGridDelegate, NCTrashHeaderMenuDelegate, DropdownMenuDelegate {
     
     @IBOutlet fileprivate weak var collectionView: UICollectionView!
 
@@ -16,10 +16,12 @@ class NCTrash: UIViewController , UICollectionViewDataSource, UICollectionViewDe
     var path = ""
     var titleCurrentFolder = NSLocalizedString("_trash_view_", comment: "")
     var datasource: [tableTrash]?
-
+    
     var listLayout: ListLayout!
     var gridLayout: GridLayout!
     
+    private let highHeader: CGFloat = 50
+    
     private let refreshControl = UIRefreshControl()
 
     override func viewDidLoad() {
@@ -124,7 +126,22 @@ class NCTrash: UIViewController , UICollectionViewDataSource, UICollectionViewDe
     }
     
     func tapMoreHeaderMenu() {
-        print("tap header more")
+        
+        var menuView: DropdownMenu?
+        
+        let item1 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "restore"), multiplier: 1, color: NCBrandColor.sharedInstance.icon), title:  NSLocalizedString("_trash_restore_all_", comment: ""))
+        let item2 = DropdownItem(image: CCGraphics.changeThemingColorImage(UIImage.init(named: "trash"), multiplier: 2, color: NCBrandColor.sharedInstance.icon), title:  NSLocalizedString("_trash_delete_all_", comment: ""))
+        
+        menuView = DropdownMenu(navigationController: self.navigationController!, items: [item1, item2], selectedRow: -1)
+        menuView?.delegate = self
+        menuView?.rowHeight = 50
+        menuView?.tableView.alwaysBounceVertical = false
+        menuView?.topOffsetY = CGFloat(highHeader-2)
+        menuView?.showMenu()
+        
+    }
+    
+    func dropdownMenu(_ dropdownMenu: DropdownMenu, didSelectRowAt indexPath: IndexPath) {
     }
     
     // MARK: NC API
@@ -288,11 +305,11 @@ class NCTrash: UIViewController , UICollectionViewDataSource, UICollectionViewDe
     }
     
     func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
-        return CGSize(width: collectionView.frame.width, height: 50)
+        return CGSize(width: collectionView.frame.width, height: highHeader)
     }
     
     func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize {
-        return CGSize(width: collectionView.frame.width, height: 50)
+        return CGSize(width: collectionView.frame.width, height: highHeader)
     }
     
     func numberOfSections(in collectionView: UICollectionView) -> Int {