UNPKG

@nativescript/core

Version:

A JavaScript library providing an easy to use api for interacting with iOS and Android platform APIs.

880 lines • 29.3 kB
import { FileSystemAccess, FileSystemAccess29 } from './file-system-access'; import { SDK_VERSION } from '../utils'; import { Application } from '../application'; // The FileSystemAccess implementation, used through all the APIs. let fileAccess; /** * Returns FileSystemAccess, a shared singleton utility class to provide methods to access and work with the file system. This is used under the hood of all the file system apis in @nativescript/core and provided as a lower level convenience if needed. * @returns FileSystemAccess */ export function getFileAccess() { if (!fileAccess) { if (__ANDROID__ && SDK_VERSION >= 29) { fileAccess = new FileSystemAccess29(); } else { fileAccess = new FileSystemAccess(); } } return fileAccess; } function createFile(info) { const file = new File(); file._path = info.path; file._name = info.name; file._extension = info.extension; return file; } function createFolder(info) { const documents = knownFolders.documents(); if (info.path === documents.path) { return documents; } const temp = knownFolders.temp(); if (info.path === temp.path) { return temp; } const folder = new Folder(); folder._path = info.path; folder._name = info.name; return folder; } export class FileSystemEntity { get parent() { const onError = function (error) { throw error; }; const folderInfo = getFileAccess().getParent(this.path, onError); if (!folderInfo) { return undefined; } return createFolder(folderInfo); } remove() { return new Promise((resolve, reject) => { let hasError = false; const localError = function (error) { hasError = true; reject(error); }; this.removeSync(localError); if (!hasError) { resolve(true); } }); } removeSync(onError) { if (this._isKnown) { if (onError) { onError({ message: 'Cannot delete known folder.' }); } return; } const fileAccess = getFileAccess(); if (this instanceof File) { fileAccess.deleteFile(this.path, onError); } else if (this instanceof Folder) { fileAccess.deleteFolder(this.path, onError); } } rename(newName) { return new Promise((resolve, reject) => { let hasError = false; const localError = function (error) { hasError = true; reject(error); }; this.renameSync(newName, localError); if (!hasError) { resolve(true); } }); } renameSync(newName, onError) { if (this._isKnown) { if (onError) { onError(new Error('Cannot rename known folder.')); } return; } const localError = function (error) { if (onError) { onError(error); } return null; }; const fileAccess = getFileAccess(); // call rename for FileSystemAccess29 if (fileAccess.__skip) { fileAccess.rename(this.path, newName, localError); const fileInfo = getFileAccess().getFile(this.path, null); if (fileInfo) { this._name = fileInfo.name; this._extension = fileInfo.extension; } return; } const parentFolder = this.parent; if (!parentFolder) { if (onError) { onError(new Error('No parent folder.')); } return; } const path = parentFolder.path; const newPath = fileAccess.joinPath(path, newName); fileAccess.rename(this.path, newPath, localError); this._path = newPath; this._name = newName; if (this instanceof File) { this._extension = fileAccess.getFileExtension(newPath); } } get name() { return this._name; } get path() { return this._path; } get lastModified() { return getFileAccess().getLastModified(this.path); } } let applicationContext; function getApplicationContext() { if (!applicationContext) { applicationContext = Application.android.getNativeApplication().getApplicationContext(); } return applicationContext; } export var AndroidDirectory; (function (AndroidDirectory) { AndroidDirectory["ALARMS"] = "alarms"; AndroidDirectory["AUDIOBOOKS"] = "audiobooks"; AndroidDirectory["DCIM"] = "dcim"; AndroidDirectory["DOCUMENTS"] = "documents"; AndroidDirectory["DOWNLOADS"] = "downloads"; AndroidDirectory["MOVIES"] = "movies"; AndroidDirectory["MUSIC"] = "music"; AndroidDirectory["NOTIFICATIONS"] = "notifications"; AndroidDirectory["PICTURES"] = "pictures"; AndroidDirectory["PODCASTS"] = "podcasts"; AndroidDirectory["RINGTONES"] = "ringtones"; AndroidDirectory["SCREENSHOTS"] = "screenshots"; })(AndroidDirectory || (AndroidDirectory = {})); function getAndroidDirectory(value) { switch (value) { case AndroidDirectory.ALARMS: return { path: android.os.Environment.DIRECTORY_ALARMS, column: android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, }; case AndroidDirectory.AUDIOBOOKS: return { path: android.os.Environment.DIRECTORY_AUDIOBOOKS, column: android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, }; case AndroidDirectory.DCIM: return { path: android.os.Environment.DIRECTORY_DCIM, column: android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, }; case AndroidDirectory.DOCUMENTS: return { path: android.os.Environment.DIRECTORY_DOCUMENTS, column: android.provider.MediaStore.Files.getContentUri('external'), }; case AndroidDirectory.DOWNLOADS: return { path: android.os.Environment.DIRECTORY_DOWNLOADS, column: android.provider.MediaStore.Downloads.EXTERNAL_CONTENT_URI, }; case AndroidDirectory.MOVIES: return { path: android.os.Environment.DIRECTORY_MOVIES, column: android.provider.MediaStore.Video.Media.EXTERNAL_CONTENT_URI, }; case AndroidDirectory.MUSIC: return { path: android.os.Environment.DIRECTORY_MUSIC, column: android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, }; case AndroidDirectory.NOTIFICATIONS: return { path: android.os.Environment.DIRECTORY_NOTIFICATIONS, column: android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, }; case AndroidDirectory.PICTURES: return { path: android.os.Environment.DIRECTORY_PICTURES, column: android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, }; case AndroidDirectory.PODCASTS: return { path: android.os.Environment.DIRECTORY_PODCASTS, column: android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, }; case AndroidDirectory.RINGTONES: return { path: android.os.Environment.DIRECTORY_RINGTONES, column: android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, }; case AndroidDirectory.SCREENSHOTS: return { path: android.os.Environment.DIRECTORY_SCREENSHOTS, column: android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI, }; default: return null; } } class Android { createFile(options) { if (!__ANDROID__) { throw new Error(`createFile is available on Android only!`); } const context = getApplicationContext(); const meta = new android.content.ContentValues(); meta.put(android.provider.MediaStore.MediaColumns.DISPLAY_NAME, options.name); meta.put(android.provider.MediaStore.MediaColumns.MIME_TYPE, options.mime); //meta.put(android.provider.MediaStore.MediaColumns.DATE_ADDED, java.lang.System.currentTimeMillis() as any); const externalDirectory = getAndroidDirectory(options.directory); if (SDK_VERSION >= 29) { const relativePath = options?.relativePath ? `/${options.relativePath}` : ''; meta.put(android.provider.MediaStore.MediaColumns.RELATIVE_PATH, `${externalDirectory.path}${relativePath}`); // todo // meta.put(android.provider.MediaStore.MediaColumns.IS_PENDING, java.lang.Integer.valueOf(1)); } else { const relativePath = options?.relativePath ? `${options.relativePath}/` : ''; const directory = android.os.Environment.getExternalStoragePublicDirectory(externalDirectory.path); const file = new java.io.File(directory, `${relativePath}${options.name}`); meta.put(android.provider.MediaStore.MediaColumns.DATA, file.getAbsolutePath()); } const uri = context.getContentResolver().insert(externalDirectory.column, meta); return File.fromPath(uri.toString()); } } const ad = new Android(); class iOS { } const ios = new iOS(); export class File extends FileSystemEntity { static get ios() { return ios; } static get android() { return ad; } static fromPath(path, copy = false) { const onError = function (error) { throw error; }; if (__ANDROID__ && copy) { if (path.startsWith('content:')) { const fileInfo = getFileAccess().getFile(path, onError); // falls back to creating a temp file without a known extension. if (!fileInfo) { const tempFile = `${knownFolders.temp().path}/${java.util.UUID.randomUUID().toString()}`; org.nativescript.widgets.Async.File.copySync(path, tempFile, getApplicationContext()); path = tempFile; } else { const ext = fileInfo.extension; const name = `${fileInfo.name.replace(`.${ext}`, '')}.${ext}`; const tempFile = `${knownFolders.temp().path}/${name}`; getFileAccess().copySync(path, tempFile); path = tempFile; } } } const fileInfo = getFileAccess().getFile(path, onError); if (!fileInfo) { return undefined; } return createFile(fileInfo); } static exists(path) { return getFileAccess().fileExists(path); } get extension() { return this._extension; } get isLocked() { // !! is a boolean conversion/cast, handling undefined as well return !!this._locked; } get size() { return getFileAccess().getFileSize(this.path); } append(content) { return new Promise((resolve, reject) => { try { this._checkAccess(); } catch (ex) { reject(ex); return; } this._locked = true; getFileAccess() .appendAsync(this.path, content) .then(() => { resolve(); this._locked = false; }, (error) => { reject(error); this._locked = false; }); }); } appendSync(content, onError) { this._checkAccess(); try { this._locked = true; const that = this; const localError = function (error) { that._locked = false; if (onError) { onError(error); } }; getFileAccess().appendSync(this.path, content, localError); } finally { this._locked = false; } } appendText(content, encoding) { return new Promise((resolve, reject) => { try { this._checkAccess(); } catch (ex) { reject(ex); return; } this._locked = true; getFileAccess() .appendTextAsync(this.path, content, encoding) .then(() => { resolve(true); this._locked = false; }, (error) => { reject(error); this._locked = false; }); }); } appendTextSync(content, onError, encoding) { this._checkAccess(); try { this._locked = true; const that = this; const localError = function (error) { that._locked = false; if (onError) { onError(error); } }; getFileAccess().appendTextSync(this.path, content, localError, encoding); } finally { this._locked = false; } } copy(dest) { return new Promise((resolve, reject) => { try { this._checkAccess(); } catch (ex) { reject(ex); return; } this._locked = true; getFileAccess() .copyAsync(this.path, dest) .then((result) => { resolve(result); this._locked = false; }, (error) => { reject(error); this._locked = false; }); }); } copySync(dest, onError) { this._checkAccess(); this._locked = true; const that = this; const localError = (error) => { that._locked = false; if (onError) { onError(error); } }; const content = getFileAccess().copySync(this.path, dest, localError); this._locked = false; return content; } read() { return new Promise((resolve, reject) => { try { this._checkAccess(); } catch (ex) { reject(ex); return; } this._locked = true; getFileAccess() .readAsync(this.path) .then((result) => { resolve(result); this._locked = false; }, (error) => { reject(error); this._locked = false; }); }); } readSync(onError) { this._checkAccess(); this._locked = true; const that = this; const localError = (error) => { that._locked = false; if (onError) { onError(error); } }; const content = getFileAccess().readSync(this.path, localError); this._locked = false; return content; } write(content) { return new Promise((resolve, reject) => { try { this._checkAccess(); } catch (ex) { reject(ex); return; } this._locked = true; getFileAccess() .writeAsync(this.path, content) .then(() => { resolve(); this._locked = false; }, (error) => { reject(error); this._locked = false; }); }); } writeSync(content, onError) { this._checkAccess(); try { this._locked = true; const that = this; const localError = function (error) { that._locked = false; if (onError) { onError(error); } }; getFileAccess().writeSync(this.path, content, localError); } finally { this._locked = false; } } readText(encoding) { return new Promise((resolve, reject) => { try { this._checkAccess(); } catch (ex) { reject(ex); return; } this._locked = true; getFileAccess() .readTextAsync(this.path, encoding) .then((result) => { resolve(result); this._locked = false; }, (error) => { reject(error); this._locked = false; }); }); } readTextSync(onError, encoding) { this._checkAccess(); this._locked = true; const that = this; const localError = (error) => { that._locked = false; if (onError) { onError(error); } }; const content = getFileAccess().readTextSync(this.path, localError, encoding); this._locked = false; return content; } writeText(content, encoding) { return new Promise((resolve, reject) => { try { this._checkAccess(); } catch (ex) { reject(ex); return; } this._locked = true; getFileAccess() .writeTextAsync(this.path, content, encoding) .then(() => { resolve(true); this._locked = false; }, (error) => { reject(error); this._locked = false; }); }); } writeTextSync(content, onError, encoding) { this._checkAccess(); try { this._locked = true; const that = this; const localError = function (error) { that._locked = false; if (onError) { onError(error); } }; getFileAccess().writeTextSync(this.path, content, localError, encoding); } finally { this._locked = false; } } _checkAccess() { if (this.isLocked) { throw new Error('Cannot access a locked file.'); } } } export class Folder extends FileSystemEntity { static fromPath(path) { const onError = function (error) { throw error; }; const folderInfo = getFileAccess().getFolder(path, onError); if (!folderInfo) { return undefined; } return createFolder(folderInfo); } static exists(path) { return getFileAccess().folderExists(path); } contains(name) { const fileAccess = getFileAccess(); const path = fileAccess.joinPath(this.path, name); if (fileAccess.fileExists(path)) { return true; } return fileAccess.folderExists(path); } clear() { return new Promise((resolve, reject) => { let hasError = false; const onError = function (error) { hasError = true; reject(error); }; this.clearSync(onError); if (!hasError) { resolve(true); } }); } clearSync(onError) { getFileAccess().emptyFolder(this.path, onError); } get isKnown() { return this._isKnown; } getFile(name) { const fileAccess = getFileAccess(); const path = fileAccess.joinPath(this.path, name); const onError = function (error) { throw error; }; const fileInfo = fileAccess.getFile(path, onError); if (!fileInfo) { return undefined; } return createFile(fileInfo); } getFolder(name) { const fileAccess = getFileAccess(); const path = fileAccess.joinPath(this.path, name); const onError = function (error) { throw error; }; const folderInfo = fileAccess.getFolder(path, onError); if (!folderInfo) { return undefined; } return createFolder(folderInfo); } getEntities() { return new Promise((resolve, reject) => { let hasError = false; const localError = function (error) { hasError = true; reject(error); }; const entities = this.getEntitiesSync(localError); if (!hasError) { resolve(entities); } }); } getEntitiesSync(onError) { const fileInfos = getFileAccess().getEntities(this.path, onError); if (!fileInfos) { return null; } const entities = new Array(); for (let i = 0; i < fileInfos.length; i++) { if (fileInfos[i].extension) { entities.push(createFile(fileInfos[i])); } else { entities.push(createFolder(fileInfos[i])); } } return entities; } eachEntity(onEntity) { if (!onEntity) { return; } const onSuccess = function (fileInfo) { let entity; if (fileInfo.extension) { entity = createFile(fileInfo); } else { entity = createFolder(fileInfo); } return onEntity(entity); }; const onError = function (error) { throw error; }; getFileAccess().eachEntity(this.path, onSuccess, onError); } } export var knownFolders; (function (knownFolders) { let _documents; let _externalDocuments; let _temp; let _app; function documents() { if (!_documents) { const path = getFileAccess().getDocumentsFolderPath(); _documents = new Folder(); _documents._path = path; _documents._isKnown = true; } return _documents; } knownFolders.documents = documents; function externalDocuments() { if (!_externalDocuments) { const path = getFileAccess().getExternalDocumentsFolderPath(); _externalDocuments = new Folder(); _externalDocuments._path = path; _externalDocuments._isKnown = true; } return _externalDocuments; } knownFolders.externalDocuments = externalDocuments; function temp() { if (!_temp) { const path = getFileAccess().getTempFolderPath(); _temp = new Folder(); _temp._path = path; _temp._isKnown = true; } return _temp; } knownFolders.temp = temp; function currentApp() { if (!_app) { const path = getFileAccess().getCurrentAppPath(); _app = new Folder(); _app._path = path; _app._isKnown = true; } return _app; } knownFolders.currentApp = currentApp; let ios; (function (ios) { function _checkPlatform(knownFolderName) { if (!__APPLE__) { throw new Error(`The "${knownFolderName}" known folder is available on iOS only!`); } } let _library; function library() { _checkPlatform('library'); if (!_library) { const existingFolderInfo = getExistingFolderInfo(5 /* NSSearchPathDirectory.LibraryDirectory */); if (existingFolderInfo) { _library = existingFolderInfo.folder; _library._path = existingFolderInfo.path; _library._isKnown = true; } } return _library; } ios.library = library; let _developer; function developer() { _checkPlatform('developer'); if (!_developer) { const existingFolderInfo = getExistingFolderInfo(6 /* NSSearchPathDirectory.DeveloperDirectory */); if (existingFolderInfo) { _developer = existingFolderInfo.folder; _developer._path = existingFolderInfo.path; _developer._isKnown = true; } } return _developer; } ios.developer = developer; let _desktop; function desktop() { _checkPlatform('desktop'); if (!_desktop) { const existingFolderInfo = getExistingFolderInfo(12 /* NSSearchPathDirectory.DesktopDirectory */); if (existingFolderInfo) { _desktop = existingFolderInfo.folder; _desktop._path = existingFolderInfo.path; _desktop._isKnown = true; } } return _desktop; } ios.desktop = desktop; let _downloads; function downloads() { _checkPlatform('downloads'); if (!_downloads) { const existingFolderInfo = getExistingFolderInfo(15 /* NSSearchPathDirectory.DownloadsDirectory */); if (existingFolderInfo) { _downloads = existingFolderInfo.folder; _downloads._path = existingFolderInfo.path; _downloads._isKnown = true; } } return _downloads; } ios.downloads = downloads; let _movies; function movies() { _checkPlatform('movies'); if (!_movies) { const existingFolderInfo = getExistingFolderInfo(17 /* NSSearchPathDirectory.MoviesDirectory */); if (existingFolderInfo) { _movies = existingFolderInfo.folder; _movies._path = existingFolderInfo.path; _movies._isKnown = true; } } return _movies; } ios.movies = movies; let _music; function music() { _checkPlatform('music'); if (!_music) { const existingFolderInfo = getExistingFolderInfo(18 /* NSSearchPathDirectory.MusicDirectory */); if (existingFolderInfo) { _music = existingFolderInfo.folder; _music._path = existingFolderInfo.path; _music._isKnown = true; } } return _music; } ios.music = music; let _pictures; function pictures() { _checkPlatform('pictures'); if (!_pictures) { const existingFolderInfo = getExistingFolderInfo(19 /* NSSearchPathDirectory.PicturesDirectory */); if (existingFolderInfo) { _pictures = existingFolderInfo.folder; _pictures._path = existingFolderInfo.path; _pictures._isKnown = true; } } return _pictures; } ios.pictures = pictures; let _sharedPublic; function sharedPublic() { _checkPlatform('sharedPublic'); if (!_sharedPublic) { const existingFolderInfo = getExistingFolderInfo(21 /* NSSearchPathDirectory.SharedPublicDirectory */); if (existingFolderInfo) { _sharedPublic = existingFolderInfo.folder; _sharedPublic._path = existingFolderInfo.path; _sharedPublic._isKnown = true; } } return _sharedPublic; } ios.sharedPublic = sharedPublic; function getExistingFolderInfo(pathDirectory /* NSSearchPathDirectory */) { const fileAccess = getFileAccess(); const folderPath = fileAccess.getKnownPath(pathDirectory); const folderInfo = fileAccess.getExistingFolder(folderPath); if (folderInfo) { return { folder: createFolder(folderInfo), path: folderPath, }; } return undefined; } })(ios = knownFolders.ios || (knownFolders.ios = {})); })(knownFolders || (knownFolders = {})); export var path; (function (path_1) { function normalize(path) { return getFileAccess().normalizePath(path); } path_1.normalize = normalize; function join(...paths) { const fileAccess = getFileAccess(); return fileAccess.joinPaths(paths); } path_1.join = join; path_1.separator = getFileAccess().getPathSeparator(); })(path || (path = {})); //# sourceMappingURL=index.js.map