Skip to content

Commit

Permalink
[feature/sort direction] Allow sorting asc/desc for all sort methods (#…
Browse files Browse the repository at this point in the history
…474)

* #470 added change sort direction asc/desc for all sort methods

* - removed comments
- changed translation keys

* fixes sort comparator for sort method "shared"

* use correct images for sort direction asc and desc

* updated choosing sort method from a tableView/Popover instead of a UIAlertViewController

* set maximum width for popover and set arrow direction

* Added show sort direction in UISegmentControl

* - make sure arrows of popovers appear in same color as the popover contents
- fix issue where direction was toggled during setup of SortBar (setting of initial value from user defaults), so logging in, logging out and logging in would change the sort direction
- reset sort direction to ascendant when switching sort methods
- SortMethodTableViewController
	- remove extraneous instance lets
	- enforce row height used for table view height calculation
	- change table view height calculation to account for the last divider (which could look a bit off if present)

* tap on segment control was fired twice, because there was a missing check, if selected segment changed

* fixed changing width on selecting an other segment

* fixed jumping width of sortSegmentControl items by setting the same width for all items by calculating the longest width before
  • Loading branch information
hosy authored Aug 9, 2019
1 parent 57b855f commit dd6b625
Show file tree
Hide file tree
Showing 10 changed files with 252 additions and 53 deletions.
4 changes: 4 additions & 0 deletions ownCloud.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
39CC8B01228C8A950020253B /* MediaUploadSettingsSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CC8B00228C8A950020253B /* MediaUploadSettingsSection.swift */; };
39CC8B37228D5B890020253B /* ShareClientItemCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39CC8B36228D5B890020253B /* ShareClientItemCell.swift */; };
39D06BEC229BE8D8000D7FC9 /* SettingsSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39D06BEB229BE8D8000D7FC9 /* SettingsSection.swift */; };
39DE75CD22F960CF0064C1E2 /* SortMethodTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39DE75C722F960CF0064C1E2 /* SortMethodTableViewController.swift */; };
39E2FDED21FDEC7500F0117F /* ServerListTableHeaderView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E2FDEC21FDEC7500F0117F /* ServerListTableHeaderView.swift */; };
39E2FE0021FF814A00F0117F /* ThemeRoundedButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E2FDFF21FF814A00F0117F /* ThemeRoundedButton.swift */; };
39E98B3E22797D1B009911F1 /* PublicLinkTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 39E98B3D22797D1B009911F1 /* PublicLinkTableViewController.swift */; };
Expand Down Expand Up @@ -617,6 +618,7 @@
39CC8B00228C8A950020253B /* MediaUploadSettingsSection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MediaUploadSettingsSection.swift; sourceTree = "<group>"; };
39CC8B36228D5B890020253B /* ShareClientItemCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareClientItemCell.swift; sourceTree = "<group>"; };
39D06BEB229BE8D8000D7FC9 /* SettingsSection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsSection.swift; sourceTree = "<group>"; };
39DE75C722F960CF0064C1E2 /* SortMethodTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SortMethodTableViewController.swift; sourceTree = "<group>"; };
39E2FDEC21FDEC7500F0117F /* ServerListTableHeaderView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ServerListTableHeaderView.swift; sourceTree = "<group>"; };
39E2FDFF21FF814A00F0117F /* ThemeRoundedButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ThemeRoundedButton.swift; sourceTree = "<group>"; };
39E98B3D22797D1B009911F1 /* PublicLinkTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicLinkTableViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1320,6 +1322,7 @@
4C1561E7222321E0009C4EF3 /* PhotoSelectionViewController.swift */,
4C1561EE22232357009C4EF3 /* PhotoSelectionViewCell.swift */,
394804D9225CBDBA00AA8183 /* BreadCrumbTableViewController.swift */,
39DE75C722F960CF0064C1E2 /* SortMethodTableViewController.swift */,
);
path = Client;
sourceTree = "<group>";
Expand Down Expand Up @@ -2489,6 +2492,7 @@
DC29F09522976B9300F77349 /* LibrarySharesTableViewController.swift in Sources */,
392557FE2278703300E83F60 /* UISearchBar+Extension.swift in Sources */,
DC7DBA2B207F71E400E7337D /* VectorImageView.swift in Sources */,
39DE75CD22F960CF0064C1E2 /* SortMethodTableViewController.swift in Sources */,
DCE974BC207EACA60069FC2B /* UIImage+Extension.swift in Sources */,
DC1B2707209CF0D3004715E1 /* IssuesDismissalAnimator.swift in Sources */,
23BEF1182076667F00DD2E6F /* IssuesViewController.swift in Sources */,
Expand Down
4 changes: 4 additions & 0 deletions ownCloud/Client/ClientQueryViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -581,6 +581,10 @@ class ClientQueryViewController: QueryFileListTableViewController, UIDropInterac
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}

func prepareForPopoverPresentation(_ popoverPresentationController: UIPopoverPresentationController) {
popoverPresentationController.backgroundColor = Theme.shared.activeCollection.tableBackgroundColor
}
}

// MARK: - Drag & Drop delegates
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class LibraryFilesTableViewController: QueryFileListTableViewController {
}

override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
if sortMethod == .alphabeticallyAscendant || sortMethod == .alphabeticallyDescendant {
if sortMethod == .alphabetically {
return Array( Set( self.items.map { String(( $0.name?.first!.uppercased())!) })).sorted()
}

Expand Down
113 changes: 94 additions & 19 deletions ownCloud/Client/SortBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,40 @@

import UIKit

class SegmentedControl: UISegmentedControl {
var oldValue : Int!

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent? ) {
self.oldValue = self.selectedSegmentIndex
super.touchesBegan(touches, with: event)
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent? ) {
super.touchesEnded(touches, with: event )

if self.oldValue == self.selectedSegmentIndex {
sendActions(for: UIControl.Event.valueChanged)
}
}
}

protocol SortBarDelegate: class {

var sortDirection: SortDirection { get set }
var sortMethod: SortMethod { get set }

func sortBar(_ sortBar: SortBar, didUpdateSortMethod: SortMethod)

func sortBar(_ sortBar: SortBar, presentViewController: UIViewController, animated: Bool, completionHandler: (() -> Void)?)
}

class SortBar: UIView, Themeable {
class SortBar: UIView, Themeable, UIPopoverPresentationControllerDelegate {

weak var delegate: SortBarDelegate?
weak var delegate: SortBarDelegate? {
didSet {
updateSortButtonTitle()
}
}

// MARK: - Constants
let sideButtonsSize: CGSize = CGSize(width: 30.0, height: 30.0)
Expand All @@ -37,19 +62,33 @@ class SortBar: UIView, Themeable {

// MARK: - Instance variables.

var sortSegmentedControl: UISegmentedControl?
var sortSegmentedControl: SegmentedControl?
var sortButton: UIButton?

var sortMethod: SortMethod {
didSet {
if self.superview != nil { // Only toggle direction if the view is already in the view hierarchy (i.e. not during initial setup)
if oldValue == sortMethod {
if delegate?.sortDirection == .ascendant {
delegate?.sortDirection = .descendant
} else {
delegate?.sortDirection = .ascendant
}
} else {
delegate?.sortDirection = .ascendant // Reset sort direction when switching sort methods
}
}
updateSortButtonTitle()

let title = NSString(format: "Sort by %@".localized as NSString, sortMethod.localizedName()) as String
sortButton?.setTitle(title, for: .normal)
sortButton?.accessibilityLabel = NSString(format: "Sort by %@".localized as NSString, sortMethod.localizedName()) as String
sortButton?.sizeToFit()

if let oldSementIndex = SortMethod.all.index(of: oldValue) {
sortSegmentedControl?.setTitle(oldValue.localizedName(), forSegmentAt: oldSementIndex)
}
if let segmentIndex = SortMethod.all.index(of: sortMethod) {
sortSegmentedControl?.selectedSegmentIndex = segmentIndex
sortSegmentedControl?.setTitle(sortDirectionTitle(sortMethod.localizedName()), forSegmentAt: segmentIndex)
}

delegate?.sortBar(self, didUpdateSortMethod: sortMethod)
Expand All @@ -59,7 +98,7 @@ class SortBar: UIView, Themeable {
// MARK: - Init & Deinit

init(frame: CGRect, sortMethod: SortMethod) {
sortSegmentedControl = UISegmentedControl()
sortSegmentedControl = SegmentedControl()

sortButton = UIButton(type: .system)

Expand All @@ -86,8 +125,19 @@ class SortBar: UIView, Themeable {
sortSegmentedControl.rightAnchor.constraint(lessThanOrEqualTo: self.rightAnchor, constant: -rightPadding)
])

var longestTitleWidth : CGFloat = 0.0
for method in SortMethod.all {
sortSegmentedControl.insertSegment(withTitle: method.localizedName(), at: SortMethod.all.index(of: method)!, animated: false)
let titleWidth = method.localizedName().appending("").width(withConstrainedHeight: sortSegmentedControl.frame.size.height, font: UIFont.systemFont(ofSize: 16.0))
if titleWidth > longestTitleWidth {
longestTitleWidth = titleWidth
}
}

var currentIndex = 0
for _ in SortMethod.all {
sortSegmentedControl.setWidth(longestTitleWidth, forSegmentAt: currentIndex)
currentIndex += 1
}

sortSegmentedControl.selectedSegmentIndex = SortMethod.all.index(of: sortMethod)!
Expand All @@ -98,6 +148,7 @@ class SortBar: UIView, Themeable {
sortButton.titleLabel?.font = UIFont.preferredFont(forTextStyle: .subheadline)
sortButton.titleLabel?.adjustsFontForContentSizeCategory = true
sortButton.semanticContentAttribute = (sortButton.effectiveUserInterfaceLayoutDirection == .leftToRight) ? .forceRightToLeft : .forceLeftToRight

sortButton.setImage(UIImage(named: "chevron-small-light"), for: .normal)

sortButton.setContentHuggingPriority(.required, for: .horizontal)
Expand All @@ -110,7 +161,7 @@ class SortBar: UIView, Themeable {
])

sortButton.isHidden = true
sortButton.addTarget(self, action: #selector(presentSortButtonOptions), for: .touchUpInside)
sortButton.addTarget(self, action: #selector(presentSortButtonOptions(_:)), for: .touchUpInside)
}

// Finalize view setup
Expand Down Expand Up @@ -147,20 +198,35 @@ class SortBar: UIView, Themeable {
}
}

// MARK: - Actions
@objc private func presentSortButtonOptions() {
let controller = UIAlertController(title: "Sort by".localized, message: nil, preferredStyle: .actionSheet)

for method in SortMethod.all {
let action = UIAlertAction(title: method.localizedName(), style: .default, handler: {(_) in
self.sortMethod = method
})
controller.addAction(action)
// MARK: - Sort Direction Title

func updateSortButtonTitle() {
let title = NSString(format: "Sort by %@".localized as NSString, sortMethod.localizedName()) as String
sortButton?.setTitle(sortDirectionTitle(title), for: .normal)
}

func sortDirectionTitle(_ title: String) -> String {
if delegate?.sortDirection == .descendant {
return String(format: "%@ ↓", title)
} else {
return String(format: "%@ ↑", title)
}
}

let cancel = UIAlertAction(title: "Cancel".localized, style: .cancel)
controller.addAction(cancel)
delegate?.sortBar(self, presentViewController: controller, animated: true, completionHandler: nil)
// MARK: - Actions
@objc private func presentSortButtonOptions(_ sender : UIButton) {
let tableViewController = SortMethodTableViewController()
tableViewController.modalPresentationStyle = UIModalPresentationStyle.popover
tableViewController.sortBarDelegate = self.delegate
tableViewController.sortBar = self

let popoverPresentationController = tableViewController.popoverPresentationController
popoverPresentationController?.sourceView = sender
popoverPresentationController?.delegate = self
popoverPresentationController?.sourceRect = CGRect(x: 0, y: 0, width: sender.frame.size.width, height: sender.frame.size.height)
popoverPresentationController?.permittedArrowDirections = .up

delegate?.sortBar(self, presentViewController: tableViewController, animated: true, completionHandler: nil)
}

@objc private func sortSegmentedControllerValueChanged() {
Expand All @@ -169,4 +235,13 @@ class SortBar: UIView, Themeable {
delegate?.sortBar(self, didUpdateSortMethod: self.sortMethod)
}
}

// MARK: - UIPopoverPresentationControllerDelegate
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}

func prepareForPopoverPresentation(_ popoverPresentationController: UIPopoverPresentationController) {
popoverPresentationController.backgroundColor = Theme.shared.activeCollection.tableBackgroundColor
}
}
68 changes: 41 additions & 27 deletions ownCloud/Client/SortMethod.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,27 @@ import ownCloudSDK

typealias OCSort = Comparator

public enum SortDirection: Int {
case ascendant = 0
case descendant = 1
}

public enum SortMethod: Int {

case alphabeticallyAscendant = 0
case alphabeticallyDescendant = 1
case type = 2
case size = 3
case date = 4
case shared = 5
case alphabetically = 0
case type = 1
case size = 2
case date = 3
case shared = 4

static var all: [SortMethod] = [alphabeticallyAscendant, alphabeticallyDescendant, type, size, date, shared]
static var all: [SortMethod] = [alphabetically, type, size, date, shared]

func localizedName() -> String {
var name = ""

switch self {
case .alphabeticallyAscendant:
name = "name (A-Z)".localized
case .alphabeticallyDescendant:
name = "name (Z-A)".localized
case .alphabetically:
name = "name".localized
case .type:
name = "type".localized
case .size:
Expand All @@ -53,7 +55,7 @@ public enum SortMethod: Int {
return name
}

func comparator() -> OCSort {
func comparator(direction: SortDirection) -> OCSort {
var comparator: OCSort

switch self {
Expand All @@ -64,28 +66,23 @@ public enum SortMethod: Int {

let leftSize = leftItem!.size as NSNumber
let rightSize = rightItem!.size as NSNumber
if direction == .descendant {
return (leftSize.compare(rightSize))
}

return (rightSize.compare(leftSize))
}

case .alphabeticallyAscendant:
case .alphabetically:
comparator = { (left, right) in
guard let leftName = (left as? OCItem)?.name, let rightName = (right as? OCItem)?.name else {
return .orderedSame
}

return (leftName.caseInsensitiveCompare(rightName))
}

case .alphabeticallyDescendant:
comparator = { (left, right) in
guard let leftName = (left as? OCItem)?.name, let rightName = (right as? OCItem)?.name else {
return .orderedSame
if direction == .descendant {
return (rightName.caseInsensitiveCompare(leftName))
}

return (rightName.caseInsensitiveCompare(leftName))
return (leftName.caseInsensitiveCompare(rightName))
}

case .type:
comparator = { (left, right) in
let leftItem = left as? OCItem
Expand All @@ -109,6 +106,9 @@ public enum SortMethod: Int {
if rightMimeType == nil {
rightMimeType = "various"
}
if direction == .descendant {
return rightMimeType!.compare(leftMimeType!)
}

return leftMimeType!.compare(rightMimeType!)
}
Expand All @@ -122,17 +122,31 @@ public enum SortMethod: Int {

if leftShared == rightShared {
return .orderedSame
} else if leftShared {
return .orderedAscending
}
return .orderedDescending

if direction == .descendant {
if rightShared {
return .orderedAscending
}

return .orderedDescending
} else {
if leftShared {
return .orderedAscending
}

return .orderedDescending
}
}
case .date:
comparator = { (left, right) in

guard let leftLastModified = (left as? OCItem)?.lastModified, let rightLastModified = (right as? OCItem)?.lastModified else {
return .orderedSame
}
if direction == .descendant {
return (leftLastModified.compare(rightLastModified))
}

return (rightLastModified.compare(leftLastModified))
}
Expand Down
Loading

0 comments on commit dd6b625

Please sign in to comment.