Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ae4cd1dff3 |
@@ -34,6 +34,7 @@ before_deploy:
|
||||
- brew update
|
||||
- brew outdated carthage || brew upgrade carthage
|
||||
- carthage version
|
||||
- carthage build --no-skip-current --verbose
|
||||
- carthage archive $PROJECTNAME
|
||||
|
||||
deploy:
|
||||
|
||||
@@ -16,7 +16,7 @@ Pod::Spec.new do |s|
|
||||
#
|
||||
|
||||
s.name = "FileProvider"
|
||||
s.version = "0.12.3"
|
||||
s.version = "0.12.4"
|
||||
s.summary = "FileManager replacement for Local and Remote (WebDAV/Dropbox/OneDrive/SMB2) files on iOS and macOS."
|
||||
|
||||
# This description is used to generate tags and improve search results.
|
||||
|
||||
@@ -603,7 +603,7 @@
|
||||
799396601D48B7BF00086753 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_VERSION_STRING = 0.12.3;
|
||||
BUNDLE_VERSION_STRING = 0.12.4;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
@@ -633,7 +633,7 @@
|
||||
799396611D48B7BF00086753 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_VERSION_STRING = 0.12.3;
|
||||
BUNDLE_VERSION_STRING = 0.12.4;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
|
||||
@@ -329,13 +329,56 @@ let data = "What's up Newyork!".data(encoding: .utf8)
|
||||
documentsProvider.writeContents(path: "old.txt", content: data, atomically: true, completionHandler: nil)
|
||||
```
|
||||
|
||||
### Undo Operations
|
||||
|
||||
Providers conform to `FileProviderUndoable` can perform undo for **some** operations like moving/renaming, copying and creating (file or folder). **Now, only `LocalFileProvider` supports this feature.** To implement:
|
||||
|
||||
```swift
|
||||
// To setup a new UndoManager:
|
||||
documentsProvider.setupUndoManager()
|
||||
// or if you have an UndoManager object already:
|
||||
documentsProvider.undoManager = self.undoManager
|
||||
|
||||
// e.g.: To undo last operation manually:
|
||||
documentsProvider.undoManager?.undo()
|
||||
```
|
||||
|
||||
You can also bind `UndoManager` object with view controller to use shake gesture and builtin undo support in iOS/macOS, add these code to your ViewController class like this sample code:
|
||||
|
||||
```swift
|
||||
class ViewController: UIViewController
|
||||
override var canBecomeFirstResponder: Bool {
|
||||
return true
|
||||
}
|
||||
|
||||
override var undoManager: UndoManager? {
|
||||
return (provider as? FileProvideUndoable)?.undoManager
|
||||
}
|
||||
|
||||
override func viewDidAppear(_ animated: Bool) {
|
||||
super.viewDidAppear(animated)
|
||||
// Your code here
|
||||
UIApplication.shared.applicationSupportsShakeToEdit = true
|
||||
self.becomeFirstResponder()
|
||||
}
|
||||
|
||||
override func viewWillDisappear(_ animated: Bool) {
|
||||
super.viewWillDisappear(animated)
|
||||
// Your code here
|
||||
UIApplication.shared.applicationSupportsShakeToEdit = false
|
||||
self.resignFirstResponder()
|
||||
}
|
||||
// The rest of your implementation
|
||||
}
|
||||
```
|
||||
|
||||
### Operation Handle
|
||||
|
||||
Creating/Copying/Deleting functions return a `OperationHandle` for remote operations. It provides operation type, progress and a `.cancel()` method which allows you to cancel operation in midst.
|
||||
|
||||
It's not supported by native `(NS)FileManager` so `LocalFileProvider`, but this functionality will be added to future `PosixFileProvider` class.
|
||||
|
||||
### Monitoring FIle Changes
|
||||
### Monitoring File Changes
|
||||
|
||||
You can monitor updates in some file system (Local and SMB2), there is three methods in supporting provider you can use to register a handler, to unregister and to check whether it's being monitored or not. It's useful to find out when new files added or removed from directory and update user interface. The handler will be dispatched to main threads to avoid UI bugs with a 0.25 sec delay.
|
||||
|
||||
|
||||
@@ -493,9 +493,15 @@ public protocol FileProviderMonitor: FileProviderBasic {
|
||||
}
|
||||
|
||||
public protocol FileProvideUndoable: FileProviderOperations {
|
||||
/// To initialize undo manager either call `setupUndoManager()` or set it manually.
|
||||
///
|
||||
/// - Note: Only some operations (moving/renaming, copying and creating) are supported for undoing.
|
||||
/// - Note: recording operations will occur after setting this object.
|
||||
var undoManager: UndoManager? { get set }
|
||||
|
||||
/// UndoManager supports undoing this file operation
|
||||
func canUndo(handle: OperationHandle) -> Bool
|
||||
/// UndoManager supports undoing this operation
|
||||
func canUndo(operation: FileOperationType) -> Bool
|
||||
}
|
||||
|
||||
@@ -526,6 +532,13 @@ public extension FileProvideUndoable {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
/// Initiates `self.undoManager` if equals with `nil`, and set `levelsOfUndo` to 10.
|
||||
public func setupUndoManager() {
|
||||
guard self.undoManager == nil else { return }
|
||||
self.undoManager = UndoManager()
|
||||
self.undoManager?.levelsOfUndo = 10
|
||||
}
|
||||
}
|
||||
|
||||
public protocol FileProvider: FileProviderBasic, FileProviderOperations, FileProviderReadWrite, NSCopying {
|
||||
|
||||
@@ -200,7 +200,8 @@ open class LocalFileProvider: FileProvider, FileProviderMonitor, FileProvideUndo
|
||||
}
|
||||
|
||||
dynamic func doSimpleOperation(_ box: UndoBox) {
|
||||
_ = self.doOperation(box.operation) { (_) in
|
||||
guard let _ = self.undoManager else { return }
|
||||
_ = self.doOperation(box.undoOperation) { (_) in
|
||||
return
|
||||
}
|
||||
}
|
||||
@@ -209,24 +210,23 @@ open class LocalFileProvider: FileProvider, FileProviderMonitor, FileProvideUndo
|
||||
fileprivate func doOperation(_ opType: FileOperationType, data: Data? = nil, atomically: Bool = false, completionHandler: SimpleCompletionHandler) -> OperationHandle? {
|
||||
guard let sourcePath = opType.source else { return nil }
|
||||
let destPath = opType.destination
|
||||
let source: URL, dest: URL?
|
||||
|
||||
if sourcePath.hasPrefix("file://") {
|
||||
source = URL(string: sourcePath)!
|
||||
} else {
|
||||
source = self.url(of: sourcePath)
|
||||
}
|
||||
let source: URL = sourcePath.hasPrefix("file://") ? URL(string: sourcePath)! : self.url(of: sourcePath)
|
||||
let dest: URL?
|
||||
|
||||
if let destPath = destPath {
|
||||
if destPath.hasPrefix("file://") {
|
||||
dest = URL(string: destPath)!
|
||||
} else {
|
||||
dest = self.url(of: destPath)
|
||||
}
|
||||
dest = destPath.hasPrefix("file://") ? URL(string: destPath)! : self.url(of: destPath)
|
||||
} else {
|
||||
dest = nil
|
||||
}
|
||||
|
||||
if let undoManager = self.undoManager, let undoOp = self.undoOperation(for: opType) {
|
||||
let undoBox = UndoBox(provider: self, operation: opType, undoOperation: undoOp)
|
||||
undoManager.beginUndoGrouping()
|
||||
undoManager.registerUndo(withTarget: self, selector: #selector(LocalFileProvider.doSimpleOperation(_:)), object: undoBox)
|
||||
undoManager.setActionName(opType.actionDescription)
|
||||
undoManager.endUndoGrouping()
|
||||
}
|
||||
|
||||
let operationHandler: (URL, URL?) -> Void = { source, dest in
|
||||
let successfulSecurityScopedResourceAccess = source.startAccessingSecurityScopedResource()
|
||||
do {
|
||||
@@ -254,11 +254,6 @@ open class LocalFileProvider: FileProvider, FileProviderMonitor, FileProvideUndo
|
||||
source.stopAccessingSecurityScopedResource()
|
||||
}
|
||||
|
||||
if let undoOp = self.undoOperation(for: opType) {
|
||||
let undoBox = UndoBox(provider: self, operation: undoOp)
|
||||
self.undoManager?.registerUndo(withTarget: self, selector: #selector(LocalFileProvider.doSimpleOperation(_:)), object: undoBox)
|
||||
}
|
||||
|
||||
completionHandler?(nil)
|
||||
DispatchQueue.main.async {
|
||||
self.delegate?.fileproviderSucceed(self, operation: opType)
|
||||
@@ -354,12 +349,8 @@ open class LocalFileProvider: FileProvider, FileProviderMonitor, FileProvideUndo
|
||||
let url = self.url(of: path)
|
||||
|
||||
let operationHandler: (URL) -> Void = { url in
|
||||
guard self.fileManager.fileExists(atPath: url.path) && !url.fileIsDirectory else {
|
||||
completionHandler(nil, self.throwError(path, code: CocoaError.fileNoSuchFile as FoundationErrorEnum))
|
||||
return
|
||||
}
|
||||
guard let handle = FileHandle(forReadingAtPath: url.path) else {
|
||||
completionHandler(nil, self.throwError(path, code: CocoaError.fileReadNoPermission as FoundationErrorEnum))
|
||||
completionHandler(nil, self.throwError(path, code: CocoaError.fileNoSuchFile as FoundationErrorEnum))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -367,17 +358,18 @@ open class LocalFileProvider: FileProvider, FileProviderMonitor, FileProvideUndo
|
||||
handle.closeFile()
|
||||
}
|
||||
|
||||
let size = LocalFileObject(fileWithURL: url)?.size ?? -1
|
||||
guard size > offset else {
|
||||
completionHandler(nil, self.throwError(path, code: CocoaError.fileReadTooLarge as FoundationErrorEnum))
|
||||
return
|
||||
}
|
||||
handle.seek(toFileOffset: UInt64(offset))
|
||||
guard Int64(handle.offsetInFile) == offset else {
|
||||
completionHandler(nil, self.throwError(path, code: CocoaError.fileReadUnknown as FoundationErrorEnum))
|
||||
completionHandler(nil, self.throwError(path, code: CocoaError.fileReadTooLarge as FoundationErrorEnum))
|
||||
return
|
||||
}
|
||||
|
||||
let data = handle.readData(ofLength: length)
|
||||
guard length > 0 && data.count == length else {
|
||||
completionHandler(nil, self.throwError(path, code: CocoaError.fileReadTooLarge as FoundationErrorEnum))
|
||||
return
|
||||
}
|
||||
|
||||
completionHandler(data, nil)
|
||||
}
|
||||
@@ -462,6 +454,8 @@ open class LocalFileProvider: FileProvider, FileProviderMonitor, FileProvideUndo
|
||||
copy.delegate = self.delegate
|
||||
copy.fileOperationDelegate = self.fileOperationDelegate
|
||||
copy.isPathRelative = self.isPathRelative
|
||||
copy.undoManager = self.undoManager
|
||||
copy.isCoorinating = self.isCoorinating
|
||||
return copy
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,10 +308,12 @@ open class LocalOperationHandle: OperationHandle {
|
||||
class UndoBox: NSObject {
|
||||
weak var provider: FileProvideUndoable?
|
||||
let operation: FileOperationType
|
||||
let undoOperation: FileOperationType
|
||||
|
||||
init(provider: FileProvideUndoable, operation: FileOperationType) {
|
||||
init(provider: FileProvideUndoable, operation: FileOperationType, undoOperation: FileOperationType) {
|
||||
self.provider = provider
|
||||
self.operation = operation
|
||||
self.undoOperation = undoOperation
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user