diff --git a/ios-sdk b/ios-sdk index 57b05c6d6..8c67ac059 160000 --- a/ios-sdk +++ b/ios-sdk @@ -1 +1 @@ -Subproject commit 57b05c6d62bce4301915f08e1a3a97b52a0ac04a +Subproject commit 8c67ac059257409e20ee85d0ad09e4e3d4827023 diff --git a/ownCloud/Client/Actions/Actions+Extensions/CreateDocumentAction.swift b/ownCloud/Client/Actions/Actions+Extensions/CreateDocumentAction.swift index a7c832f63..2814c1cf4 100644 --- a/ownCloud/Client/Actions/Actions+Extensions/CreateDocumentAction.swift +++ b/ownCloud/Client/Actions/Actions+Extensions/CreateDocumentAction.swift @@ -270,6 +270,7 @@ class CreateDocumentAction: Action { } }) + documentNameViewController.requiredFileExtension = fileType.extension documentNameViewController.navigationItem.title = "Pick a name".localized navigationViewController.pushViewController(documentNameViewController, animated: true) diff --git a/ownCloud/Client/Actions/Scanner/ScanViewController.swift b/ownCloud/Client/Actions/Scanner/ScanViewController.swift index 43853dec8..24d4e4288 100644 --- a/ownCloud/Client/Actions/Scanner/ScanViewController.swift +++ b/ownCloud/Client/Actions/Scanner/ScanViewController.swift @@ -287,6 +287,11 @@ class ScanViewController: StaticTableViewController { didSet { if let fileName = fileNameRow?.value as? NSString { fileNameRow?.value = fileName.deletingPathExtension + "." + (exportFormat?.suffix ?? "") + fileNameRow?.requiredFileExtension = exportFormat?.suffix + + if let textField = fileNameRow?.textField, textField.isFirstResponder { + textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.beginningOfDocument) + } } guard let oneFilePerPageRow = oneFilePerPageRow else { return } @@ -315,7 +320,9 @@ class ScanViewController: StaticTableViewController { self.isModalInPresentation = true self.navigationItem.title = "Scan".localized self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(ScanViewController.cancel)) - self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(ScanViewController.save)) + + let saveBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(ScanViewController.save)) + self.navigationItem.rightBarButtonItem = saveBarButtonItem self.core = core self.targetFolderItem = item @@ -353,7 +360,7 @@ class ScanViewController: StaticTableViewController { // Save section // - Name - fileNameRow = StaticTableViewRow(textFieldWithAction: { [weak self] (row, textField, type) in + fileNameRow = StaticTableViewRow(textFieldWithAction: { [weak self, weak saveBarButtonItem] (row, textField, type) in self?.navigationItem.rightBarButtonItem?.isEnabled = ((row.value as? String)?.count ?? 0) > 0 if type == .didBegin, let nameTextField = textField as? UITextField { @@ -369,6 +376,10 @@ class ScanViewController: StaticTableViewController { nameTextField.selectedTextRange = nameTextField.textRange(from: nameTextField.beginningOfDocument, to: nameTextField.endOfDocument) } } + + if let fileName = (textField as? UITextField)?.text, let requiredFileExtension = row.requiredFileExtension { + saveBarButtonItem?.isEnabled = (fileName.count > (requiredFileExtension.count + 1)) + } }, placeholder: "Name".localized, value: fileName ?? "", keyboardType: .default, autocorrectionType: .no, enablesReturnKeyAutomatically: true, returnKeyType: .default, identifier: "name", accessibilityLabel: "Name".localized) saveSection.add(row: fileNameRow!) self.addSection(saveSection) diff --git a/ownCloudAppShared/Client/User Interface/NamingViewController.swift b/ownCloudAppShared/Client/User Interface/NamingViewController.swift index 7aff8f858..0f457a0e5 100644 --- a/ownCloudAppShared/Client/User Interface/NamingViewController.swift +++ b/ownCloudAppShared/Client/User Interface/NamingViewController.swift @@ -19,8 +19,8 @@ import UIKit import ownCloudSDK -public typealias StringValidatorResult = (Bool, String?, String?) -public typealias StringValidatorHandler = (String) -> StringValidatorResult +public typealias StringValidatorResult = (Bool, String?, String?) // (validationPassed, validationErrorTitle, validationErrorMessage) +public typealias StringValidatorHandler = (_ stringToCheck: String) -> StringValidatorResult open class NamingViewController: UIViewController { weak open var item: OCItem? @@ -28,6 +28,7 @@ open class NamingViewController: UIViewController { open var completion: (String?, NamingViewController) -> Void open var stringValidator: StringValidatorHandler? open var defaultName: String? + open var requiredFileExtension: String? private var blurView: UIVisualEffectView @@ -37,7 +38,7 @@ open class NamingViewController: UIViewController { private var thumbnailImageView: ResourceViewHost private var nameContainer: UIView - private var nameTextField: UITextField + private var nameTextField: ThemeCSSTextField private var textfieldTopAnchorConstraint: NSLayoutConstraint private var textfieldCenterYAnchorConstraint: NSLayoutConstraint @@ -152,6 +153,7 @@ open class NamingViewController: UIViewController { // Name textfield nameTextField.translatesAutoresizingMaskIntoConstraints = false + nameTextField.requiredFileExtension = requiredFileExtension nameContainer.addSubview(nameTextField) NSLayoutConstraint.activate([ nameTextField.heightAnchor.constraint(equalToConstant: 40), @@ -267,7 +269,9 @@ open class NamingViewController: UIViewController { } @objc open func textfieldDidChange(_ sender: UITextField) { - if sender.text != "" { + let filename = sender.text + + if filename != "", requiredFileExtension == nil || ((requiredFileExtension != nil) && filename != ".\(requiredFileExtension!)") { doneButton?.isEnabled = true } else { doneButton?.isEnabled = false @@ -351,7 +355,15 @@ extension NamingViewController: UITextFieldDelegate { } else { textField.selectedTextRange = nameTextField.textRange(from: nameTextField.beginningOfDocument, to: nameTextField.endOfDocument) } + } + public func textFieldShouldClear(_ textField: UITextField) -> Bool { + if let requiredFileExtension { + textField.text = "." + requiredFileExtension + textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.beginningOfDocument) + return false + } + return true } open func textFieldShouldReturn(_ textField: UITextField) -> Bool { diff --git a/ownCloudAppShared/User Interface/StaticTableView/StaticTableViewRow.swift b/ownCloudAppShared/User Interface/StaticTableView/StaticTableViewRow.swift index aabbad6fa..ff607e669 100644 --- a/ownCloudAppShared/User Interface/StaticTableView/StaticTableViewRow.swift +++ b/ownCloudAppShared/User Interface/StaticTableView/StaticTableViewRow.swift @@ -528,6 +528,21 @@ open class StaticTableViewRow : NSObject, UITextFieldDelegate { return true } + public func textFieldShouldClear(_ textField: UITextField) -> Bool { + if let requiredFileExtension { + textField.text = "." + requiredFileExtension + textField.selectedTextRange = textField.textRange(from: textField.beginningOfDocument, to: textField.beginningOfDocument) + return false + } + return true + } + + open var requiredFileExtension: String? { + didSet { + (textField as? ThemeCSSTextField)?.requiredFileExtension = requiredFileExtension + } + } + // MARK: - Labels convenience public init(label: String, accessoryView: UIView? = nil, identifier: String? = nil) { self.init() diff --git a/ownCloudAppShared/User Interface/Theme/CSS/Views/ThemeCSSTextField.swift b/ownCloudAppShared/User Interface/Theme/CSS/Views/ThemeCSSTextField.swift index d22b6e34c..4b37e38e7 100644 --- a/ownCloudAppShared/User Interface/Theme/CSS/Views/ThemeCSSTextField.swift +++ b/ownCloudAppShared/User Interface/Theme/CSS/Views/ThemeCSSTextField.swift @@ -18,9 +18,20 @@ import UIKit +public extension UITextInput { + func range(from textRange: UITextRange) -> NSRange { + let startOffset = offset(from: beginningOfDocument, to: textRange.start) + let endOffset = offset(from: beginningOfDocument, to: textRange.end) + + return NSRange(location: startOffset, length: endOffset-startOffset+1) + } +} + public class ThemeCSSTextField: UITextField, Themeable { private var hasRegistered : Bool = false + open var requiredFileExtension: String? + override open func didMoveToWindow() { super.didMoveToWindow() @@ -41,4 +52,26 @@ public class ThemeCSSTextField: UITextField, Themeable { open func applyThemeCollection(theme: Theme, collection: ThemeCollection, event: ThemeEvent) { self.applyThemeCollection(collection) } + + public override func shouldChangeText(in range: UITextRange, replacementText: String) -> Bool { + if let requiredFileExtension, let previousText = text, + let textRange = Range(self.range(from: range), in: previousText) { + let newName = previousText.replacingCharacters(in: textRange, with: replacementText) + return (newName as NSString).pathExtension == requiredFileExtension || (newName == ".\(requiredFileExtension)") + } + + return super.shouldChangeText(in: range, replacementText: replacementText) + } + + public override var selectedTextRange: UITextRange? { + didSet { + if let requiredFileExtension { + if let selectedTextRange, + let maxAllowedPosition = position(from: endOfDocument, offset: -requiredFileExtension.count-1), + compare(selectedTextRange.end, to: maxAllowedPosition) == .orderedDescending { + self.selectedTextRange = textRange(from: selectedTextRange.start, to: maxAllowedPosition) + } + } + } + } }