123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229 |
- import Foundation
- import Capacitor
- import IONFilesystemLib
- typealias FileService = any IONFILEDirectoryManager & IONFILEFileManager
- /**
- * Please read the Capacitor iOS Plugin Development Guide
- * here: https://capacitorjs.com/docs/plugins/ios
- */
- @objc(FilesystemPlugin)
- public class FilesystemPlugin: CAPPlugin, CAPBridgedPlugin {
- public let identifier = "FilesystemPlugin"
- public let jsName = "Filesystem"
- public let pluginMethods: [CAPPluginMethod] = [
- CAPPluginMethod(name: "readFile", returnType: CAPPluginReturnPromise),
- CAPPluginMethod(name: "readFileInChunks", returnType: CAPPluginReturnCallback),
- CAPPluginMethod(name: "writeFile", returnType: CAPPluginReturnPromise),
- CAPPluginMethod(name: "appendFile", returnType: CAPPluginReturnPromise),
- CAPPluginMethod(name: "deleteFile", returnType: CAPPluginReturnPromise),
- CAPPluginMethod(name: "mkdir", returnType: CAPPluginReturnPromise),
- CAPPluginMethod(name: "rmdir", returnType: CAPPluginReturnPromise),
- CAPPluginMethod(name: "readdir", returnType: CAPPluginReturnPromise),
- CAPPluginMethod(name: "getUri", returnType: CAPPluginReturnPromise),
- CAPPluginMethod(name: "stat", returnType: CAPPluginReturnPromise),
- CAPPluginMethod(name: "rename", returnType: CAPPluginReturnPromise),
- CAPPluginMethod(name: "copy", returnType: CAPPluginReturnPromise),
- CAPPluginMethod(name: "checkPermissions", returnType: CAPPluginReturnPromise),
- CAPPluginMethod(name: "requestPermissions", returnType: CAPPluginReturnPromise),
- CAPPluginMethod(name: "downloadFile", returnType: CAPPluginReturnPromise)
- ]
- private let legacyImplementation = LegacyFilesystemImplementation()
- private var fileService: FileService?
- override public func load() {
- self.fileService = IONFILEManager()
- }
- func getService() -> Result<FileService, FilesystemError> {
- if fileService == nil { load() }
- return fileService.map(Result.success) ?? .failure(.bridgeNotInitialised)
- }
- @objc override public func checkPermissions(_ call: CAPPluginCall) {
- call.handlePermissionSuccess()
- }
- @objc override public func requestPermissions(_ call: CAPPluginCall) {
- call.handlePermissionSuccess()
- }
- }
- // MARK: - Public API Methods
- private extension FilesystemPlugin {
- /**
- * Read a file from the filesystem.
- */
- @objc func readFile(_ call: CAPPluginCall) {
- let encoding = call.getEncoding(Constants.MethodParameter.encoding)
- performSinglePathOperation(call) {
- .readFile(url: $0, encoding: encoding)
- }
- }
- @objc func readFileInChunks(_ call: CAPPluginCall) {
- let encoding = call.getEncoding(Constants.MethodParameter.encoding)
- guard let chunkSize = call.getInt(Constants.MethodParameter.chunkSize) else {
- return call.handleError(.invalidInput(method: call.getIONFileMethod()))
- }
- performSinglePathOperation(call) {
- .readFileInChunks(url: $0, encoding: encoding, chunkSize: chunkSize)
- }
- }
- /**
- * Write a file to the filesystem.
- */
- @objc func writeFile(_ call: CAPPluginCall) {
- guard let encodingMapper = call.getEncodingMapper() else {
- return call.handleError(.invalidInput(method: call.getIONFileMethod()))
- }
- let recursive = call.getBool(Constants.MethodParameter.recursive, false)
- performSinglePathOperation(call) {
- .write(url: $0, encodingMapper: encodingMapper, recursive: recursive)
- }
- }
- /**
- * Append to a file.
- */
- @objc func appendFile(_ call: CAPPluginCall) {
- guard let encodingMapper = call.getEncodingMapper() else {
- return call.handleError(.invalidInput(method: call.getIONFileMethod()))
- }
- let recursive = call.getBool(Constants.MethodParameter.recursive, false)
- performSinglePathOperation(call) {
- .append(url: $0, encodingMapper: encodingMapper, recursive: recursive)
- }
- }
- /**
- * Delete a file.
- */
- @objc func deleteFile(_ call: CAPPluginCall) {
- performSinglePathOperation(call) {
- .delete(url: $0)
- }
- }
- /**
- * Make a new directory, optionally creating parent folders first.
- */
- @objc func mkdir(_ call: CAPPluginCall) {
- let recursive = call.getBool(Constants.MethodParameter.recursive, false)
- performSinglePathOperation(call) {
- .mkdir(url: $0, recursive: recursive)
- }
- }
- /**
- * Remove a directory.
- */
- @objc func rmdir(_ call: CAPPluginCall) {
- let recursive = call.getBool(Constants.MethodParameter.recursive, false)
- performSinglePathOperation(call) {
- .rmdir(url: $0, recursive: recursive)
- }
- }
- /**
- * Read the contents of a directory.
- */
- @objc func readdir(_ call: CAPPluginCall) {
- performSinglePathOperation(call) {
- .readdir(url: $0)
- }
- }
- @objc func stat(_ call: CAPPluginCall) {
- performSinglePathOperation(call) {
- .stat(url: $0)
- }
- }
- @objc func getUri(_ call: CAPPluginCall) {
- performSinglePathOperation(call) {
- .getUri(url: $0)
- }
- }
- /**
- * Rename a file or directory.
- */
- @objc func rename(_ call: CAPPluginCall) {
- performDualPathOperation(call) {
- .rename(source: $0, destination: $1)
- }
- }
- /**
- * Copy a file or directory.
- */
- @objc func copy(_ call: CAPPluginCall) {
- performDualPathOperation(call) {
- .copy(source: $0, destination: $1)
- }
- }
- /**
- * [DEPRECATED] Download a file
- */
- @available(*, deprecated, message: "Use @capacitor/file-transfer plugin instead.")
- @objc func downloadFile(_ call: CAPPluginCall) {
- guard let url = call.getString("url") else { return call.reject("Must provide a URL") }
- let progressEmitter: LegacyFilesystemImplementation.ProgressEmitter = { bytes, contentLength in
- self.notifyListeners("progress", data: [
- "url": url,
- "bytes": bytes,
- "contentLength": contentLength
- ])
- }
- do {
- try legacyImplementation.downloadFile(call: call, emitter: progressEmitter, config: bridge?.config)
- } catch let error {
- call.reject(error.localizedDescription)
- }
- }
- }
- // MARK: - Operation Execution
- private extension FilesystemPlugin {
- func performSinglePathOperation(_ call: CAPPluginCall, operationBuilder: (URL) -> FilesystemOperation) {
- executeOperation(call) { service in
- FilesystemLocationResolver(service: service)
- .resolveSinglePath(from: call)
- .map { operationBuilder($0) }
- }
- }
- func performDualPathOperation(_ call: CAPPluginCall, operationBuilder: (URL, URL) -> FilesystemOperation) {
- executeOperation(call) { service in
- FilesystemLocationResolver(service: service)
- .resolveDualPaths(from: call)
- .map { operationBuilder($0.source, $0.destination) }
- }
- }
- func executeOperation(_ call: CAPPluginCall, operationProvider: (FileService) -> Result<FilesystemOperation, FilesystemError>) {
- switch getService() {
- case .success(let service):
- switch operationProvider(service) {
- case .success(let operation):
- let executor = FilesystemOperationExecutor(service: service)
- executor.execute(operation, call)
- case .failure(let error):
- call.handleError(error)
- }
- case .failure(let error):
- call.handleError(error)
- }
- }
- }
|