Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[feature/globalsearch] Global search using custom queries #545

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions ownCloud.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
2308F94321467F6200CF0B91 /* ClientDirectoryPickerViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2308F93C21467F6200CF0B91 /* ClientDirectoryPickerViewController.swift */; };
232B01F42126B0CE00366FA0 /* MoreViewHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 232B01F32126B0CE00366FA0 /* MoreViewHeader.swift */; };
232B01F62126B10900366FA0 /* MoreStaticTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 232B01F52126B10900366FA0 /* MoreStaticTableViewController.swift */; };
232F7CAD2097140300EE22E4 /* UploadsSettingsSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 232F7CAC2097140300EE22E4 /* UploadsSettingsSection.swift */; };
232F7CAF2097260400EE22E4 /* SettingsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 232F7CAE2097260400EE22E4 /* SettingsViewController.swift */; };
233BDEA0204FEFE500C06732 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 233BDE9F204FEFE500C06732 /* AppDelegate.swift */; };
233BDEA7204FEFE500C06732 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 233BDEA6204FEFE500C06732 /* Assets.xcassets */; };
Expand Down Expand Up @@ -583,7 +582,6 @@
2308F93C21467F6200CF0B91 /* ClientDirectoryPickerViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClientDirectoryPickerViewController.swift; sourceTree = "<group>"; };
232B01F32126B0CE00366FA0 /* MoreViewHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoreViewHeader.swift; sourceTree = "<group>"; };
232B01F52126B10900366FA0 /* MoreStaticTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MoreStaticTableViewController.swift; sourceTree = "<group>"; };
232F7CAC2097140300EE22E4 /* UploadsSettingsSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UploadsSettingsSection.swift; sourceTree = "<group>"; };
232F7CAE2097260400EE22E4 /* SettingsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsViewController.swift; sourceTree = "<group>"; };
233BDE9C204FEFE500C06732 /* ownCloud.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = ownCloud.app; sourceTree = BUILT_PRODUCTS_DIR; };
233BDE9F204FEFE500C06732 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1819,7 +1817,6 @@
593BAB3F209ADFB900023634 /* Passcode */,
233E0FD72099F11D00C3D8D5 /* SecuritySettingsSection.swift */,
DCD2D40522F06ECA0071FB8F /* StorageSettingsSection.swift */,
232F7CAC2097140300EE22E4 /* UploadsSettingsSection.swift */,
DC854935218331CF00782BA8 /* UserInterfaceSettingsSection.swift */,
);
path = Settings;
Expand Down Expand Up @@ -2594,7 +2591,6 @@
4C88041822E78D790016CBA9 /* MediaFilesSettings.swift in Sources */,
DC3BE0E12077CD4B002A0AC0 /* Synchronized.swift in Sources */,
DCE5E8B82080D8D9005F60CE /* OCItem+Extension.swift in Sources */,
232F7CAD2097140300EE22E4 /* UploadsSettingsSection.swift in Sources */,
4CB8ADDE22DF5D3700F1FEBC /* PHPhotoLibrary+Extension.swift in Sources */,
DCB44D852186FEF700DAA4CC /* ThemeStyle+DefaultStyles.swift in Sources */,
597A404920AD59EF00B028B2 /* AppLockWindow.swift in Sources */,
Expand Down
4 changes: 2 additions & 2 deletions ownCloud.xcodeproj/xcshareddata/xcschemes/ownCloud.xcscheme
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,8 @@
</EnvironmentVariable>
<EnvironmentVariable
key = "oc:log.log-omit-tags"
value = "[Request,Response]"
isEnabled = "NO">
value = "[BGMAN]"
isEnabled = "YES">
</EnvironmentVariable>
<EnvironmentVariable
key = "oc:log.log-blank-filtered-messages"
Expand Down
107 changes: 102 additions & 5 deletions ownCloud/Client/ClientQueryViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ extension OCQueryState {
}
}

class ClientQueryViewController: QueryFileListTableViewController, UIDropInteractionDelegate, UIPopoverPresentationControllerDelegate {
class ClientQueryViewController: QueryFileListTableViewController, UIDropInteractionDelegate, UIPopoverPresentationControllerDelegate, UISearchControllerDelegate {
var selectedItemIds = Set<OCLocalID>()

var actions : [Action]?
Expand All @@ -58,8 +58,50 @@ class ClientQueryViewController: QueryFileListTableViewController, UIDropInterac

private var _actionProgressHandler : ActionProgressHandler?

private var _query : OCQuery
override var query : OCQuery {
set {
_query = newValue
}

get {
if let customSearchQuery = customSearchQuery {
return customSearchQuery
} else {
return _query
}
}
}
var customSearchQuery : OCQuery? {
willSet {
if customSearchQuery != newValue, let query = customSearchQuery {
core?.stop(query)
query.delegate = nil
}
}

didSet {
if customSearchQuery != nil, let query = customSearchQuery {
query.delegate = self
query.sortComparator = sortMethod.comparator(direction: sortDirection)
core?.start(query)
}
}
}
override var searchScope: SearchScope {
set {
UserDefaults.standard.setValue(newValue.rawValue, forKey: "search-scope")
}

get {
let scope = SearchScope(rawValue: UserDefaults.standard.integer(forKey: "search-scope")) ?? SearchScope.local
return scope
}
}

// MARK: - Init & Deinit
public override init(core inCore: OCCore, query inQuery: OCQuery) {
_query = inQuery
super.init(core: inCore, query: inQuery)

let lastPathComponent = (query.queryPath as NSString?)!.lastPathComponent
Expand Down Expand Up @@ -126,6 +168,49 @@ class ClientQueryViewController: QueryFileListTableViewController, UIDropInterac
}
}

// MARK: - Search events
func willPresentSearchController(_ searchController: UISearchController) {
self.sortBar?.showSearchScope = true
}

func willDismissSearchController(_ searchController: UISearchController) {
self.sortBar?.showSearchScope = false
}

// MARK: - Search scope support
private var searchText: String?

override func applySearchFilter(for searchText: String?, to query: OCQuery) {
self.searchText = searchText

updateCustomSearchQuery()
}

override func sortBar(_ sortBar: SortBar, didUpdateSearchScope: SearchScope) {
updateCustomSearchQuery()
}

override func sortBar(_ sortBar: SortBar, didUpdateSortMethod: SortMethod) {
sortMethod = didUpdateSortMethod

let comparator = sortMethod.comparator(direction: sortDirection)

_query.sortComparator = comparator
customSearchQuery?.sortComparator = comparator
}

func updateCustomSearchQuery() {
if let searchText = searchText, let searchScope = sortBar?.searchScope, searchScope == .global {
self.customSearchQuery = OCQuery(condition: .where(.name, contains: searchText), inputFilter: nil)
} else {
self.customSearchQuery = nil
}

super.applySearchFilter(for: searchText, to: _query)

self.queryHasChangesAvailable(query)
}

// MARK: - View controller events
override func viewDidLoad() {
super.viewDidLoad()
Expand Down Expand Up @@ -170,6 +255,12 @@ class ClientQueryViewController: QueryFileListTableViewController, UIDropInterac

private var viewControllerVisible : Bool = false

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

searchController?.delegate = self
}

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)

Expand Down Expand Up @@ -588,10 +679,16 @@ class ClientQueryViewController: QueryFileListTableViewController, UIDropInterac

// MARK: - Updates
override func performUpdatesWithQueryChanges(query: OCQuery, changeSet: OCQueryChangeSet?) {
if let rootItem = self.query.rootItem {
if query.queryPath != "/" {
let totalSize = String(format: "Total: %@".localized, rootItem.sizeLocalized)
self.updateFooter(text: totalSize)
if query == self.query {
super.performUpdatesWithQueryChanges(query: query, changeSet: changeSet)

if let rootItem = self.query.rootItem, searchText == nil {
if query.queryPath != "/" {
let totalSize = String(format: "Total: %@".localized, rootItem.sizeLocalized)
self.updateFooter(text: totalSize)
}
} else {
self.updateFooter(text: nil)
}
}
}
Expand Down
72 changes: 67 additions & 5 deletions ownCloud/Client/SortBar.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,32 @@ class SegmentedControl: UISegmentedControl {
}
}

public enum SearchScope : Int, CaseIterable {
case global
case local

var label : String {
var name : String!

switch self {
case .global: name = "all".localized
case .local: name = "folder".localized
}

return name
}
}

protocol SortBarDelegate: class {

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

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

func sortBar(_ sortBar: SortBar, didUpdateSearchScope: SearchScope)

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

func toggleSelectMode()
Expand All @@ -66,13 +85,27 @@ class SortBar: UIView, Themeable, UIPopoverPresentationControllerDelegate {

var sortSegmentedControl: SegmentedControl?
var sortButton: UIButton?
var searchScopeSegmentedControl : SegmentedControl?
var selectButton: UIButton?
var showSelectButton: Bool = false {
didSet {
selectButton?.isHidden = !showSelectButton
}
}

var showSearchScope: Bool = false {
didSet {
self.searchScopeSegmentedControl?.isHidden = false
self.searchScopeSegmentedControl?.alpha = oldValue ? 1.0 : 0.0

UIView.animate(withDuration: 0.3, animations: {
self.searchScopeSegmentedControl?.alpha = self.showSearchScope ? 1.0 : 0.0
}, completion: { (_) in
self.searchScopeSegmentedControl?.isHidden = !self.showSearchScope
})
}
}

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)
Expand Down Expand Up @@ -103,36 +136,57 @@ class SortBar: UIView, Themeable, UIPopoverPresentationControllerDelegate {
}
}

var searchScope : SearchScope {
didSet {
delegate?.searchScope = searchScope
searchScopeSegmentedControl?.selectedSegmentIndex = searchScope.rawValue
}
}

// MARK: - Init & Deinit

init(frame: CGRect, sortMethod: SortMethod) {
init(frame: CGRect, sortMethod: SortMethod, searchScope: SearchScope = .local) {
sortSegmentedControl = SegmentedControl()
selectButton = UIButton()
sortButton = UIButton(type: .system)
searchScopeSegmentedControl = SegmentedControl()

self.sortMethod = sortMethod
self.searchScope = searchScope

super.init(frame: frame)

if let sortButton = sortButton, let sortSegmentedControl = sortSegmentedControl, let selectButton = selectButton {
if let sortButton = sortButton, let sortSegmentedControl = sortSegmentedControl, let searchScopeSegmentedControl = searchScopeSegmentedControl, let selectButton = selectButton {
sortButton.translatesAutoresizingMaskIntoConstraints = false
sortSegmentedControl.translatesAutoresizingMaskIntoConstraints = false
selectButton.translatesAutoresizingMaskIntoConstraints = false
searchScopeSegmentedControl.translatesAutoresizingMaskIntoConstraints = false

sortButton.accessibilityIdentifier = "sort-bar.sortButton"
sortSegmentedControl.accessibilityIdentifier = "sort-bar.segmentedControl"
searchScopeSegmentedControl.accessibilityIdentifier = "sort-bar.searchScopeSegmentedControl"

for scope in SearchScope.allCases {
searchScopeSegmentedControl.insertSegment(withTitle: scope.label, at: scope.rawValue, animated:false)
}
searchScopeSegmentedControl.selectedSegmentIndex = searchScope.rawValue
searchScopeSegmentedControl.isHidden = !self.showSearchScope
searchScopeSegmentedControl.addTarget(self, action: #selector(searchScopeValueChanged), for: .valueChanged)

self.addSubview(sortSegmentedControl)
self.addSubview(sortButton)
self.addSubview(searchScopeSegmentedControl)
self.addSubview(selectButton)

// Sort segmented control
NSLayoutConstraint.activate([
sortSegmentedControl.topAnchor.constraint(equalTo: self.topAnchor, constant: topPadding),
sortSegmentedControl.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -bottomPadding),
sortSegmentedControl.centerXAnchor.constraint(equalTo: self.centerXAnchor),
sortSegmentedControl.leftAnchor.constraint(greaterThanOrEqualTo: self.leftAnchor, constant: leftPadding),
sortSegmentedControl.rightAnchor.constraint(lessThanOrEqualTo: self.rightAnchor, constant: -rightPadding)
sortSegmentedControl.leftAnchor.constraint(equalTo: self.leftAnchor, constant: leftPadding),

searchScopeSegmentedControl.trailingAnchor.constraint(equalTo: selectButton.leadingAnchor, constant: -10),
searchScopeSegmentedControl.topAnchor.constraint(equalTo: self.topAnchor, constant: topPadding),
searchScopeSegmentedControl.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -bottomPadding)
])

var longestTitleWidth : CGFloat = 0.0
Expand Down Expand Up @@ -207,6 +261,7 @@ class SortBar: UIView, Themeable, UIPopoverPresentationControllerDelegate {
self.sortButton?.applyThemeCollection(collection)
self.selectButton?.applyThemeCollection(collection)
self.sortSegmentedControl?.applyThemeCollection(collection)
self.searchScopeSegmentedControl?.applyThemeCollection(collection)
self.backgroundColor = collection.navigationBarColors.backgroundColor
}

Expand Down Expand Up @@ -276,6 +331,13 @@ class SortBar: UIView, Themeable, UIPopoverPresentationControllerDelegate {
}
}

@objc private func searchScopeValueChanged() {
if let selectedIndex = searchScopeSegmentedControl?.selectedSegmentIndex {
self.searchScope = SearchScope(rawValue: selectedIndex)!
delegate?.sortBar(self, didUpdateSearchScope: self.searchScope)
}
}

@objc private func toggleSelectMode() {
delegate?.toggleSelectMode()
}
Expand Down
Loading