@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
JavaScript
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