From 39b505384a3c16d3cfc9c9804fcab1ed55593263 Mon Sep 17 00:00:00 2001 From: atanasovg Date: Wed, 12 Mar 2014 18:26:58 +0200 Subject: [PATCH] New BCL approach & BuildTasks --- .gitignore | 3 + Application/application.android.ts | 131 +++++++ Application/application.d.ts | 50 +++ Application/application.ios.ts | 91 +++++ Application/application_common.ts | 26 ++ BCL.csproj | 170 +++++++++ BCL.sln | 22 ++ Camera/camera.android.ts | 24 ++ Camera/camera.d.ts | 22 ++ Camera/camera.ios.ts | 15 + Database/Readme.md | 28 ++ Database/database.android.ts | 92 +++++ Database/database.d.ts | 16 + Database/database.ios.ts | 53 +++ Database/database_query_result.ts | 21 ++ FileSystem/file_system.d.ts | 138 ++++++++ FileSystem/file_system.ts | 364 ++++++++++++++++++++ FileSystem/file_system_access.android.ts | 305 ++++++++++++++++ FileSystem/file_system_access.d.ts | 28 ++ FileSystem/file_system_access.ios.ts | 82 +++++ Image/Readme.md | 5 + Image/image.android.ts | 68 ++++ Image/image.d.ts | 18 + Image/image.ios.ts | 59 ++++ Location/location.android.ts | 88 +++++ Location/location.d.ts | 66 ++++ Location/location.ios.ts | 44 +++ Location/location_types.ts | 46 +++ Readme.md | 5 + UserPreferences/Readme.md | 6 + UserPreferences/user_preferences.android.ts | 103 ++++++ UserPreferences/user_preferences.d.ts | 19 + UserPreferences/user_preferences.ios.ts | 114 ++++++ Utils/utils_android.ts | 29 ++ Utils/utils_ios.ts | 27 ++ WebClient/Readme.md | 25 ++ WebClient/web_client.android.ts | 48 +++ WebClient/web_client.d.ts | 15 + WebClient/web_client.ios.ts | 40 +++ declarations.android.d.ts | 331 ++++++++++++++++++ declarations.d.ts | 9 + declarations.ios.d.ts | 61 ++++ 42 files changed, 2907 insertions(+) create mode 100644 .gitignore create mode 100644 Application/application.android.ts create mode 100644 Application/application.d.ts create mode 100644 Application/application.ios.ts create mode 100644 Application/application_common.ts create mode 100644 BCL.csproj create mode 100644 BCL.sln create mode 100644 Camera/camera.android.ts create mode 100644 Camera/camera.d.ts create mode 100644 Camera/camera.ios.ts create mode 100644 Database/Readme.md create mode 100644 Database/database.android.ts create mode 100644 Database/database.d.ts create mode 100644 Database/database.ios.ts create mode 100644 Database/database_query_result.ts create mode 100644 FileSystem/file_system.d.ts create mode 100644 FileSystem/file_system.ts create mode 100644 FileSystem/file_system_access.android.ts create mode 100644 FileSystem/file_system_access.d.ts create mode 100644 FileSystem/file_system_access.ios.ts create mode 100644 Image/Readme.md create mode 100644 Image/image.android.ts create mode 100644 Image/image.d.ts create mode 100644 Image/image.ios.ts create mode 100644 Location/location.android.ts create mode 100644 Location/location.d.ts create mode 100644 Location/location.ios.ts create mode 100644 Location/location_types.ts create mode 100644 Readme.md create mode 100644 UserPreferences/Readme.md create mode 100644 UserPreferences/user_preferences.android.ts create mode 100644 UserPreferences/user_preferences.d.ts create mode 100644 UserPreferences/user_preferences.ios.ts create mode 100644 Utils/utils_android.ts create mode 100644 Utils/utils_ios.ts create mode 100644 WebClient/Readme.md create mode 100644 WebClient/web_client.android.ts create mode 100644 WebClient/web_client.d.ts create mode 100644 WebClient/web_client.ios.ts create mode 100644 declarations.android.d.ts create mode 100644 declarations.d.ts create mode 100644 declarations.ios.d.ts diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..f47e111db --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +# generated files +*.map +*.js diff --git a/Application/application.android.ts b/Application/application.android.ts new file mode 100644 index 000000000..55a071ea6 --- /dev/null +++ b/Application/application.android.ts @@ -0,0 +1,131 @@ +import app_common_module = require("Application/application_common"); +var currentApp = app_common_module.tk.ui.Application.current; + +export module tk { + // TODO: This is tricky, we have a module named android down in the hierarchy and we need to declare it here + var callbacks = android.app.Application.ActivityLifecycleCallbacks; + + export module ui { + export module android { + var initEvents = function () { + var androidApp = app_common_module.tk.ui.Application.current.android; + + var lifecycleCallbacks = new callbacks({ + onActivityCreated: function (activity: any, bundle: any) { + if (!androidApp.startActivity) { + androidApp.startActivity = activity; + + //if (UI.Application.current.onLaunch) { + // UI.Application.current.onLaunch(); + //} + + if (androidApp.onActivityCreated) { + androidApp.onActivityCreated(activity, bundle); + } + } + }, + onActivityDestroyed: function (activity: any) { + // Clear the current activity reference to prevent leak + if (activity === androidApp.currentActivity) { + androidApp.currentActivity = undefined; + } + + //if (activity === UI.Application.android.startActivity) { + // UI.Application.android.currentActivity = undefined; + // if (UI.Application.current.onExit) { + // UI.Application.current.onExit(); + // } + //} + + if (androidApp.onActivityDestroyed) { + androidApp.onActivityDestroyed(activity); + } + }, + onActivityPaused: function (activity: any) { + //if (UI.Application.android.currentActivity === activity) { + // if (UI.Application.current.onSuspend) { + // UI.Application.current.onSuspend(); + // } + //} + + if (androidApp.onActivityPaused) { + androidApp.onActivityPaused(activity); + } + }, + onActivityResumed: function (activity: any) { + //if (UI.Application.android.currentActivity === activity) { + // if (UI.Application.current.onResume) { + // UI.Application.current.onResume(); + // } + //} + + if (androidApp.onActivityResumed) { + androidApp.onActivityResumed(activity); + } + }, + onActivitySaveInstanceState: function (activity: any, bundle: any) { + if (androidApp.onSaveActivityState) { + androidApp.onSaveActivityState(activity, bundle); + } + }, + onActivityStarted: function (activity: any) { + androidApp.currentActivity = activity; + + //if (activity === UI.Application.android.startActivity) { + // if (UI.Application.current.onStart) { + // UI.Application.current.onStart(); + // } + //} + + if (androidApp.onActivityStarted) { + androidApp.onActivityStarted(activity); + } + }, + onActivityStopped: function (activity: any) { + if (androidApp.onActivityStopped) { + androidApp.onActivityStopped(activity); + } + } + }); + + return lifecycleCallbacks; + } + + export var initApp = function (nativeApp: any) { + var app = new Application(nativeApp); + currentApp.os = app_common_module.tk.TargetOS.Android; + currentApp.android = app; + app.init(); + } + + class Application { + public nativeApp: any; + public context: any; + public currentActivity: any; + public startActivity: any; + public packageName: string; + + // TODO: Provide type information once definitions are done - e.g. activity: android.widget.activity + public onActivityCreated: (activity: any, bundle: any) => any; + public onActivityDestroyed: (activity: any) => any; + public onActivityStarted: (activity: any) => any; + public onActivityPaused: (activity: any) => any; + public onActivityResumed: (activity: any) => any; + public onActivityStopped: (activity: any) => any; + public onSaveActivityState: (activity: any, bundle: any) => any; + + private _eventsToken: any; + + constructor(nativeApp: any) { + this.nativeApp = nativeApp; + this.packageName = nativeApp.getPackageName(); + } + + public init() { + this._eventsToken = initEvents(); + this.nativeApp.registerActivityLifecycleCallbacks(this._eventsToken); + } + } + } + } +} \ No newline at end of file diff --git a/Application/application.d.ts b/Application/application.d.ts new file mode 100644 index 000000000..7352f5a75 --- /dev/null +++ b/Application/application.d.ts @@ -0,0 +1,50 @@ +export declare module tk { + export enum TargetOS { + iOS, + Android, + //WP + } + + export module ui { + export class Application { + static current: Application; + public os: TargetOS; + + public onLaunch: () => any; + public onSuspend: () => any; + public onResume: () => any; + public onExit: () => any; + public onLowMemory: () => any; + + public android: android.Application; + public ios: ios.Application; + } + + export module android { + export function initApp(nativeApp: any); + export class Application { + public nativeApp: any; // TODO: android.app + public context: any; // TODO: android.context + public currentActivity: any; // TODO: android.activity + public startActivity: any; // TODO: android.activity + public packageName: string; + + // TODO: Provide type information once definitions are done - e.g. activity: android.widget.activity + public onActivityCreated: (activity: any, bundle: any) => any; + public onActivityDestroyed: (activity: any) => any; + public onActivityStarted: (activity: any) => any; + public onActivityPaused: (activity: any) => any; + public onActivityResumed: (activity: any) => any; + public onActivityStopped: (activity: any) => any; + public onSaveActivityState: (activity: any, bundle: any) => any; + } + } + + export module ios { + export function initApp(nativeApp: any); + export class Application { + public rootController: any; + } + } + } +} \ No newline at end of file diff --git a/Application/application.ios.ts b/Application/application.ios.ts new file mode 100644 index 000000000..14e7d8072 --- /dev/null +++ b/Application/application.ios.ts @@ -0,0 +1,91 @@ +import app_common_module = require("Application/application_common"); +var currentApp = app_common_module.tk.ui.Application.current; + +export module tk { + export module ui { + export module ios { + // TODO: Declarations + export var initApp = function (nativeApp: any) { + var app = new Application(nativeApp); + currentApp.os = app_common_module.tk.TargetOS.iOS; + currentApp.ios = app; + app.init(); + } + + class Application { + public nativeApp: any; + public rootController: any; + + constructor(nativeApp: any) { + this.nativeApp = nativeApp; + } + + public init() { + UIKit.UIResponder.extends({/*TODO: Empty parameter here, needs API improvement*/}, { + name: "KimeraAppDelegate", + }).extends({ + protocol: "UIApplicationDelegate", + implementation: { + applicationDidFinishLaunchingWithOptions: function () { + log("Application launched: applicationDidFinishLaunchingWithOptions."); + + this.window = new UIKit.UIWindow(UIKit.UIScreen.mainScreen().bounds()); + this.window.setBackgroundColor(UIKit.UIColor.whiteColor()); + + var iosApp = currentApp.ios; + this.window.setRootViewController(iosApp.rootController); + + if (currentApp.onLaunch) { + currentApp.onLaunch(); + } else { + log("Missing TK.UI.Application.current.onLaunch"); + } + + this.window.makeKeyAndVisible(); + + log("applicationDidFinishLaunchingWithOptions finished."); + return true; + }, + + applicationDidBecomeActive: function (application) { + log("applicationDidBecomeActive: " + application); + if (currentApp.onResume) { + currentApp.onResume(); + } + }, + + applicationWillResignActive: function (application) { + log("applicationWillResignActive: " + application); + }, + + applicationDidEnterBackground: function (application) { + log("applicationDidEnterBackground: " + application); + if (currentApp.onSuspend) { + currentApp.onSuspend(); + } + }, + + applicationWillEnterForeground: function (application) { + log("applicationWillEnterForeground: " + application); + }, + + applicationWillTerminate: function (application) { + log("applicationWillTerminate: " + application); + if (currentApp.onExit) { + currentApp.onExit(); + } + }, + + applicationDidReceiveMemoryWarning: function (application) { + log("applicationDidReceiveMemoryWarning: " + application); + if (currentApp.onLowMemory) { + currentApp.onLowMemory(); + } + } + } + }); + } + } + } + } +} \ No newline at end of file diff --git a/Application/application_common.ts b/Application/application_common.ts new file mode 100644 index 000000000..f404ed324 --- /dev/null +++ b/Application/application_common.ts @@ -0,0 +1,26 @@ +export module tk { + export enum TargetOS { + iOS, + Android, + //WP + } + + export module ui { + export class Application { + + public os: TargetOS; + + public onLaunch: () => any; + public onSuspend: () => any; + public onResume: () => any; + public onExit: () => any; + public onLowMemory: () => any; + + public static current: Application = new Application(); + + // TODO: These fields are declared by the application.d.ts file and intellisense will come from there + public android: any; + public ios: any; + } + } +} \ No newline at end of file diff --git a/BCL.csproj b/BCL.csproj new file mode 100644 index 000000000..fdb309b36 --- /dev/null +++ b/BCL.csproj @@ -0,0 +1,170 @@ + + + + Debug + {2313F1BF-1F2D-4F11-806A-87927FA6A7C0} + {349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} + Library + bin + v4.5 + full + true + 0.9 + true + + + + + + + 12.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + + + BCL + + + bin\ + + + bin\ + + + true + + + + + + + + True + True + 63708 + / + http://localhost:63708/ + False + False + + + False + + + + + + + application.d.ts + + + application.d.ts + + + + application.d.ts + + + database.d.ts + + + + database.d.ts + + + + declarations.d.ts + + + camera.d.ts + + + + camera.d.ts + + + database.d.ts + + + declarations.d.ts + + + + file_system.d.ts + + + file_system_access.d.ts + + + + file_system_access.d.ts + + + image.d.ts + + + image.d.ts + + + + location.d.ts + + + + location.d.ts + + + location.d.ts + + + user_preferences.d.ts + + + + user_preferences.d.ts + + + + + web_client.d.ts + + + web_client.d.ts + + + + + + + + + + + + + + + + + + + + commonjs + True + True + ES5 + + + commonjs + True + True + ES5 + + + True + + + + + + + \ No newline at end of file diff --git a/BCL.sln b/BCL.sln new file mode 100644 index 000000000..4467379ab --- /dev/null +++ b/BCL.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2013 +VisualStudioVersion = 12.0.30110.0 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BCL", "BCL.csproj", "{2313F1BF-1F2D-4F11-806A-87927FA6A7C0}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Android|Any CPU = Android|Any CPU + iOS|Any CPU = iOS|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2313F1BF-1F2D-4F11-806A-87927FA6A7C0}.Android|Any CPU.ActiveCfg = Android|Any CPU + {2313F1BF-1F2D-4F11-806A-87927FA6A7C0}.Android|Any CPU.Build.0 = Android|Any CPU + {2313F1BF-1F2D-4F11-806A-87927FA6A7C0}.iOS|Any CPU.ActiveCfg = iOS|Any CPU + {2313F1BF-1F2D-4F11-806A-87927FA6A7C0}.iOS|Any CPU.Build.0 = iOS|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/Camera/camera.android.ts b/Camera/camera.android.ts new file mode 100644 index 000000000..6d480f0fc --- /dev/null +++ b/Camera/camera.android.ts @@ -0,0 +1,24 @@ +export module tk { + export module io { + var REQUEST_IMAGE_CAPTURE: number = 1; + var REQUEST_SELECT_PICTURE: number = 2; + + export class CameraManager { + public takePicture(params: any, onSuccess: (imageData: any) => any, onError?: (error: any) => any) { + //var takePictureIntent = new android.content.Intent('android.media.action.IMAGE_CAPTURE'); + //if (takePictureIntent.resolveActivity(UI.Application.android.context.getPackageManager()) !== null) { + // UI.Application.android.currentActivity.startActivityForResult(takePictureIntent, REQUEST_IMAGE_CAPTURE); + //} + } + + // options { useSavedPhotos: true } + public pictureFromLibrary(params: any, onSuccess: (imageData: any) => any, onError?: (error: any) => any) { + //var readPictureIntent = new android.content.Intent(); + //readPictureIntent.setType('image/*'); + //readPictureIntent.setAction('android.intent.action.GET_CONTENT'); + //UI.Application.android.currentActivity.startActivityForResult(android.content.Intent.createChooser(readPictureIntent, + // 'Select Picture'), REQUEST_SELECT_PICTURE); + } + } + } +} \ No newline at end of file diff --git a/Camera/camera.d.ts b/Camera/camera.d.ts new file mode 100644 index 000000000..92e12ed8d --- /dev/null +++ b/Camera/camera.d.ts @@ -0,0 +1,22 @@ +export declare module tk { + export module camera { + export enum CameraPosition { + FRONT = 0, + BACK = 1, + } + + export enum FlashMode { + AUTO = 0, // default + ON = 1, + OFF = 2 + } + + // TODO most of hardware related parts need to handle onPause and onResume of the calling activities + export class CameraManager { + takePicture(params: any, onSuccess: (imageData: any) => any, onError?: (error: any) => any); + + // options { useSavedPhotos: true } + pictureFromLibrary(params: any, onSuccess: (imageData: any) => any, onError?: (error: any) => any); + } + } +} \ No newline at end of file diff --git a/Camera/camera.ios.ts b/Camera/camera.ios.ts new file mode 100644 index 000000000..99654b883 --- /dev/null +++ b/Camera/camera.ios.ts @@ -0,0 +1,15 @@ +export module tk { + export module io { + var REQUEST_IMAGE_CAPTURE: number = 1; + var REQUEST_SELECT_PICTURE: number = 2; + + export class CameraManager { + public takePicture(params: any, onSuccess: (imageData: any) => any, onError?: (error: any) => any) { + } + + // options { useSavedPhotos: true } + public pictureFromLibrary(params: any, onSuccess: (imageData: any) => any, onError?: (error: any) => any) { + } + } + } +} \ No newline at end of file diff --git a/Database/Readme.md b/Database/Readme.md new file mode 100644 index 000000000..ece3a25d1 --- /dev/null +++ b/Database/Readme.md @@ -0,0 +1,28 @@ +Sample code: +``` +// TODO: Update with the module architecture (require) +var folder = TK.IO.KnownFolders.Documents(); + +var path = folder.path + "/MyDB.db"; + +var db = TK.Data.Database.openDatabase(path); + +db.executeSql('DROP TABLE IF EXISTS DEMO;'); +db.executeSql('CREATE TABLE DEMO (id unique, data);'); +db.executeSql('INSERT INTO DEMO (id, data) VALUES (1, "First row")'); +db.executeSql('INSERT INTO DEMO (id, data) VALUES (2, "Second row")'); + +db.query("SELECT * FROM DEMO", function(result){ + Log("result count:" + result.count); + + for(var item in result.items) + { + for(var name in item) + { + Log(name + ":" + item[name]); + } + } + }, function(e){ Log("Error:" + e.message ); } +); + +``` \ No newline at end of file diff --git a/Database/database.android.ts b/Database/database.android.ts new file mode 100644 index 000000000..48c82dc0a --- /dev/null +++ b/Database/database.android.ts @@ -0,0 +1,92 @@ +import query_module = require("Database/database_query_result"); + +export module tk { + export module data { + /** + * Android specific Database implementation. + */ + export class Database { + public android: android.database.sqlite.SQLiteDatabase; + + public static openDatabase(path: string): Database { + return new Database(path); + } + + /** + * Open or creates SQLiteDatabase using the specified path. + */ + constructor(path: string) { + this.android = android.database.sqlite.SQLiteDatabase.openOrCreateDatabase(path, null); + } + + /** + * Executes non-select SQL statements using execSQL method of android.database.sqlite.SQLiteDatabase. + */ + public executeSql(sqlStatement: string, successCallback?: Function, errorCallback?: (e: Error) => void) { + try { + if (sqlStatement.toLowerCase().indexOf("select") > -1) { + throw new Error("Please use 'query' method for select SQL statements!"); + } + + this.android.execSQL(sqlStatement); + + if (successCallback) { + successCallback(); + } + } catch (ex) { + + if (errorCallback) { + errorCallback(ex); + } + + } + } + + /** + * Executes select SQL statements using rawQuery method of android.database.sqlite.SQLiteDatabase and returns QueryResult. + */ + public query(sqlSelectStatement: string, successCallback: (results: query_module.tk.data.QueryResult) => void, errorCallback?: (e: Error) => void) { + try { + + if (sqlSelectStatement.toLowerCase().indexOf("select") == -1) { + throw new Error("Please use 'executeSql' method for non-select SQL statements!"); + } + + if (successCallback) { + var cursor = this.android.rawQuery(sqlSelectStatement, null); + + var qr = new query_module.tk.data.QueryResult(); + qr.items = []; + qr.count = cursor.getCount(); + + if (qr.count > 0) { + cursor.moveToFirst(); + + var names = cursor.getColumnNames(); + + do { + var item = {}; + + for (var name in names) { + item[name] = cursor.getString(cursor.getColumnIndex(name)); + } + + qr.items.push(item); + } while (cursor.moveToNext()); + + cursor.close(); + } + + successCallback(qr); + } + } catch (ex) { + + if (errorCallback) { + errorCallback(ex); + } + + } + } + } + } +} \ No newline at end of file diff --git a/Database/database.d.ts b/Database/database.d.ts new file mode 100644 index 000000000..8f204c5f4 --- /dev/null +++ b/Database/database.d.ts @@ -0,0 +1,16 @@ +import qr = require("Database/database_query_result"); + +/** + * Data (Database) module. + */ +export declare module tk { + export module data { + /** + * The Database interface. + */ + export class Database { + executeSql(sqlStatement: string, successCallback?: Function, errorCallback?: (e: Error) => void) + query(sqlSelectStatement: string, successCallback: (results: qr.tk.data.QueryResult) => void, errorCallback?: (e: Error) => void) + } + } +} \ No newline at end of file diff --git a/Database/database.ios.ts b/Database/database.ios.ts new file mode 100644 index 000000000..1eae9083c --- /dev/null +++ b/Database/database.ios.ts @@ -0,0 +1,53 @@ +import query_module = require("Database/database_query_result"); + +export module tk { + export module data { + export class Database { + + public static openDatabase(path: string): Database { + return new Database(path); + } + + constructor(path: string) { + + } + + public executeSql(sqlStatement: string, successCallback?: Function, errorCallback?: (e: Error) => void) { + try { + + // native code goes here + + if (successCallback) { + successCallback(); + } + } catch (ex) { + + if (errorCallback) { + errorCallback(ex); + } + + } + } + + public query(sqlSelectStatement: string, successCallback: (results: query_module.tk.data.QueryResult) => void, errorCallback?: (e: Error) => void) { + try { + + // native code goes here + + if (successCallback) { + + var qr = new query_module.tk.data.QueryResult(); + + successCallback(qr); + } + } catch (ex) { + + if (errorCallback) { + errorCallback(ex); + } + + } + } + } + } +} \ No newline at end of file diff --git a/Database/database_query_result.ts b/Database/database_query_result.ts new file mode 100644 index 000000000..a1558732c --- /dev/null +++ b/Database/database_query_result.ts @@ -0,0 +1,21 @@ +export module tk { + export module data { + export class QueryResult { + constructor() { + + } + + /** + * Total number of query result items. + */ + get count(): number { + return 0; + } + + /** + * The query result items. + */ + public items: Array; + } + } +} \ No newline at end of file diff --git a/FileSystem/file_system.d.ts b/FileSystem/file_system.d.ts new file mode 100644 index 000000000..33e0fa209 --- /dev/null +++ b/FileSystem/file_system.d.ts @@ -0,0 +1,138 @@ +export declare module tk { + export module io { + export class FileSystemEntity { + public readonly: boolean; + public lastModified: Date; + /** + * Gets the name of the entity. + */ + public name: string; + /** + * Gets the fully-qualified path (including the extension for a File) of the entity. + */ + public path: string; + /** + * Gets the Folder object representing the parent of this entity. Will be null for a root folder like Documents or Temporary. + */ + public getParent(onSuccess: (folder: Folder) => any, onError?: (error: any) => any); + /** + * Deletes the current Entity from the file system. + */ + public delete(onSuccess?: () => any, onError?: (error: any) => any); + /** + * Renames the current entity using the specified name. + */ + public rename(newName: string, onSuccess: Function, onError: Function); + } + + export class File extends FileSystemEntity { + /** + * Gets the extension of the entity. + */ + public extension: string; + /** + * Gets a value indicating whether the file is currently locked, meaning a background operation associated with this file is running. + */ + public isLocked: boolean; + /** + * Gets or creates a File entity at the specified path. + */ + public static fromPath(path: string, onSuccess: (file: File) => any, onError?: (error: any) => any); + /** + * Checks whether a File with the specified path already exists. + */ + public static exists(path: string): boolean; + /** + * Creates a FileReader object over this file and locks the file until the reader is released. + */ + public openRead(): FileReader; + /** + * Creates a FileWriter object over this file and locks the file until the writer is released. + */ + public openWrite(): FileWriter; + } + + export class Folder extends FileSystemEntity { + /** + * Determines whether this instance is a KnownFolder (accessed through the KnownFolders object). + */ + public isKnown: boolean; + + /** + * Gets or creates a Folder entity at the specified path. + */ + public static fromPath(path: string, onSuccess: (folder: Folder) => any, onError?: (error: any) => any); + /** + * Checks whether a Folder with the specified path already exists. + */ + public static exists(path: string): boolean; + /** + * Checks whether this Folder contains a file with the specified name. + */ + public containsFile(name: string): boolean; + /** + * Deletes all the files and folders (recursively), contained within this Folder. + */ + public empty(onSuccess?: () => any, onError?: (error: any) => any); + /** + * Gets or creates a File entity with the specified name within this Folder. + */ + public getFile(name: string, onSuccess: (file: File) => any, onError?: (error: any) => any); + /** + * Gets or creates a Folder entity with the specified name within this Folder. + */ + public getFolder(name: string, onSuccess: (folder: Folder) => any, onError?: (error: any) => any); + /** + * Gets all the top-level files residing within this Folder. + */ + public enumFiles(onSuccess: (files: Array) => any, onError?: (error: any) => any); + } + + /** + * Provides access to the top-level Folders instances that are accessible from the application. Use these as entry points to access the FileSystem. + */ + export class KnownFolders { + /** + * Gets the Documents folder available for the current application. This Folder is private for the application and not accessible from Users/External apps. + */ + public static Documents(): Folder; + + /** + * Gets the Temporary (Caches) folder available for the current application. This Folder is private for the application and not accessible from Users/External apps. + */ + public static Temporary(): Folder; + } + + /** + * Base class for FileReader and FileWriter APIs. + */ + export class FileAccess { + constructor(file: File); + /** + * Unlocks the file and allows other operations over it. + */ + public release(); + /** + * Gets the underlying File instance. + */ + file: File; + } + + /** + * Enables reading the content of a File entity. + */ + export class FileReader extends FileAccess { + /** + * Reads the content of the underlying File as a UTF8 encoded string. + */ + public readText(onSuccess: (content: string) => any, onError?: (error: any) => any); + } + + /** + * Enables saving data to a File entity. + */ + export class FileWriter extends FileAccess { + public writeText(content: string, onSuccess?: () => any, onError?: (error: any) => any); + } + } +} \ No newline at end of file diff --git a/FileSystem/file_system.ts b/FileSystem/file_system.ts new file mode 100644 index 000000000..38dca4cf1 --- /dev/null +++ b/FileSystem/file_system.ts @@ -0,0 +1,364 @@ +import file_access_module = require("FileSystem/file_system_access"); + +export module tk { + export module io { + // The FileSystemAccess implementation, used through all the APIs. + var fileAccess; + var getFileAccess = function (): file_access_module.tk.io.FileSystemAccess { + if (!fileAccess) { + fileAccess = new file_access_module.tk.io.FileSystemAccess(); + } + + return fileAccess; + } + + // we are defining these as private variables within the IO scope and will use them to access the corresponding properties for each FSEntity instance. + // this allows us to encapsulate (hide) the explicit property setters and force the users go through the exposed APIs to receive FSEntity instances. + var nameProperty = "_name"; + var pathProperty = "_path"; + var isKnownProperty = "_isKnown"; + var fileLockedProperty = "_locked"; + var extensionProperty = "_extension"; + var readonlyProperty = "_readonly"; + var lastModifiedProperty = "_lastModified"; + + /** + * Represents the basic file system entity - a File or a Folder. + */ + export class FileSystemEntity { + /** + * Gets the Folder object representing the parent of this entity. Will be null for a root folder like Documents or Temporary. + */ + public getParent(onSuccess: (parent: Folder) => any, onError?: (error: any) => any) { + var localSuccess = function (path: string) { + var folder = new Folder(); + folder[pathProperty] = path; + + if (onSuccess) { + onSuccess(folder); + } + } + getFileAccess().getParent(this.path, localSuccess, onError); + } + /** + * Deletes the current entity from the file system. + */ + public delete(onSuccess?: () => any, onError?: (error: any) => any) { + if (this instanceof File) { + getFileAccess().deleteFile(this.path, onSuccess, onError); + } else if (this instanceof Folder) { + getFileAccess().deleteFolder(this.path, this[isKnownProperty], onSuccess, onError); + } + } + /** + * Renames the current entity using the specified name. + */ + public rename(newName: string, onSuccess?: () => any, onError?: (error: any) => any) { + // TODO: No implementation + } + /** + * Gets the name of the entity. + */ + get name(): string { + return this[nameProperty]; + } + /** + * Gets the fully-qualified path (including the extension for a File) of the entity. + */ + get path(): string { + return this[pathProperty]; + } + /** + * Gets a value indicating whether this entity is read-only (no write persmissions). + */ + get readonly(): boolean { + var value = this[readonlyProperty]; + if (this[readonlyProperty] === undefined) { + value = this[readonlyProperty] = getFileAccess().getReadonly(this.path); + } + + return value; + } + /** + * Gets the fully-qualified path (including the extension for a File) of the entity. + */ + get lastModified(): Date { + var value = this[lastModifiedProperty]; + if (this[lastModifiedProperty] === undefined) { + value = this[lastModifiedProperty] = getFileAccess().getLastModified(this.path); + } + + return value; + } + } + + /** + * Represents a File entity. + */ + export class File extends FileSystemEntity { + /** + * Gets the File instance associated with the specified path. + */ + public static fromPath(path: string, onSuccess: (file: File) => any, onError?: (error: any) => any) { + var localSuccess = function (path: string) { + var file = new File(); + file[pathProperty] = path; + + if (onSuccess) { + onSuccess(file); + } + } + getFileAccess().getFile(path, localSuccess, onError); + } + /** + * Checks whether a File with the specified path already exists. + */ + public static exists(path: string): boolean { + return getFileAccess().fileExists(path); + } + /** + * Deletes the current File from the file system. + */ + public delete(onSuccess?: () => any, onError?: (error: any) => any) { + getFileAccess().deleteFile(this.path, onSuccess, onError); + } + /** + * Creates a FileReader object over this file and locks the file until the reader is released. + */ + public openRead(): FileReader { + this.checkAccess(); + return new FileReader(this); + } + /** + * Creates a FileWriter object over this file and locks the file until the writer is released. + */ + public openWrite(): FileWriter { + this.checkAccess(); + return new FileWriter(this); + } + /** + * Gets the extension of the entity. + */ + get extension(): string { + return this[extensionProperty]; + } + /** + * Gets a value indicating whether the file is currently locked, meaning a background operation associated with this file is running. + */ + get isLocked(): boolean { + return this[fileLockedProperty]; + } + + private checkAccess() { + if (this.isLocked) { + throw { + message: "Cannot access a locked file." + }; + } + } + } + + /** + * Represents a Folder entity. + */ + export class Folder extends FileSystemEntity { + /** + * Attempts to access a Folder at the specified path and creates a new Folder if there is no existing one. + */ + public static fromPath(path: string, onSuccess: (folder: Folder) => any, onError?: (error: any) => any) { + var localSuccess = function (path: string) { + var folder = new Folder(); + folder[pathProperty] = path; + + if (onSuccess) { + onSuccess(folder); + } + } + getFileAccess().getFolder(path, localSuccess, onError); + } + + /** + * Checks whether a Folder with the specified path already exists. + */ + public static exists(path: string): boolean { + return getFileAccess().folderExists(path); + } + + /** + * Checks whether this Folder contains a file with the specified name. + */ + public containsFile(name: string): boolean { + var fileAccess = getFileAccess(); + var path = fileAccess.concatPath(this.path, name); + return fileAccess.fileExists(path); + } + + /** + * Deletes the current Folder (recursively) from the file system. + */ + public delete(onSuccess?: () => any, onError?: (error: any) => any) { + getFileAccess().deleteFolder(this.path, this.isKnown, onSuccess, onError); + } + + /** + * Deletes all the files and folders (recursively), contained within this Folder. + */ + public empty(onSuccess?: () => any, onError?: (error: any) => any) { + getFileAccess().emptyFolder(this.path, onSuccess, onError); + } + + /** + * Determines whether this instance is a KnownFolder (accessed through the KnownFolders object). + */ + get isKnown(): boolean { + return this[isKnownProperty]; + } + + /** + * Attempts to open a File with the specified name within this Folder and optionally creates a new File if there is no existing one. + */ + public getFile(name: string, onSuccess: (file: File) => any, onError?: (error: any) => any, createIfNonExisting?: boolean) { + var localSuccess = function (filePath: string) { + var newFile = new File(); + + newFile[pathProperty] = filePath; + newFile[nameProperty] = name; + + if (onSuccess) { + onSuccess(newFile); + } + } + var fileAccess = getFileAccess(); + var path = fileAccess.concatPath(this.path, name); + fileAccess.getFile(path, localSuccess, onError); + } + + /** + * Attempts to open a Folder with the specified name within this Folder and optionally creates a new Folder if there is no existing one. + */ + public getFolder(name: string, onSuccess: (folder: Folder) => any, onError?: (error: any) => any) { + var localSuccess = function (filePath: string) { + var newFolder = new Folder(); + + newFolder[pathProperty] = filePath; + newFolder[nameProperty] = name; + + if (onSuccess) { + onSuccess(newFolder); + } + } + + var fileAccess = getFileAccess(); + var path = fileAccess.concatPath(this.path, name); + fileAccess.getFolder(path, localSuccess, onError); + } + + /** + * Gets all the top-level files residing within this Folder. + */ + public enumFiles(onSuccess: (files: Array) => any, onError?: (error: any) => any) { + var localSuccess = function (paths: Array) { + if (onSuccess) { + var files = new Array(); + var i, + path: string, + file: File; + + for (i = 0; i < files.length; i++) { + file = new File(); + file[pathProperty] = files[i]; + files.push(file); + } + + onSuccess(files); + } + } + getFileAccess().enumFiles(this.path, localSuccess, onError); + } + } + + /** + * Provides access to the top-level Folders instances that are accessible from the application. Use these as entry points to access the FileSystem. + */ + export class KnownFolders { + private static _documents: Folder; + private static _temp: Folder; + + /** + * Gets the Documents folder available for the current application. This Folder is private for the application and not accessible from Users/External apps. + */ + public static Documents(): Folder { + if (!KnownFolders._documents) { + var path = getFileAccess().getDocumentsFolderPath(); + KnownFolders._documents = new Folder(); + KnownFolders._documents[pathProperty] = path; + KnownFolders._documents[isKnownProperty] = true; + } + + return KnownFolders._documents; + } + + /** + * Gets the Temporary (Caches) folder available for the current application. This Folder is private for the application and not accessible from Users/External apps. + */ + public static Temporary(): Folder { + if (!KnownFolders._temp) { + var path = getFileAccess().getTempFolderPath(); + KnownFolders._temp = new Folder(); + KnownFolders._temp[pathProperty] = path; + KnownFolders._temp[isKnownProperty] = true; + } + + return KnownFolders._temp; + } + } + + /** + * Base class for FileReader and FileWriter APIs. + */ + export class FileAccess { + private _file; + + constructor(file: File) { + this._file = file; + this._file[fileLockedProperty] = true; + } + + /** + * Unlocks the file and allows other operations over it. + */ + public release() { + this._file[fileLockedProperty] = false; + this._file = undefined; + } + + /** + * Gets the underlying File instance. + */ + get file(): File { + return this._file; + } + } + + /** + * Enables reading the content of a File entity. + */ + export class FileReader extends FileAccess { + /** + * Reads the content of the underlying File as a UTF8 encoded string. + */ + public readText(onSuccess: (content: string) => any, onError?: (error: any) => any) { + getFileAccess().readText(this.file.path, onSuccess, onError); + } + } + + /** + * Enables saving data to a File entity. + */ + export class FileWriter extends FileAccess { + public writeText(content: string, onSuccess?: () => any, onError?: (error: any) => any) { + getFileAccess().writeText(this.file.path, content, onSuccess, onError); + } + } + } +} \ No newline at end of file diff --git a/FileSystem/file_system_access.android.ts b/FileSystem/file_system_access.android.ts new file mode 100644 index 000000000..71c1b0592 --- /dev/null +++ b/FileSystem/file_system_access.android.ts @@ -0,0 +1,305 @@ +import app_module = require("Application/application"); + +export module tk { + export module io { + export class FileSystemAccess { + private _encoding = "UTF-8"; + private _pathSeparator = "/"; + + public getReadonly(path: string): boolean { + var javaFile = new java.io.File(path); + return javaFile.exists() && !javaFile.canWrite(); + } + + public getLastModified(path: string): Date { + var javaFile = new java.io.File(path); + return new Date(javaFile.lastModified()); + } + + public getParent(path: string, onSuccess: (path: string) => any, onError?: (error: any) => any) { + try { + var javaFile = new java.io.File(path); + if (onSuccess) { + var parent = javaFile.getParentFile(); + onSuccess(parent.getPath()); + } + } catch (exception) { + // TODO: unified approach for error messages + if (onError) { + onError(exception); + } + } + } + + public getFile(path: string, onSuccess: (path: string) => any, onError?: (error: any) => any) { + this.ensureFile(new java.io.File(path), onSuccess, onError); + } + + public getFolder(path: string, onSuccess: (path: string) => any, onError?: (error: any) => any) { + var javaFile = new java.io.File(path); + if (javaFile.exists() && !javaFile.isDirectory()) { + if (onError) { + onError("The path " + path + "exists and is not a directory"); + } + } else { + this.ensureFile(javaFile, onSuccess, onError); + } + } + + public enumFiles(path: string, onSuccess: (files: Array) => any, onError?: (error: any) => any) { + try { + var javaFile = new java.io.File(path); + if (!javaFile.isDirectory()) { + if (onError) { + onError("There is no folder existing at path " + path); + } + + return; + } + + if (javaFile.isDirectory()) { + var filesList: Array = javaFile.listFiles(); + var filePaths = new Array(); + + var length = filesList.length, + i, + filePath; + + for (i = 0; i < length; i++) { + javaFile = filesList[i]; + + if (javaFile.isFile()) { + filePath = javaFile.getPath(); + filesList.push(filePath); + } + } + + if (onSuccess) { + onSuccess(filePaths); + } + } + + } catch (exception) { + if (onError) { + onError(exception); + } + } + } + + public fileExists(path: string): boolean { + var file = new java.io.File(path); + return file.exists(); + } + + public folderExists(path: string): boolean { + var file = new java.io.File(path); + return file.exists() && file.isDirectory(); + } + + public concatPath(left: string, right: string): string { + return left + this._pathSeparator + right; + } + + public deleteFile(path: string, onSuccess?: () => any, onError?: (error: any) => any) { + try { + var javaFile = new java.io.File(path); + if (!javaFile.isFile()) { + if (onError) { + onError({ message: "The specified parameter is not a File entity." }); + } + + return; + } + + if (!javaFile.delete()) { + if (onError) { + onError({ message: "File deletion failed" }); + } + } else if (onSuccess) { + onSuccess(); + } + } catch (exception) { + if (onError) { + onError(exception); + } + } + } + + public deleteFolder(path: string, isKnown?: boolean, onSuccess?: () => any, onError?: (error: any) => any) { + try { + var javaFile = new java.io.File(path); + if (!javaFile.isDirectory()) { + if (onError) { + onError({ message: "The specified parameter is not a Folder entity." }); + } + + return; + } + + // TODO: Asynchronous + this.deleteFolderContent(javaFile); + + if (!isKnown) { + if (javaFile.delete()) { + if (onSuccess) { + onSuccess(); + } + } else { + if (onError) { + onError({ message: "Folder deletion failed." }); + } + } + } else { + // TODO: Notify error? + } + } catch (exception) { + if (onError) { + onError(exception); + } + } + } + + public emptyFolder(path: string, onSuccess?: () => any, onError?: (error: any) => any) { + try { + var javaFile = new java.io.File(path); + if (!javaFile.isDirectory()) { + if (onError) { + onError({ message: "The specified parameter is not a Folder entity." }); + } + + return; + } + + // TODO: Asynchronous + this.deleteFolderContent(javaFile); + + if (onSuccess) { + onSuccess(); + } + + } catch (exception) { + if (onError) { + onError(exception); + } + } + } + + public rename(path: string, onSuccess?: () => any, onError?: (error: any) => any) { + // TODO: No implementation + } + + public getDocumentsFolderPath(): string { + var context = app_module.tk.ui.Application.current.android.context; + var dir: java.io.File = context.getFilesDir(); + return dir.getPath(); + } + + public getTempFolderPath(): string { + var context = app_module.tk.ui.Application.current.android.context; + var dir: java.io.File = context.getCacheDir(); + return dir.getPath(); + } + + public readText(path: string, onSuccess: (content: string) => any, onError?: (error: any) => any) { + try { + var javaFile = new java.io.File(path); + var stream = new java.io.FileInputStream(javaFile); + var reader = new java.io.InputStreamReader(stream, this._encoding); + var bufferedReader = new java.io.BufferedReader(reader); + + // TODO: We will need to read the entire file to a CharBuffer instead of reading it line by line + // TODO: bufferedReader.read(CharBuffer) does not currently work + var line = undefined; + var result = ""; + while (true) { + line = bufferedReader.readLine(); + if (!line) { + break; + } + + if (result.length > 0) { + // add the new line manually to the result + // TODO: Try with CharBuffer at a later stage, when the Bridge allows it + // result += "\n"; + } + result += line; + } + + bufferedReader.close(); + + if (onSuccess) { + onSuccess(result); + } + } catch (exception) { + if (onError) { + onError(exception); + } + } + } + + public writeText(path: string, content: string, onSuccess?: () => any, onError?: (error: any) => any) { + try { + var javaFile = new java.io.File(path); + var stream = new java.io.FileOutputStream(javaFile); + var writer = new java.io.OutputStreamWriter(stream, this._encoding); + var bufferedWriter = new java.io.BufferedWriter(writer); + + bufferedWriter.write(content); + bufferedWriter.close(); + + if (onSuccess) { + onSuccess(); + } + } catch (exception) { + if (onError) { + onError(exception); + } + } + } + + private deleteFolderContent(file: java.io.File): boolean { + var filesList = file.listFiles(); + + var i, + childFile: java.io.File, + success: boolean = false; + + for (i = 0; i < filesList.length; i++) { + childFile = filesList[i]; + if (childFile.isDirectory()) { + success = this.deleteFolderContent(childFile); + if (!success) { + break; + } + } + + success = childFile.delete(); + } + + return success; + } + + private ensureFile(javaFile: java.io.File, onSuccess: (path: string) => any, onError?: (error: any) => any) { + try { + if (!javaFile.exists()) { + if (!javaFile.createNewFile()) { + // TODO: unified approach for error messages + if (onError) { + onError("Failed to create new file for path " + javaFile.getPath()); + } + } + } + + if (onSuccess) { + onSuccess(javaFile.getPath()); + } + } catch (exception) { + // TODO: unified approach for error messages + if (onError) { + onError(exception); + } + } + } + } + } +} \ No newline at end of file diff --git a/FileSystem/file_system_access.d.ts b/FileSystem/file_system_access.d.ts new file mode 100644 index 000000000..8462bbb0d --- /dev/null +++ b/FileSystem/file_system_access.d.ts @@ -0,0 +1,28 @@ +//import file_system_module = require("FileSystem/file_system"); +//import entities = file_system_module.tk.io; + +//@hidden +export declare module tk { + export module io { + export class FileSystemAccess { + getReadonly(path: string): boolean; + getLastModified(path: string): Date; + + getParent(path: string, onSuccess: (path: string) => any, onError?: (error: any) => any); + getFile(path: string, onSuccess: (path: string) => any, onError?: (error: any) => any); + getFolder(path: string, onSuccess: (path: string) => any, onError?: (error: any) => any); + enumFiles(path: string, onSuccess: (files: Array) => any, onError?: (error: any) => any); + fileExists(path: string): boolean; + folderExists(path: string): boolean; + concatPath(left: string, right: string): string; + deleteFile(path: string, onSuccess?: () => any, onError?: (error: any) => any); + deleteFolder(path: string, isKnown: boolean, onSuccess?: () => any, onError?: (error: any) => any); + emptyFolder(path: string, onSuccess?: () => any, onError?: (error: any) => any): void; + rename(path: string, onSuccess?: () => any, onError?: (error: any) => any): void; + getDocumentsFolderPath(): string; + getTempFolderPath(): string; + readText(path: string, onSuccess: (content: string) => any, onError?: (error: any) => any); + writeText(path: string, content: string, onSuccess?: () => any, onError?: (error: any) => any); + } + } +} \ No newline at end of file diff --git a/FileSystem/file_system_access.ios.ts b/FileSystem/file_system_access.ios.ts new file mode 100644 index 000000000..a313aa385 --- /dev/null +++ b/FileSystem/file_system_access.ios.ts @@ -0,0 +1,82 @@ +import app_module = require("Application/application"); + +export module tk { + export module io { + export class FileSystemAccess { + public getReadonly(path: string): boolean { + // TODO: Not implemented + return false; + } + + public getLastModified(path: string): Date { + // TODO: Not implemented + return undefined; + } + + public getParent(path: string, onSuccess: (path: string) => any, onError?: (error: any) => any) { + // TODO: Not implemented + } + + public getFile(path: string, onSuccess: (path: string) => any, onError?: (error: any) => any) { + // TODO: Not implemented + } + + public getFolder(path: string, onSuccess: (path: string) => any, onError?: (error: any) => any) { + // TODO: Not implemented + } + + public enumFiles(path: string, onSuccess: (files: Array) => any, onError?: (error: any) => any) { + // TODO: Not implemented + } + + public fileExists(path: string): boolean { + // TODO: Not implemented + return false; + } + + public folderExists(path: string): boolean { + // TODO: Not implemented + return false; + } + + public concatPath(left: string, right: string): string { + // TODO: Not implemented + return undefined; + } + + public deleteFile(path: string, onSuccess?: () => any, onError?: (error: any) => any) { + // TODO: Not implemented + } + + public deleteFolder(path: string, isKnown?: boolean, onSuccess?: () => any, onError?: (error: any) => any) { + // TODO: Not implemented + } + + public emptyFolder(path: string, onSuccess?: () => any, onError?: (error: any) => any) { + // TODO: Not implemented + } + + public rename(path: string, onSuccess?: () => any, onError?: (error: any) => any) { + // TODO: No implementation + } + + public getDocumentsFolderPath(): string { + // TODO: Not implemented + return undefined; + } + + public getTempFolderPath(): string { + // TODO: Not implemented + return undefined; + } + + public readText(path: string, onSuccess: (content: string) => any, onError?: (error: any) => any) { + // TODO: Not implemented + } + + public writeText(path: string, content: string, onSuccess?: () => any, onError?: (error: any) => any) { + // TODO: Not implemented + } + } + } +} \ No newline at end of file diff --git a/Image/Readme.md b/Image/Readme.md new file mode 100644 index 000000000..4bfd8e245 --- /dev/null +++ b/Image/Readme.md @@ -0,0 +1,5 @@ +The way we get local path here is different for now. Maybe we should get it from FS module in the future samples. Sample code Android: + +``` +// TODO: Update code sample using require and BCL File/Folder +``` diff --git a/Image/image.android.ts b/Image/image.android.ts new file mode 100644 index 000000000..d044fdc46 --- /dev/null +++ b/Image/image.android.ts @@ -0,0 +1,68 @@ +import app_module = require("Application/application"); + +export module tk { + export module ui { + export enum ImageType { + PNG = 0, + JPEG = 1, + } + + export class Image { + private _nativeImage: any; + + constructor() { + this._nativeImage = null; + } + + public loadFromResource(name: string): boolean { + var androidApp = app_module.tk.ui.Application.current.android; + var res = androidApp.context.getResources(); + if (res) { + var identifier: number = res.getIdentifier(name, 'drawable', androidApp.packageName); + if (0 < identifier) { + this._nativeImage = android.graphics.BitmapFactory.decodeResource(res, identifier); + return (this._nativeImage != null); + } + } + return false; + } + + public loadFromFile(path: string): boolean { + this._nativeImage = android.graphics.BitmapFactory.decodeFile(path, null); + return (this._nativeImage != null); + } + + public loadFromData(data: any): boolean { + this._nativeImage = android.graphics.BitmapFactory.decodeStream(data); + return (this._nativeImage != null); + } + + public saveToFile(path: string, format: ImageType, quality?: number): boolean { + if (this._nativeImage) { + var targetFormat = android.graphics.Bitmap.CompressFormat.PNG; + switch (format) { + case ImageType.JPEG: + targetFormat = android.graphics.Bitmap.CompressFormat.JPEG; + break; + } + + // TODO add exception handling + var outputStream = new java.io.BufferedOutputStream(new java.io.FileOutputStream(path)); + // FIXME compress is not found + var res = this._nativeImage.compress(targetFormat, outputStream); + outputStream.close(); + return res; + } + return false; + } + + public getHeight(): number { + return (this._nativeImage) ? this._nativeImage.getHeight() : NaN; + } + + public getWidth(): number { + return (this._nativeImage) ? this._nativeImage.getWidth() : NaN; + } + } + } +} \ No newline at end of file diff --git a/Image/image.d.ts b/Image/image.d.ts new file mode 100644 index 000000000..65db7e37f --- /dev/null +++ b/Image/image.d.ts @@ -0,0 +1,18 @@ +export declare module tk { + export module ui { + export enum ImageType { + PNG = 0, + JPEG = 1, + } + + export class Image { + loadFromResource(name: string): boolean; + loadFromFile(path: string): boolean; + loadFromData(data: any): boolean; + saveToFile(path: string, format: ImageType, quality?: number): boolean; + + getHeight(): number; + getWidth(): number; + } + } +} \ No newline at end of file diff --git a/Image/image.ios.ts b/Image/image.ios.ts new file mode 100644 index 000000000..8e556d310 --- /dev/null +++ b/Image/image.ios.ts @@ -0,0 +1,59 @@ +module tk { + export module ui { + export enum ImageType { + PNG = 0, + JPEG = 1, + } + + export class Image { + private _nativeImage: any; + + constructor() { + this._nativeImage = null; + } + + public loadFromResource(name: string): boolean { + this._nativeImage = UIKit.UIImage.imageNamed(name); + return (this._nativeImage != null); + } + + public loadFromFile(path: string): boolean { + this._nativeImage = UIKit.UIImage.imageWithContentsOfFile(path); + return (this._nativeImage != null); + } + + public loadFromData(data: any): boolean { + this._nativeImage = UIKit.UIImage.imageWithData(data); + return (this._nativeImage != null); + } + + public saveToFile(path: string, format: ImageType, quality?: number): boolean { + if (null == this._nativeImage) { + return false; + } + var res = false; + var data = null; + switch (format) { + case ImageType.JPEG: + data = UIKit.UIImageJPEGRepresentation(this._nativeImage, ('undefined' == typeof quality) ? 1.0 : quality); + break; + case ImageType.PNG: + data = UIKit.UIImagePNGRepresentation(this._nativeImage); + break; + } + if (null != data) { + res = data.writeToFileAtomically(path, true); + } + return res; + } + + public getHeight(): number { + return (this._nativeImage) ? this._nativeImage.size().height : NaN; + } + + public getWidth(): number { + return (this._nativeImage) ? this._nativeImage.size().width : NaN; + } + } + } +} \ No newline at end of file diff --git a/Location/location.android.ts b/Location/location.android.ts new file mode 100644 index 000000000..f998c1103 --- /dev/null +++ b/Location/location.android.ts @@ -0,0 +1,88 @@ +import types_module = require("Location/location_types"); +import app_module = require("Application/application"); + +export module tk { + export module location { + export class LocationManager { + + //public regions: LocationRegion[]; + + private _locationManager: any; + private _locationListener: android.location.LocationListener; + + public isLocationEnabled(): boolean { + // TODO add proper implementation + return true; + } + + constructor() { + //this.regions = []; + this.desiredAccuracy = types_module.tk.location.DesiredAccuracy.ANY; + this._locationManager = app_module.tk.ui.Application.current.android.context.getSystemService('location'); + Log('location manager: ' + this._locationManager); + + this._locationListener = new android.location.LocationListener({ + onLocationChanged: function (location: android.location.Location) { + }, + + onProviderDisabled: function (provider: string) { + }, + + onProviderEnabled: function (provider: string) { + } + }); + } + + // in meters + // we might need some predefined values here like 'any' and 'high' + public desiredAccuracy: number; + + // listeners + public locationChangeListener: types_module.tk.location.LocationChangeListener; + + // public regionChangeListener: RegionChangeListener; + + + /* // regions + public addRegion(region: LocationRegion) { + this.regions.push(region); + } + + public removeRegion(region: LocationRegion) { + + } + + public clearRegions() { + + }*/ + + // monitoring + + public startLocationMonitoring() { + var criteria = new android.location.Criteria(); + criteria.setAccuracy((this.desiredAccuracy === types_module.tk.location.DesiredAccuracy.HIGH) ? 3 : 1); + var providers = this._locationManager.getProviders(criteria, false); + var it = providers.iterator(); + while (it.hasNext()) { + var element = it.next(); + Log('found provider: ' + element); + this._locationManager.requestLocationUpdates(element, 200, 10, this._locationListener); + } + } + + public stopLocationMonitoring() { + this._locationManager.removeUpdates(this._locationListener); + } + + // other + + public getLastKnownLocation(): types_module.tk.location.LocationPoint { + return null; + } + + public distanceInMeters(loc1: types_module.tk.location.LocationPoint, loc2: types_module.tk.location.LocationPoint): number { + return 0; + } + } + } +} \ No newline at end of file diff --git a/Location/location.d.ts b/Location/location.d.ts new file mode 100644 index 000000000..98ee7fdf7 --- /dev/null +++ b/Location/location.d.ts @@ -0,0 +1,66 @@ +export declare module tk { + export module location { + export enum DesiredAccuracy { + // in meters + ANY, + HIGH, + } + + export class LocationPoint { + public latitude: number; + public longitude: number; + + public altitude: number; + + public horizontalAccuracy: number; + public verticalAccuracy: number; + + public speed: number; // in m/s ? + + public direction: number; // in degrees + + public timestamp: any; + } + + export class LocationRegion { + public latitude: number; + public longitude: number; + + public raduis: number; // radius in meters + } + + export class LocationChangeListener { + onLocationChange(location: Location); + } + + export class RegionChangeListener { + onRegionEnter(region: LocationRegion); + onRegionExit(region: LocationRegion); + } + + export class LocationManager { + isLocationEnabled(): boolean; + desiredAccuracy: number; + + // listeners + locationChangeListener: LocationChangeListener; + /* regionChangeListener: RegionChangeListener; + + // regions + addRegion(region: LocationRegion); + + removeRegion(region: LocationRegion); + + clearRegions();*/ + + // monitoring + + startLocationMonitoring(); + stopLocationMonitoring(); + + // other + getLastKnownLocation(): LocationPoint; + distanceInMeters(loc1: LocationPoint, loc2: LocationPoint): number; + } + } +} \ No newline at end of file diff --git a/Location/location.ios.ts b/Location/location.ios.ts new file mode 100644 index 000000000..bc2aca86c --- /dev/null +++ b/Location/location.ios.ts @@ -0,0 +1,44 @@ +import types = require("Location/location_types"); + +export module tk { + export module location { + export class LocationManager { + + public isLocationEnabled(): boolean { + // TODO add proper implementation + return true; + } + + constructor() { + + } + + // in meters + // we might need some predefined values here like 'any' and 'high' + public desiredAccuracy: number; + + // listeners + public locationChangeListener: types.tk.location.LocationChangeListener; + + // monitoring + + public startLocationMonitoring() { + + } + + public stopLocationMonitoring() { + + } + + // other + + public getLastKnownLocation(): types.tk.location.LocationPoint { + return null; + } + + public distanceInMeters(loc1: types.tk.location.LocationPoint, loc2: types.tk.location.LocationPoint): number { + return 0; + } + } + } +} diff --git a/Location/location_types.ts b/Location/location_types.ts new file mode 100644 index 000000000..3344ec76d --- /dev/null +++ b/Location/location_types.ts @@ -0,0 +1,46 @@ +export module tk { + export module location { + export enum DesiredAccuracy { + // in meters + ANY = 300, + HIGH = 3, + } + + export class LocationPoint { + public latitude: number; + public longitude: number; + + public altitude: number; + + public horizontalAccuracy: number; + public verticalAccuracy: number; + + public speed: number; // in m/s ? + + public direction: number; // in degrees + + public timestamp: any; + } + + export class LocationRegion { + public latitude: number; + public longitude: number; + + public raduis: number; // radius in meters + } + + // TODO: This might be implemented with a callback, no need of special type. + export class LocationChangeListener { + onLocationChange(location: Location) { + } + } + + // TODO: This might be implemented with two callbacks, no need of special type. + export class RegionChangeListener { + onRegionEnter(region: LocationRegion) { + } + onRegionExit(region: LocationRegion) { + } + } + } +} \ No newline at end of file diff --git a/Readme.md b/Readme.md new file mode 100644 index 000000000..a46dc6f7a --- /dev/null +++ b/Readme.md @@ -0,0 +1,5 @@ +Steps to build the BCL solution: + +``` +// TODO: Update code sample using require and BCL File/Folder +``` diff --git a/UserPreferences/Readme.md b/UserPreferences/Readme.md new file mode 100644 index 000000000..648fbedc9 --- /dev/null +++ b/UserPreferences/Readme.md @@ -0,0 +1,6 @@ +Sample code: + +``` +// TODO: Add API usage +// TODO: We may think to expose an instance through the Application class - e.g. tk.ui.Application.userPreferences, like in Windows (Phone) 8. +``` \ No newline at end of file diff --git a/UserPreferences/user_preferences.android.ts b/UserPreferences/user_preferences.android.ts new file mode 100644 index 000000000..6ee58ed18 --- /dev/null +++ b/UserPreferences/user_preferences.android.ts @@ -0,0 +1,103 @@ +import utils_module = require("Utils/utils_android"); +import app_module = require("Application/application"); + +export module tk { + // TODO: Think better naming and namespaces - e.g. tk.storage + export module preferences { + + export class UserPreferences { + private sharedPreferences: any; + + constructor() { + this.sharedPreferences = app_module.tk.ui.Application.current.android.context.getSharedPreferences("prefs.db", 0); + } + + public containsKey(key: string): boolean { + return this.sharedPreferences.contains(key); + } + + public getBoolean(key: string, defaultValue?: boolean): boolean { + if ("undefined" == typeof defaultValue) { + defaultValue = false; + } + return this.sharedPreferences.getBoolean(key, defaultValue); + } + + public getDouble(key: string, defaultValue?: number): number { + if ("undefined" == typeof defaultValue) { + defaultValue = 0.0; + } + Log('getting double for key ' + key + ' with default ' + defaultValue + ' result: ' + this.sharedPreferences.getFloat(key, defaultValue)); + return this.sharedPreferences.getFloat(key, defaultValue); + } + + public getInt(key: string, defaultValue?: number): number { + if ("undefined" == typeof defaultValue) { + defaultValue = 0; + } + return this.sharedPreferences.getInt(key, defaultValue); + } + + public getLong(key: string, defaultValue?: number): number { + if ("undefined" == typeof defaultValue) { + defaultValue = 0; + } + return this.sharedPreferences.getLong(key, defaultValue); + } + + public getString(key: string, defaultValue?: string): string { + if ("undefined" == typeof defaultValue) { + defaultValue = null; // is this ok? + } + return this.sharedPreferences.getString(key, defaultValue); + } + + public getStrings(key: string, defaultValue?: string[]): string[] { + if ("undefined" == typeof defaultValue) { + defaultValue = []; + } + var hashSet = utils_module.tk.utils.Collections.stringArrayToStringSet(defaultValue); + var res = this.sharedPreferences.getStringSet(key, hashSet); + return utils_module.tk.utils.Collections.stringSetToStringArray(res); + } + + public setBoolean(key: string, value: boolean) { + var editor = this.sharedPreferences.edit(); + editor.putBoolean(key, value); + editor.commit(); + } + + public setDouble(key: string, value: number) { + var editor = this.sharedPreferences.edit(); + Log('setting double for key ' + key + ' with value ' + value); + editor.putFloat(key, float(value)); + editor.commit(); + } + + public setInt(key: string, value: number) { + var editor = this.sharedPreferences.edit(); + editor.putInt(key, value); + editor.commit(); + } + + public setLong(key: string, value: number) { + var editor = this.sharedPreferences.edit(); + editor.putLong(key, long(value)); + editor.commit(); + } + + public setString(key: string, value: string) { + var editor = this.sharedPreferences.edit(); + editor.putString(key, value); + editor.commit(); + } + + public setStrings(key: string, values: string[]) { + var editor = this.sharedPreferences.edit(); + var hashSet = utils_module.tk.utils.Collections.stringArrayToStringSet(values); + editor.putStringSet(key, hashSet); + editor.commit(); + } + } + } +} \ No newline at end of file diff --git a/UserPreferences/user_preferences.d.ts b/UserPreferences/user_preferences.d.ts new file mode 100644 index 000000000..60ad9c467 --- /dev/null +++ b/UserPreferences/user_preferences.d.ts @@ -0,0 +1,19 @@ +export declare module tk { + export module preferences { + export class UserPreferences { + containsKey(key: string): boolean; + getBoolean(key: string, defaultValue?: boolean): boolean; + getDouble(key: string, defaultValue?: number): number; + getInt(key: string, defaultValue?: number): number; + getLong(key: string, defaultValue?: number): number; + getString(key: string, defaultValue?: string): string; + getStrings(key: string, defaultValue?: string[]): string[]; + setBoolean(key: string, value: boolean); + setDouble(key: string, value: number); + setInt(key: string, value: number); + setLong(key: string, value: number); + setString(key: string, value: string); + setStrings(key: string, value: string[]); + } + } +} \ No newline at end of file diff --git a/UserPreferences/user_preferences.ios.ts b/UserPreferences/user_preferences.ios.ts new file mode 100644 index 000000000..20d0618c6 --- /dev/null +++ b/UserPreferences/user_preferences.ios.ts @@ -0,0 +1,114 @@ +import utils_module = require("Utils/utils_ios"); + +module tk { + // TODO: Think better naming and namespaces - e.g. tk.storage + export module preferences { + + export class UserPreferences { + + private userDefaults: any; + + constructor() { + this.userDefaults = Foundation.NSUserDefaults.standardUserDefaults(); + } + + public containsKey(key: string): boolean { + // FIXME: is there a better way to do this check? + return this.userDefaults.objectForKey(key) ? true : false; + } + + public getBoolean(key: string, defaultValue?: boolean): boolean { + if (this.containsKey(key)) { + return this.userDefaults.boolForKey(key); + } + if ("undefined" == typeof defaultValue) { + defaultValue = false; + } + return defaultValue; + } + + public getDouble(key: string, defaultValue?: number): number { + if (this.containsKey(key)) { + return this.userDefaults.doubleForKey(key); + } + if ("undefined" == typeof defaultValue) { + defaultValue = 0.0; + } + return defaultValue; + } + + public getInt(key: string, defaultValue?: number): number { + if (this.containsKey(key)) { + return this.userDefaults.integerForKey(key); + } + if ("undefined" == typeof defaultValue) { + defaultValue = 0; + } + return defaultValue; + } + + public getLong(key: string, defaultValue?: number): number { + if (this.containsKey(key)) { + return this.userDefaults.integerForKey(key); + } + if ("undefined" == typeof defaultValue) { + defaultValue = 0; + } + return defaultValue; + } + + public getString(key: string, defaultValue?: string): string { + if (this.containsKey(key)) { + return this.userDefaults.stringForKey(key); + } + if ("undefined" == typeof defaultValue) { + defaultValue = ""; + } + return defaultValue; + } + + public getStrings(key: string, defaultValue?: string[]): string[] { + if (this.containsKey(key)) { + var nsArray = this.userDefaults.stringArrayForKey(key); + var jsArray = utils_module.tk.utils.Collections.nsArrayToJSArray(nsArray); + return jsArray; + } + if ("undefined" == typeof defaultValue) { + defaultValue = []; + } + return defaultValue; + } + + public setBoolean(key: string, value: boolean) { + this.userDefaults.setBoolForKey(value, key); + this.userDefaults.synchronize(); + } + + public setDouble(key: string, value: number) { + this.userDefaults.setDoubleForKey(value, key); + this.userDefaults.synchronize(); + } + + public setInt(key: string, value: number) { + this.userDefaults.setIntegerForKey(value, key); + this.userDefaults.synchronize(); + } + + public setLong(key: string, value: number) { + this.userDefaults.setIntegerForKey(value, key); + this.userDefaults.synchronize(); + } + + public setString(key: string, value: string) { + this.userDefaults.setObjectForKey(value, key); + this.userDefaults.synchronize(); + } + + public setStrings(key: string, values: string[]) { + var nsArray = utils_module.tk.utils.Collections.jsArrayToNSArray(values); + this.userDefaults.setObjectForKey(nsArray, key); + this.userDefaults.synchronize(); + } + } + } +} \ No newline at end of file diff --git a/Utils/utils_android.ts b/Utils/utils_android.ts new file mode 100644 index 000000000..96d6923fe --- /dev/null +++ b/Utils/utils_android.ts @@ -0,0 +1,29 @@ +export module tk { + // TODO: this should be properly organized + export module utils { + export class Collections { + public static stringArrayToStringSet(str: string[]): any { + var hashSet = new java.util.HashSet(); + if ("undefined" != typeof str) { + for (var element in str) { + hashSet.add('' + str[element]); + } + } + return hashSet; + } + + public static stringSetToStringArray(stringSet: any): string[] { + var arr = []; + if ("undefined" != typeof stringSet) { + var it = stringSet.iterator(); + while (it.hasNext()) { + var element = '' + it.next(); + arr.push(element); + } + } + + return arr; + } + } + } +} \ No newline at end of file diff --git a/Utils/utils_ios.ts b/Utils/utils_ios.ts new file mode 100644 index 000000000..97c8c9d84 --- /dev/null +++ b/Utils/utils_ios.ts @@ -0,0 +1,27 @@ +export module tk { + // TODO: this should be properly organized + export module utils { + export class Collections { + public static jsArrayToNSArray(str: string[]): any { + var arr = new Foundation.NSMutableArray(); + if ("undefined" != typeof str) { + for (var element in str) { + arr.addObject(str[element]); + } + } + return arr; + } + + public static nsArrayToJSArray(a: any): string[] { + var arr = []; + if ("undefined" != typeof a) { + for (var i = 0; i < a.count(); i++) { + arr.push(a.objectAtIndex(i)); + } + } + + return arr; + } + } + } +} \ No newline at end of file diff --git a/WebClient/Readme.md b/WebClient/Readme.md new file mode 100644 index 000000000..6da412a82 --- /dev/null +++ b/WebClient/Readme.md @@ -0,0 +1,25 @@ +Sample code: +``` +var web_module = require("web_client"); +var image_module = require("image"); + +var client = new web_module.tk.web.Client(); +client.downloadString("http://www.reddit.com/r/aww.json?limit=10", + function(result) { + Log("Result:" + result); + }, + function(e) { + Log("Error:" + e.message); + }); +``` + +``` + +var client = new web_module.tk.web.Client(); +client.downloadImage("http://www.telerik.com/sfimages/default-source/Homepage/hp_any_approachf6e4079a7a99493a8ab2e367b9cb3f7d.png", + function(image){ // This is image_module.tk.ui.Image + }, + function(e) { + Log("Error:" + e.message); + }); +``` \ No newline at end of file diff --git a/WebClient/web_client.android.ts b/WebClient/web_client.android.ts new file mode 100644 index 000000000..59e7e548f --- /dev/null +++ b/WebClient/web_client.android.ts @@ -0,0 +1,48 @@ +import image_module = require("Image/image"); + +export module tk { + export module web { + /** + * Android specific WebClient implementation. + */ + export class Client { + /** + * Downloads string from url. + */ + public downloadString(url: string, successCallback: (result: string) => void, errorCallback?: (e: Error) => void) { + try { + if (successCallback) { + var httpClient = new org.apache.http.impl.client.DefaultHttpClient(); + var httpGet = new org.apache.http.client.methods.HttpGet(url); + var responseHandler = new org.apache.http.impl.client.BasicResponseHandler(); + var responseBody = httpClient.execute(httpGet, responseHandler); + + successCallback(responseBody); + } + } catch (ex) { + + if (errorCallback) { + errorCallback(ex); + } + + } + } + + public downloadImage(url: string, successCallback: (image: image_module.tk.ui.Image) => void, errorCallback?: (e: Error) => void) { + try { + if (successCallback) { + var image = new image_module.tk.ui.Image(); + image.loadFromData(new java.net.URL(url).getContent()); + successCallback(image); + } + } catch (ex) { + + if (errorCallback) { + errorCallback(ex); + } + + } + } + } + } +} \ No newline at end of file diff --git a/WebClient/web_client.d.ts b/WebClient/web_client.d.ts new file mode 100644 index 000000000..c5a301851 --- /dev/null +++ b/WebClient/web_client.d.ts @@ -0,0 +1,15 @@ +import image_module = require("Image/image"); +/** + * Web (WebClient) module. + */ +export declare module tk { + export module web { + /** + * The Client interface. + */ + export class Client { + downloadString(url: string, successCallback: (result: string) => void, errorCallback?: (e: Error) => void) + downloadImage(url: string, successCallback: (image: image_module.tk.ui.Image) => void, errorCallback?: (e: Error) => void) + } + } +} \ No newline at end of file diff --git a/WebClient/web_client.ios.ts b/WebClient/web_client.ios.ts new file mode 100644 index 000000000..e307cdb54 --- /dev/null +++ b/WebClient/web_client.ios.ts @@ -0,0 +1,40 @@ +import image_module = require("Image/image"); +// TODO: Not implemented for iOS + +export module tk { + export module web { + /** + * iOS specific WebClient implementation. + */ + export class Client { + /** + * Downloads string from url. + */ + public downloadString(url: string, successCallback: (result: string) => void, errorCallback?: (e: Error) => void) { + try { + if (successCallback) { + // successCallback(result); + } + } catch (ex) { + + if (errorCallback) { + errorCallback(ex); + } + } + } + + public downloadImage(url: string, successCallback: (image: image_module.tk.ui.Image) => void, errorCallback?: (e: Error) => void) { + try { + if (successCallback) { + // successCallback(response); + } + } catch (ex) { + + if (errorCallback) { + errorCallback(ex); + } + } + } + } + } +} \ No newline at end of file diff --git a/declarations.android.d.ts b/declarations.android.d.ts new file mode 100644 index 000000000..9d56a3650 --- /dev/null +++ b/declarations.android.d.ts @@ -0,0 +1,331 @@ + +// Android specific TypeScript declarations +// TODO: This is temporary, until we have the TS definitions for the native APIs + +declare module org { + export module json { + export class JSONArray { + constructor(json: string); + length: number; + } + } +} + +declare module android { + export module app { + export module Application { + export class ActivityLifecycleCallbacks { + constructor(override: any); + + onActivityCreated: (activity: any, bundle: any) => any; + onActivityDestroyed: (activity: any) => any; + onActivityPaused: (activity: any) => any; + onActivityResumed: (activity: any) => any; + onActivitySaveInstanceState: (activity: any, bundle: any) => any; + onActivityStarted: (activity: any) => any; + onActivityStopped: (activity: any) => any; + } + } + } + export module location { + export class Location { + } + + export class LocationListener { + constructor(overrides: any); + onLocationChanged(location: Location); + onProviderDisabled(provider: string); + onProviderEnabled(provider: string); + } + + export class Criteria { + setAccuracy(accuracy: number); + } + } + + export module hardware { + export module Camera { + export class Parameters { + } + } + + export class Camera { + public static open(camera: number): Camera; + + public getParameters(): Camera.Parameters; + public setPreviewDisplay(surfaceHolder: android.view.SurfaceHolder); + + public startPreview(); + public stopPreview(); + public release(); + } + } + + export module view { + export class SurfaceHolder { + } + } + + export module content { + export class Intent { + static FLAG_ACTIVITY_NEW_TASK: any; + static ACTION_MAIN: any; + static createChooser(target: Intent, title: string): Intent; + + constructor(); + constructor(action: string); + constructor(obj: any, klass: any); + resolveActivity(pm: any): any; + setType(type: string): Intent; + setAction(action: string): Intent; + setFlags(num: number); + } + } + + export module app { + export class Activity { + } + } + + export module graphics { + export class BitmapFactory { + static decodeStream(s: any): any; + static decodeFile(pathName: string, options: any): any; + static decodeResource(res: any, identifier: number): any; + } + + export module Bitmap { + export enum CompressFormat { + JPEG, + PNG, + WEBP, + } + } + } + + export module os { + export class Environment { + static getExternalStorageDirectory(): java.io.File; + } + } +} + +declare module java { + export module io { + export interface OutputStream { + close(); + flush(); + } + + export interface InputStream { + } + + export class File { + constructor(path: string); + exists(): boolean; + length(): number; + isFile(): boolean; + isDirectory(): boolean; + getPath(): string; + getName(): string; + getParentFile(): File; + lastModified(): number; + canWrite(): boolean; + createNewFile(): boolean; + delete(): boolean; + listFiles(): Array; + getAbsolutePath(): string; + } + + export class FileOutputStream implements OutputStream { + constructor(file: File); + constructor(path: string); + close(); + flush(); + } + export class FileInputStream implements InputStream { + constructor(file: File); + } + export class OutputStreamWriter { + constructor(stream: FileOutputStream, encoding: string); + } + + export class InputStreamReader { + constructor(stream: FileInputStream, encoding: string); + } + + export class BufferedReader { + constructor(reader: InputStreamReader); + public readLine(): string; + public close(); + public flush(); + } + + export class BufferedWriter { + constructor(writer: OutputStreamWriter); + public write(text: string); + public close(); + public flush(); + } + + export class BufferedOutputStream implements OutputStream { + constructor(out: OutputStream); + close(); + flush(); + } + + export class ByteArrayOutputStream { + public write(data: java.util.ArrayList, pos: number, count: number); + public flush(); + public close(); + public toByteArray(); + } + } + export module nio { + export class CharBuffer { + public static allocate(capacity: number): CharBuffer; + } + } + + export module util { + export class HashSet { + add(obj: any); + } + } + + export module lang { + export class Float { + constructor(strNum: string); + floatValue(): any; + } + } + +} + +declare module android { + export module database { + export module sqlite { + export class SQLiteDatabase { + public static openOrCreateDatabase(path: string, factory: any): SQLiteDatabase; + public rawQuery(sqlStatement: string, arguments: Array): any; + public execSQL(sqlStatement: string); + } + } + } +} + +declare module org { + export module apache { + export module http { + export module impl { + export module client { + + export class DefaultHttpClient { + public execute(request: org.apache.http.client.methods.HttpUriRequest, responseHandler: org.apache.http.client.ResponseHandler); + } + + export class BasicResponseHandler { + + } + } + } + } + } +} + +declare module org { + export module apache { + export module http { + export module client { + export class ResponseHandler { + + } + } + } + } +} + +declare module org { + export module apache { + export module http { + export module client { + export module methods { + + export class HttpUriRequest { + constructor(uri: string); + } + + export class HttpGet { + constructor(uri: string); + } + } + } + } + } +} + +declare module java { + export module net { + + export class URL { + constructor(uri: string); + public getContent(): java.io.InputStream; + public openConnection(): java.net.URLConnection; + } + + export class URLConnection { + public getInputStream(): java.io.InputStream; + } + } +} + +declare module java { + export module util { + export class ArrayList { + constructor(capacity: number); + } + } +} + +declare module java { + export module lang { + export class String { + constructor(source: string); + getBytes(): Array; + getBytes(encoding: string): Array; + } + } +} + +declare module android { + export module util { + export class Base64 { + static encodeToString(bytes: Array, flags: number): string; + } + } +} + + +declare module android { + export module widget { + export class ImageView { + constructor(context: any); + setImageBitmap(bitmap: any); + } + export class TextView { + constructor(context: any); + setText(text: string); + } + export class ListView { + constructor(context: any); + setAdapter(a: any); + getAdapter(): any; + } + export class BaseAdapter { + constructor(source: any); + } + } +} + +declare var app; +declare var telerik; \ No newline at end of file diff --git a/declarations.d.ts b/declarations.d.ts new file mode 100644 index 000000000..4a78d1248 --- /dev/null +++ b/declarations.d.ts @@ -0,0 +1,9 @@ +// Global functions +declare function Log(data: any): void; +declare function log(data: any): void; +declare function float(num: number): any; +declare function long(num: number): any; +declare function fail(data: any): void; + +// TODO: Declaration for the missing asynchronous API +declare function runAsync(operation: () => any, onComplete?: () => any); \ No newline at end of file diff --git a/declarations.ios.d.ts b/declarations.ios.d.ts new file mode 100644 index 000000000..1a5eb69d4 --- /dev/null +++ b/declarations.ios.d.ts @@ -0,0 +1,61 @@ + +// iOS specific TypeScript declarations +// TODO: This is temporary, until we have the TS definitions for the native APIs + +declare module UIKit { + + export class UIResponder { + static extends(param1: any, param2: any): any; + } + + export class UIWindow { + constructor(frame: any); + } + + export class UIScreen { + static mainScreen(): any; + } + + export class UIColor { + static whiteColor: any; + } + + export class UINavigationController { + constructor(rootController: any); + } + + export class UIImageView { + constructor(); + setImage(image: any); + } + + export class UILabel { + constructor(); + setText(text: string); + sizeToFit(); + } + + export class UIImage { + static imageNamed(name: string): UIImage; + static imageWithContentsOfFile(path: string): UIImage; + static imageWithData(data: any): UIImage; + } + + function UIImagePNGRepresentation(image: UIImage); + function UIImageJPEGRepresentation(image: UIImage, compressionQuality: number); +} + +declare module Foundation { + export class NSUserDefaults { + static standardUserDefaults(): any; + } + + export class NSMutableArray { + addObject(obj: any); + } + + export class NSFileManager { + static defaultManager(): NSFileManager; + URLsForDirectoryInDomains(directory: number, mask: number): any; + } +}