diff --git a/application/application-common.ts b/application/application-common.ts index 44aa07c6d..117c305f4 100644 --- a/application/application-common.ts +++ b/application/application-common.ts @@ -1,7 +1,6 @@ require("globals"); import definition = require("application"); import fs = require("file-system"); -import fileSystemAccess = require("file-system/file-system-access"); import styleScope = require("ui/styling/style-scope"); import observable = require("data/observable"); @@ -41,8 +40,8 @@ export function loadCss() { var cssFileName = fs.path.join(fs.knownFolders.currentApp().path, definition.cssFile); var applicationCss; if (fs.File.exists(cssFileName)) { - new fileSystemAccess.FileSystemAccess().readText(cssFileName, r => { applicationCss = r; }); - definition.cssSelectorsCache = styleScope.StyleScope.createSelectorsFromCss(applicationCss, cssFileName); + var file = fs.File.fromPath(cssFileName); + definition.cssSelectorsCache = styleScope.StyleScope.createSelectorsFromCss(file.readTextSync(), cssFileName); } } } \ No newline at end of file diff --git a/apps/tests/file-system-access-tests/file-system-access-tests.ts b/apps/tests/file-system-access-tests/file-system-access-tests.ts index 94a300171..3ef17f117 100644 --- a/apps/tests/file-system-access-tests/file-system-access-tests.ts +++ b/apps/tests/file-system-access-tests/file-system-access-tests.ts @@ -1,14 +1,25 @@ import TKUnit = require("../TKUnit"); import fs = require("file-system"); -import fileSystemAccess = require("file-system/file-system-access"); -var fileAccess = new fileSystemAccess.FileSystemAccess(); export var test_UTF8_BOM_is_not_returned = function () { var actualResult: string; - fileAccess.readText(fs.path.join(__dirname, "xml.expected"), (result) => { actualResult = result; }, (error) => { TKUnit.assert(false, "Could not read file utf8.txt"); }); + var path = fs.path.join(__dirname, "xml.expected"); + if (!fs.File.exists(path)) { + TKUnit.assert(false, "Could not read file utf8.txt"); + return; + } - var actualCharCode = actualResult.charCodeAt(0); - var expectedCharCode = "{".charCodeAt(0); - TKUnit.assert(actualCharCode === expectedCharCode, "Actual character code: " + actualCharCode + "; Expected character code: " + expectedCharCode); + var file = fs.File.fromPath(path); + + var onError = function (error) { + TKUnit.assert(false, "Could not read file utf8.txt"); + } + + var text = file.readTextSync(onError); + if (text) { + var actualCharCode = text.charCodeAt(0); + var expectedCharCode = "{".charCodeAt(0); + TKUnit.assert(actualCharCode === expectedCharCode, "Actual character code: " + actualCharCode + "; Expected character code: " + expectedCharCode); + } }; \ No newline at end of file diff --git a/apps/tests/xml-declaration/xml-declaration-tests.ts b/apps/tests/xml-declaration/xml-declaration-tests.ts index 8a030799c..c0741bd35 100644 --- a/apps/tests/xml-declaration/xml-declaration-tests.ts +++ b/apps/tests/xml-declaration/xml-declaration-tests.ts @@ -9,7 +9,6 @@ import gridLayoutModule = require("ui/layouts/grid-layout"); import absoluteLayoutModule = require("ui/layouts/absolute-layout"); import types = require("utils/types"); import fs = require("file-system"); -import fileSystemAccess = require("file-system/file-system-access"); import observable = require("data/observable"); import stackLayoutModule = require("ui/layouts/stack-layout"); import labelModule = require("ui/label"); @@ -129,24 +128,15 @@ export function test_loadWithOptionsFromTNSPath() { }; export function test_parse_ShouldNotCrashWithoutExports() { - var fileAccess = new fileSystemAccess.FileSystemAccess(); - - var v: view.View; - fileAccess.readText(fs.path.join(__dirname, "mainPage.xml"), r => { - v = builder.parse(r); - }); + var file = fs.File.fromPath(fs.path.join(__dirname, "mainPage.xml")); + var text = file.readTextSync(); + var v: view.View = builder.parse(text); TKUnit.assert(v instanceof view.View, "Expected result: View; Actual result: " + v + ";"); }; export function test_parse_ShouldNotCrashWithInvalidXml() { - var fileAccess = new fileSystemAccess.FileSystemAccess(); - - var v: view.View; - fileAccess.readText(" { - v = builder.parse(r); - }); - + var v: view.View = builder.parse(" { xmlString = result; }); + var file = fs.File.fromPath(fs.path.join(__dirname, "xml.xml")); + var xmlString = file.readTextSync(); xmlString = xmlString.replace(/(\r\n|\n|\r)/gm, "\n"); - xmlParser.parse(xmlString); var expectedResult: string; - fileAccess.readText(fs.path.join(__dirname, "xml.expected"), (result) => { expectedResult = result; }); + file = fs.File.fromPath(fs.path.join(__dirname, "xml.expected")); + expectedResult = file.readTextSync(); var i; var maxLength = Math.max(actualResult.length, expectedResult.length); @@ -186,8 +184,7 @@ export var test_XmlParser_NamespacesTest = function () { }, undefined, true); - var xmlString; - fileAccess.readText(fs.path.join(__dirname, "xml-with-namespaces.xml"), (result) => { xmlString = result; }); - + var file = fs.File.fromPath(fs.path.join(__dirname, "xml-with-namespaces.xml")); + var xmlString = file.readTextSync(); xmlParser.parse(xmlString); }; \ No newline at end of file diff --git a/apps/web-view-demo/model.ts b/apps/web-view-demo/model.ts index 996d09a70..2e9a40e2b 100644 --- a/apps/web-view-demo/model.ts +++ b/apps/web-view-demo/model.ts @@ -1,13 +1,11 @@ import observable = require("data/observable"); import fs = require("file-system"); -import fileSystemAccess = require("file-system/file-system-access"); - -var fileAccess = new fileSystemAccess.FileSystemAccess(); export class WebViewModel extends observable.Observable { constructor() { super(); - fileAccess.readText(fs.path.join(__dirname, "style.css"), (result) => { this._css = result; }); + var file = fs.File.fromPath(fs.path.join(__dirname, "style.css")); + this._css = file.readTextSync(); } private _url: string; @@ -19,19 +17,6 @@ export class WebViewModel extends observable.Observable { this.notify({ object: this, eventName: observable.Observable.propertyChangeEvent, propertyName: "url", value: value }); } - //private _text: string; - //get text(): string { - // return this._text; - //} - //set text(value: string) { - // this._text = value; - // this.notify({ object: this, eventName: observable.Observable.propertyChangeEvent, propertyName: "text", value: value }); - - // if (application.ios) { - // this.url = this.text; - // } - //} - private _css: string; get css(): string { return this._css; diff --git a/file-system/file-system-access.android.ts b/file-system/file-system-access.android.ts index b0dbd8c12..e06ac1175 100644 --- a/file-system/file-system-access.android.ts +++ b/file-system/file-system-access.android.ts @@ -48,11 +48,7 @@ export class FileSystemAccess { this.enumEntities(path, onEntity, onError); } - public getEntities(path: string, onSuccess: (files: Array<{ path: string; name: string; extension: string }>) => any, onError?: (error: any) => any) { - if (!onSuccess) { - return; - } - + public getEntities(path: string, onError?: (error: any) => any): Array<{ path: string; name: string; extension: string }> { var fileInfos = new Array<{ path: string; name: string; extension: string }>(); var onEntity = function (entity: { path: string; name: string; extension: string }): boolean { fileInfos.push(entity); @@ -71,8 +67,10 @@ export class FileSystemAccess { this.enumEntities(path, onEntity, localError); if (!errorOccurred) { - onSuccess(fileInfos); + return fileInfos; } + + return null; } public fileExists(path: string): boolean { @@ -89,7 +87,7 @@ export class FileSystemAccess { return exists && dir; } - public deleteFile(path: string, onSuccess?: () => any, onError?: (error: any) => any) { + public deleteFile(path: string, onError?: (error: any) => any) { try { var javaFile = new java.io.File(path); if (!javaFile.isFile()) { @@ -104,8 +102,6 @@ export class FileSystemAccess { if (onError) { onError({ message: "File deletion failed" }); } - } else if (onSuccess) { - onSuccess(); } } catch (exception) { if (onError) { @@ -114,7 +110,7 @@ export class FileSystemAccess { } } - public deleteFolder(path: string, isKnown?: boolean, onSuccess?: () => any, onError?: (error: any) => any) { + public deleteFolder(path: string, onError?: (error: any) => any) { try { var javaFile = new java.io.File(path); if (!javaFile.getCanonicalFile().isDirectory()) { @@ -125,27 +121,14 @@ export class FileSystemAccess { return; } - if (isKnown) { - if (onError) { - onError({ message: "Cannot delete known folder." }); - } - - return; - } - // TODO: Asynchronous this.deleteFolderContent(javaFile); - if (javaFile.delete()) { - if (onSuccess) { - onSuccess(); - } - } else { + if (!javaFile.delete()) { if (onError) { onError({ message: "Folder deletion failed." }); } } - } catch (exception) { if (onError) { onError(exception); @@ -153,7 +136,7 @@ export class FileSystemAccess { } } - public emptyFolder(path: string, onSuccess?: () => any, onError?: (error: any) => any) { + public emptyFolder(path: string, onError?: (error: any) => any) { try { var javaFile = new java.io.File(path); if (!javaFile.getCanonicalFile().isDirectory()) { @@ -166,11 +149,6 @@ export class FileSystemAccess { // TODO: Asynchronous this.deleteFolderContent(javaFile); - - if (onSuccess) { - onSuccess(); - } - } catch (exception) { if (onError) { onError(exception); @@ -178,7 +156,7 @@ export class FileSystemAccess { } } - public rename(path: string, newPath: string, onSuccess?: () => any, onError?: (error: any) => any) { + public rename(path: string, newPath: string, onError?: (error: any) => any) { var javaFile = new java.io.File(path); if (!javaFile.exists()) { if (onError) { @@ -201,12 +179,6 @@ export class FileSystemAccess { if (onError) { onError(new Error("Failed to rename file '" + path + "' to '" + newPath + "'")); } - - return; - } - - if (onSuccess) { - onSuccess(); } } @@ -220,7 +192,7 @@ export class FileSystemAccess { return dir.getAbsolutePath(); } - public readText(path: string, onSuccess: (content: string) => any, onError?: (error: any) => any, encoding?: any) { + public readText(path: string, onError?: (error: any) => any, encoding?: any) { try { var javaFile = new java.io.File(path); var stream = new java.io.FileInputStream(javaFile); @@ -258,9 +230,7 @@ export class FileSystemAccess { bufferedReader.close(); - if (onSuccess) { - onSuccess(result); - } + return result; } catch (exception) { if (onError) { onError(exception); @@ -277,7 +247,7 @@ export class FileSystemAccess { return s; } - public writeText(path: string, content: string, onSuccess?: () => any, onError?: (error: any) => any, encoding?: any) { + public writeText(path: string, content: string, onError?: (error: any) => any, encoding?: any) { try { var javaFile = new java.io.File(path); var stream = new java.io.FileOutputStream(javaFile); @@ -290,10 +260,6 @@ export class FileSystemAccess { writer.write(content); writer.close(); - - if (onSuccess) { - onSuccess(); - } } catch (exception) { if (onError) { onError(exception); diff --git a/file-system/file-system-access.d.ts b/file-system/file-system-access.d.ts index 58cfff79f..aa0ddfec4 100644 --- a/file-system/file-system-access.d.ts +++ b/file-system/file-system-access.d.ts @@ -38,15 +38,15 @@ * @param onSuccess A callback function to call if operation is successful * @param onError (optional) A callback function to use if any error occurs. */ - getEntities(path: string, onSuccess: (files: Array<{ path: string; name: string; extension: string }>) => any, onError?: (error: any) => any); + getEntities(path: string, onError?: (error: any) => any): Array<{ path: string; name: string; extension: string }>; /** * Performs an action onSuccess for every entity in a folder with a given path. * Breaks the loop if onSuccess function returns false - * @param onSuccess A callback function which is called for each entity. + * @param onEntity A callback function which is called for each entity. * @param onError (optional) A callback function to use if any error occurs. */ - eachEntity(path: string, onSuccess: (entity: { path: string; name: string; extension: string }) => boolean, onError?: (error: any) => any); + eachEntity(path: string, onEntity: (entity: { path: string; name: string; extension: string }) => boolean, onError?: (error: any) => any); /** * Checks if a file with a given path exist. @@ -61,35 +61,31 @@ /** * Deletes a file with a given path. * @param path Path of the file. - * @param onSuccess (optional) A callback function which will be executed if the deletion is successful. * @param onError (optional) A callback function to use if any error occurs. */ - deleteFile(path: string, onSuccess?: () => any, onError?: (error: any) => any); + deleteFile(path: string, onError?: (error: any) => any); /** * Deletes a folder with a given path. * @param path Path of the folder. - * @param onSuccess (optional) A callback function which will be executed if the deletion is successful. * @param onError (optional) A callback function to use if any error occurs. */ - deleteFolder(path: string, isKnown: boolean, onSuccess?: () => any, onError?: (error: any) => any); + deleteFolder(path: string, onError?: (error: any) => any); /** * Deletes a content of a folder with a given path. * @param path Path of the folder. - * @param onSuccess (optional) A callback function which will be executed if the deletion is successful. * @param onError (optional) A callback function to use if any error occurs. */ - emptyFolder(path: string, onSuccess?: () => any, onError?: (error: any) => any): void; + emptyFolder(path: string, onError?: (error: any) => any): void; /** * Rename a file or a folder with a given path. * @param path Current path of the entity which should be renamed. * @param newPath The new path which will be asigned of the entity. - * @param onSuccess (optional) A callback function which will be executed if the deletion is successful. * @param onError (optional) A callback function to use if any error occurs. */ - rename(path: string, newPath: string, onSuccess?: () => any, onError?: (error: any) => any): void; + rename(path: string, newPath: string, onError?: (error: any) => any): void; /** * Gets the special documents folder. @@ -110,7 +106,7 @@ * @param onError (optional) A callback function to use if any error occurs. * @param encoding (optional) If set reads the text with the specified encoding (default UTF-8). */ - readText(path: string, onSuccess: (content: string) => any, onError?: (error: any) => any, encoding?: any); + readText(path: string, onError?: (error: any) => any, encoding?: any): string; /** * Writes a text to a file with a given path. @@ -120,7 +116,7 @@ * @param onError (optional) A callback function to use if any error occurs. * @param encoding (optional) If set writes the text with the specified encoding (default UTF-8). */ - writeText(path: string, content: string, onSuccess?: () => any, onError?: (error: any) => any, encoding?: any); + writeText(path: string, content: string, onError?: (error: any) => any, encoding?: any); /** * Gets extension of the file with a given path. diff --git a/file-system/file-system-access.ios.ts b/file-system/file-system-access.ios.ts index 74cd9f257..34628bac1 100644 --- a/file-system/file-system-access.ios.ts +++ b/file-system/file-system-access.ios.ts @@ -120,12 +120,9 @@ export class FileSystemAccess { this.enumEntities(path, onEntity, onError); } - public getEntities(path: string, onSuccess: (files: Array<{ path: string; name: string; extension: string }>) => any, onError?: (error: any) => any) { - if (!onSuccess) { - return; - } - + public getEntities(path: string, onError?: (error: any) => any): Array<{ path: string; name: string; extension: string }> { var fileInfos = new Array<{ path: string; name: string; extension: string }>(); + var onEntity = function (entity: { path: string; name: string; extension: string }): boolean { fileInfos.push(entity); return true; @@ -143,8 +140,10 @@ export class FileSystemAccess { this.enumEntities(path, onEntity, localError); if (!errorOccurred) { - onSuccess(fileInfos); + return fileInfos; } + + return null; } public fileExists(path: string): boolean { @@ -169,49 +168,38 @@ export class FileSystemAccess { return nsString.toString(); } - public deleteFile(path: string, onSuccess?: () => any, onError?: (error: any) => any) { - this.deleteEntity(path, onSuccess, onError); + public deleteFile(path: string, onError?: (error: any) => any) { + this.deleteEntity(path, onError); } - public deleteFolder(path: string, isKnown?: boolean, onSuccess?: () => any, onError?: (error: any) => any) { - if (isKnown) { - if (onError) { - onError({ message: "Cannot delete known folder." }); - } + public deleteFolder(path: string, onError?: (error: any) => any) { + this.deleteEntity(path, onError); + } + public emptyFolder(path: string, onError?: (error: any) => any) { + var fileManager = NSFileManager.defaultManager(); + var entities = this.getEntities(path, onError); + + if (!entities) { return; } - this.deleteEntity(path, onSuccess, onError); - } - - public emptyFolder(path: string, onSuccess?: () => any, onError?: (error: any) => any) { - var fileManager = NSFileManager.defaultManager(); - - var filesEnum = function (files: Array<{ path: string; name: string; extension: string }>) { - var i; - for (i = 0; i < files.length; i++) { - try { - fileManager.removeItemAtPathError(files[i].path); - } - catch (ex) { - if (onError) { - onError(new Error("Failed to empty folder '" + path + "': " + ex)); - } - - return; - } + var i; + for (i = 0; i < entities.length; i++) { + try { + fileManager.removeItemAtPathError(entities[i].path); } + catch (ex) { + if (onError) { + onError(new Error("Failed to empty folder '" + path + "': " + ex)); + } - if (onSuccess) { - onSuccess(); + return; } } - - this.getEntities(path, filesEnum, onError); } - public rename(path: string, newPath: string, onSuccess?: () => any, onError?: (error: any) => any) { + public rename(path: string, newPath: string, onError?: (error: any) => any) { var fileManager = NSFileManager.defaultManager(); try { @@ -221,12 +209,6 @@ export class FileSystemAccess { if (onError) { onError(new Error("Failed to rename '" + path + "' to '" + newPath + "': " + ex)); } - - return; - } - - if (onSuccess) { - onSuccess(); } } @@ -238,7 +220,7 @@ export class FileSystemAccess { return this.getKnownPath(this.cachesDir); } - public readText(path: string, onSuccess: (content: string) => any, onError?: (error: any) => any, encoding?: any) { + public readText(path: string, onError?: (error: any) => any, encoding?: any) { var actualEncoding = encoding; if (!actualEncoding) { actualEncoding = textModule.encoding.UTF_8; @@ -246,21 +228,16 @@ export class FileSystemAccess { try { var nsString = NSString.stringWithContentsOfFileEncodingError(path, actualEncoding); + return nsString.toString(); } catch (ex) { if (onError) { onError(new Error("Failed to read file at path '" + path + "': " + ex)); } - - return; - } - - if (onSuccess) { - onSuccess(nsString.toString()); } } - public writeText(path: string, content: string, onSuccess?: () => any, onError?: (error: any) => any, encoding?: any) { + public writeText(path: string, content: string, onError?: (error: any) => any, encoding?: any) { var nsString = NSString.alloc().initWithString(content); var actualEncoding = encoding; @@ -276,12 +253,6 @@ export class FileSystemAccess { if (onError) { onError(new Error("Failed to write to file '" + path + "': " + ex)); } - - return; - } - - if (onSuccess) { - onSuccess(); } } @@ -313,7 +284,7 @@ export class FileSystemAccess { return ""; } - private deleteEntity(path: string, onSuccess?: () => any, onError?: (error: any) => any) { + private deleteEntity(path: string, onError?: (error: any) => any) { var fileManager = NSFileManager.defaultManager(); try { fileManager.removeItemAtPathError(path); @@ -323,10 +294,6 @@ export class FileSystemAccess { onError(new Error("Failed to delete file at path '" + path + "': " + ex)); } } - - if (onSuccess) { - onSuccess(); - } } private enumEntities(path: string, callback: (entity: { path: string; name: string; extension: string }) => boolean, onError?: (error) => any) { diff --git a/file-system/file-system.d.ts b/file-system/file-system.d.ts index 8f5c6768f..579cecd69 100644 --- a/file-system/file-system.d.ts +++ b/file-system/file-system.d.ts @@ -7,134 +7,172 @@ declare module "file-system" { * Represents a single entity on the file system. */ export class FileSystemEntity { - /** - * Gets the Date object specifying the last time this entity was modified. - */ + /** + * Gets the Date object specifying the last time this entity was modified. + */ lastModified: Date; - /** - * Gets the name of the entity. - */ + /** + * Gets the name of the entity. + */ name: string; - /** - * Gets the fully-qualified path (including the extension for a File) of the entity. - */ + /** + * Gets the fully-qualified path (including the extension for a File) of the entity. + */ path: string; - /** - * Gets the Folder object representing the parent of this entity. - * Will be null for a root folder like Documents or Temporary. - * This property is readonly. - */ + /** + * Gets the Folder object representing the parent of this entity. + * Will be null for a root folder like Documents or Temporary. + * This property is readonly. + */ parent: Folder; - /** - * Removes (deletes) the current Entity from the file system. - */ + /** + * Removes (deletes) the current Entity from the file system. + */ remove(): Promise; - /** - * Renames the current entity using the specified name. - * @param newName The new name to be applied to the entity. - */ + /** + * Removes (deletes) the current Entity from the file system synchronously. + */ + removeSync(onError?: (error: any) => any): void; + + /** + * Renames the current entity using the specified name. + * @param newName The new name to be applied to the entity. + */ rename(newName: string): Promise; + + /** + * Renames the current entity synchronously, using the specified name. + * @param newName The new name to be applied to the entity. + */ + renameSync(newName: string, onError?: (error: any) => any): void; } /** * Represents a File entity on the file system. */ export class File extends FileSystemEntity { - /** - * Checks whether a File with the specified path already exists. - * @param path The path to check for. - */ + /** + * Checks whether a File with the specified path already exists. + * @param path The path to check for. + */ static exists(path: string): boolean; - /** - * Gets the extension of the file. - */ + /** + * Gets the extension of the file. + */ extension: string; - /** - * Gets a value indicating whether the file is currently locked, meaning a background operation associated with this file is running. - */ + /** + * Gets a value indicating whether the file is currently locked, meaning a background operation associated with this file is running. + */ isLocked: boolean; - /** - * Gets or creates a File entity at the specified path. - * @param path The path to get/create the file at. - */ + /** + * Gets or creates a File entity at the specified path. + * @param path The path to get/create the file at. + */ static fromPath(path: string): File; - /** - * Reads the content of the file as a string using the specified encoding (defaults to UTF-8). - * @param encoding An optional value specifying the preferred encoding (defaults to UTF-8). - */ + /** + * Reads the content of the file as a string using the specified encoding (defaults to UTF-8). + * @param encoding An optional value specifying the preferred encoding (defaults to UTF-8). + */ readText(encoding?: string): Promise; - /** - * Writes the provided string to the file, using the specified encoding (defaults to UTF-8). - * @param content The content to be saved to the file. - * @param encoding An optional value specifying the preferred encoding (defaults to UTF-8). - */ + /** + * Reads the content of the file as a string synchronously, using the specified encoding (defaults to UTF-8). + * @param onError An optional function to be called if some IO-error occurs. + * @param encoding An optional value specifying the preferred encoding (defaults to UTF-8). + */ + readTextSync(onError?: (error: any) => any, encoding?: string): string; + + /** + * Writes the provided string to the file, using the specified encoding (defaults to UTF-8). + * @param content The content to be saved to the file. + * @param encoding An optional value specifying the preferred encoding (defaults to UTF-8). + */ writeText(content: string, encoding?: string): Promise; + + /** + * Writes the provided string to the file synchronously, using the specified encoding (defaults to UTF-8). + * @param content The content to be saved to the file. + * @param onError An optional function to be called if some IO-error occurs. + * @param encoding An optional value specifying the preferred encoding (defaults to UTF-8). + */ + writeTextSync(content: string, onError?: (error: any) => any, encoding?: string): void; } - /** - * Represents a Folder (directory) entity on the file system. - */ + /** + * Represents a Folder (directory) entity on the file system. + */ export class Folder extends FileSystemEntity { - /** - * Determines whether this instance is a KnownFolder (accessed through the KnownFolders object). - */ + /** + * Determines whether this instance is a KnownFolder (accessed through the KnownFolders object). + */ isKnown: boolean; - /** - * Gets or creates a Folder entity at the specified path. - * @param path The path to get/create the folder at. - */ + /** + * Gets or creates a Folder entity at the specified path. + * @param path The path to get/create the folder at. + */ static fromPath(path: string): Folder; - /** - * Checks whether a Folder with the specified path already exists. - * @param path The path to check for. - */ + /** + * Checks whether a Folder with the specified path already exists. + * @param path The path to check for. + */ static exists(path: string): boolean; - /** - * Checks whether this Folder contains an Entity with the specified name. - * The path of the folder is added to the name to resolve the complete path to check for. - * @param name The name of the entity to check for. - */ + /** + * Checks whether this Folder contains an Entity with the specified name. + * The path of the folder is added to the name to resolve the complete path to check for. + * @param name The name of the entity to check for. + */ contains(name: string): boolean; - /** - * Deletes all the files and folders (recursively), contained within this Folder. - */ + /** + * Deletes all the files and folders (recursively), contained within this Folder. + */ clear(): Promise; - /** - * Gets or creates a File entity with the specified name within this Folder. - * @param name The name of the file to get/create. - */ + /** + * Deletes all the files and folders (recursively), contained within this Folder synchronously. + * @param onError An optional function to be called if some error occurs. + */ + clearSync(onError?: (error: any) => void): void; + + /** + * Gets or creates a File entity with the specified name within this Folder. + * @param name The name of the file to get/create. + */ getFile(name: string): File; - /** - * Gets or creates a Folder entity with the specified name within this Folder. - * @param name The name of the folder to get/create. - */ + /** + * Gets or creates a Folder entity with the specified name within this Folder. + * @param name The name of the folder to get/create. + */ getFolder(name: string): Folder; - /** - * Gets all the top-level entities residing within this folder. - */ + /** + * Gets all the top-level entities residing within this folder. + */ getEntities(): Promise>; - /** - * Enumerates all the top-level FileSystem entities residing within this folder. - * @param onEntity A callback that receives the current entity. If the callback returns false this will mean for the iteration to stop. - */ + /** + * Gets all the top-level entities residing within this folder synchronously. + * @param onError An optional function to be called if some error occurs. + */ + getEntitiesSync(onError?: (error: any) => any): Promise>; + + /** + * Enumerates all the top-level FileSystem entities residing within this folder. + * @param onEntity A callback that receives the current entity. If the callback returns false this will mean for the iteration to stop. + */ eachEntity(onEntity: (entity: FileSystemEntity) => boolean); } diff --git a/file-system/file-system.ts b/file-system/file-system.ts index 99f2826bf..95197fa93 100644 --- a/file-system/file-system.ts +++ b/file-system/file-system.ts @@ -63,60 +63,91 @@ export class FileSystemEntity { public remove(): Promise { return new Promise((resolve, reject) => { - var fileAccess = getFileAccess(); - - var localSucces = function () { - resolve(); - }; - + var hasError = false; var localError = function (error: any) { + hasError = true; reject(error); }; - if (this instanceof File) { - fileAccess.deleteFile(this.path, localSucces, localError); - } else if (this instanceof Folder) { - fileAccess.deleteFolder(this.path, this[isKnownProperty], localSucces, localError); + this.removeSync(localError); + if (!hasError) { + resolve(); } }); } + public removeSync(onError?: (error: any) => any): void { + if (this[isKnownProperty]) { + if (onError) { + onError({ message: "Cannot delete known folder." }); + } + + return; + } + + var fileAccess = getFileAccess(); + + if (this instanceof File) { + fileAccess.deleteFile(this.path, onError); + } else if (this instanceof Folder) { + fileAccess.deleteFolder(this.path, onError); + } + } + public rename(newName: string): Promise { return new Promise((resolve, reject) => { - if (this instanceof Folder) { - if (this[isKnownProperty]) { - reject(new Error("Cannot rename known folder.")); - } - } - - var parentFolder = this.parent; - if (!parentFolder) { - reject(new Error("No parent folder.")); - } - - var fileAccess = getFileAccess(); - var path = parentFolder.path; - var newPath = fileAccess.joinPath(path, newName); - - var localSucceess = () => { - this[pathProperty] = newPath; - this[nameProperty] = newName; - - if (this instanceof File) { - this[extensionProperty] = fileAccess.getFileExtension(newPath); - } - - resolve(); - } - + var hasError = false; var localError = function (error) { + hasError = true; reject(error); } - fileAccess.rename(this.path, newPath, localSucceess, localError); + this.renameSync(newName, localError); + + if (!hasError) { + resolve(); + } }); } + public renameSync(newName: string, onError?: (error: any) => any): void { + if (this[isKnownProperty]) { + if (onError) { + onError(new Error("Cannot rename known folder.")); + } + return; + } + + var parentFolder = this.parent; + if (!parentFolder) { + if (onError) { + onError(new Error("No parent folder.")); + } + return; + } + + var fileAccess = getFileAccess(); + var path = parentFolder.path; + var newPath = fileAccess.joinPath(path, newName); + + var hasError = false; + var localError = function (error) { + hasError = true; + if (onError) { + onError(error); + } + return null; + } + + fileAccess.rename(this.path, newPath, localError); + this[pathProperty] = newPath; + this[nameProperty] = newName; + + if (this instanceof File) { + this[extensionProperty] = fileAccess.getFileExtension(newPath); + } + } + get name(): string { return this[nameProperty]; } @@ -136,7 +167,6 @@ export class FileSystemEntity { } export class File extends FileSystemEntity { - public static fromPath(path: string) { var onError = function (error) { throw error; @@ -164,50 +194,71 @@ export class File extends FileSystemEntity { } public readText(encoding?: string): Promise { - this.checkAccess(); - return new Promise((resolve, reject) => { - this[fileLockedProperty] = true; - - var localSuccess = (content: string) => { - this[fileLockedProperty] = false; - resolve(content); - }; - + var hasError = false; var localError = (error) => { - this[fileLockedProperty] = false; + hasError = true; reject(error); }; - // TODO: Asyncronous - getFileAccess().readText(this.path, localSuccess, localError, encoding); - + var content = this.readTextSync(localError, encoding); + if (!hasError) { + resolve(content); + } }); } - public writeText(content: string, encoding?: string): Promise { + public readTextSync(onError?: (error: any) => any, encoding?: string): string { this.checkAccess(); + this[fileLockedProperty] = true; + + var that = this; + var localError = (error) => { + that[fileLockedProperty] = false; + if (onError) { + onError(error); + } + }; + + var content = getFileAccess().readText(this.path, localError, encoding); + this[fileLockedProperty] = false; + + return content; + } + + public writeText(content: string, encoding?: string): Promise { return new Promise((resolve, reject) => { - this[fileLockedProperty] = true; - - var that = this; - var localSuccess = function () { - that[fileLockedProperty] = false; - resolve(); - }; - + var hasError = false; var localError = function (error) { - that[fileLockedProperty] = false; + hasError = true; reject(error); }; - // TODO: Asyncronous - getFileAccess().writeText(this.path, content, localSuccess, localError, encoding); - + this.writeTextSync(content, localError, encoding); + if (!hasError) { + resolve(); + } }); } + public writeTextSync(content: string, onError?: (error: any) => any, encoding?: string): void { + this.checkAccess(); + + this[fileLockedProperty] = true; + + var that = this; + var localError = function (error) { + that[fileLockedProperty] = false; + if (onError) { + onError(error); + } + }; + + // TODO: Asyncronous + getFileAccess().writeText(this.path, content, localError, encoding); + } + private checkAccess() { if (this.isLocked) { throw new Error("Cannot access a locked file."); @@ -216,7 +267,6 @@ export class File extends FileSystemEntity { } export class Folder extends FileSystemEntity { - public static fromPath(path: string): Folder { var onError = function (error) { throw error; @@ -247,20 +297,23 @@ export class Folder extends FileSystemEntity { public clear(): Promise { return new Promise((resolve, reject) => { - - var onSuccess = function () { - resolve(); - }; - + var hasError = false; var onError = function (error) { + hasError = true; reject(error); }; - getFileAccess().emptyFolder(this.path, onSuccess, onError); - + this.clearSync(onError); + if (!hasError) { + resolve(); + } }); } + public clearSync(onError?: (error: any) => void): void { + getFileAccess().emptyFolder(this.path, onError); + } + get isKnown(): boolean { return this[isKnownProperty]; } @@ -299,31 +352,39 @@ export class Folder extends FileSystemEntity { public getEntities(): Promise> { return new Promise((resolve, reject) => { - - var onSuccess = function (fileInfos: Array<{ path: string; name: string; extension: string }>) { - var entities = new Array(); - var i; - - for (i = 0; i < fileInfos.length; i++) { - if (fileInfos[i].extension) { - entities.push(createFile(fileInfos[i])); - } else { - entities.push(createFolder(fileInfos[i])); - } - } - - resolve(entities); - } - - var onError = function (error) { - throw error; + var hasError = false; + var localError = function (error) { + hasError = true; + reject(error); }; - getFileAccess().getEntities(this.path, onSuccess, onError); - + var entities = this.getEntitiesSync(localError); + if (!hasError) { + resolve(entities); + } }); } + public getEntitiesSync(onError?: (error: any) => any): Array { + var fileInfos = getFileAccess().getEntities(this.path, onError); + if (!fileInfos) { + return null; + } + + var entities = new Array(); + + var i; + for (i = 0; i < fileInfos.length; i++) { + if (fileInfos[i].extension) { + entities.push(createFile(fileInfos[i])); + } else { + entities.push(createFolder(fileInfos[i])); + } + } + + return entities; + } + public eachEntity(onEntity: (entity: FileSystemEntity) => boolean) { if (!onEntity) { return; diff --git a/ui/builder/builder.ts b/ui/builder/builder.ts index 343f143f4..9327835c7 100644 --- a/ui/builder/builder.ts +++ b/ui/builder/builder.ts @@ -1,7 +1,6 @@ import view = require("ui/core/view"); import fs = require("file-system"); import xml = require("xml"); -import file_access_module = require("file-system/file-system-access"); import types = require("utils/types"); import componentBuilder = require("ui/builder/component-builder"); import templateBuilderDef = require("ui/builder/template-builder"); @@ -261,15 +260,12 @@ function loadInternal(fileName: string, context?: any): componentBuilder.Compone // Check if the XML file exists. if (fs.File.exists(fileName)) { - - var fileAccess = new file_access_module.FileSystemAccess(); - - // Read the XML file. - fileAccess.readText(fileName, result => { - componentModule = parseInternal(result, context); - }, (e) => { - throw new Error("Error loading file " + fileName + " :" + e.message); - }); + var file = fs.File.fromPath(fileName); + var onError = function (error) { + throw new Error("Error loading file " + fileName + " :" + error.message); + } + var text = file.readTextSync(onError); + componentModule = parseInternal(text, context); } if (componentModule && componentModule.component) { diff --git a/ui/page/page-common.ts b/ui/page/page-common.ts index 2aa969705..7c83b2fd7 100644 --- a/ui/page/page-common.ts +++ b/ui/page/page-common.ts @@ -5,7 +5,6 @@ import frame = require("ui/frame"); import styleModule = require("ui/styling/style"); import styleScope = require("ui/styling/style-scope"); import fs = require("file-system"); -import fileSystemAccess = require("file-system/file-system-access"); import frameCommon = require("ui/frame/frame-common"); import actionBar = require("ui/action-bar"); import dependencyObservable = require("ui/core/dependency-observable"); @@ -131,10 +130,12 @@ export class Page extends contentView.ContentView implements dts.Page { } if (!this._cssFiles[cssFileName]) { if (fs.File.exists(cssFileName)) { - new fileSystemAccess.FileSystemAccess().readText(cssFileName, r => { + var file = fs.File.fromPath(cssFileName); + var text = file.readTextSync(); + if (text) { this._addCssInternal(r, cssFileName); this._cssFiles[cssFileName] = true; - }); + } } } } diff --git a/ui/styling/style-scope.ts b/ui/styling/style-scope.ts index 99acf6f47..62cbdf198 100644 --- a/ui/styling/style-scope.ts +++ b/ui/styling/style-scope.ts @@ -7,9 +7,7 @@ import application = require("application"); import utils = require("utils/utils"); import types = require("utils/types"); import fs = require("file-system"); -import file_access_module = require("file-system/file-system-access"); -var fileAccess = new file_access_module.FileSystemAccess(); var pattern: RegExp = /url\(('|")(.*?)\1\)/; export class StyleScope { @@ -89,9 +87,13 @@ export class StyleScope { fileName = fs.path.join(fs.knownFolders.currentApp().path, fileName.replace("~/", "")); } - fileAccess.readText(fileName, result => { - selectors = StyleScope._joinCssSelectorsArrays([selectors, StyleScope.createSelectorsFromCss(result, fileName)]); - }); + if (fs.File.exists(fileName)) { + var file = fs.File.fromPath(fileName); + var text = file.readTextSync(); + if (text) { + selectors = StyleScope._joinCssSelectorsArrays([selectors, StyleScope.createSelectorsFromCss(text, fileName)]); + } + } } } }