Fixed most module cyclic references. There is one left for ios and android: (#4978)

- http -> http-request -> image-source
that can't be fixed easily and will be removed once we delete image-source module because it is obsolete anyway.
There is one more for android:
- frame -> fragment that could be removed if we use global object.
Updated madge bersion
This commit is contained in:
Hristo Hristov
2017-11-10 15:47:02 +02:00
committed by GitHub
parent 729b068e7b
commit 43fbabb5e9
19 changed files with 227 additions and 236 deletions

View File

@ -27,7 +27,7 @@
"grunt-ts": "6.0.0-beta.11", "grunt-ts": "6.0.0-beta.11",
"grunt-typedoc": "0.2.4", "grunt-typedoc": "0.2.4",
"http-server": "^0.9.0", "http-server": "^0.9.0",
"madge": "^2.0.0", "madge": "^2.2.0",
"markdown-snippet-injector": "0.2.2", "markdown-snippet-injector": "0.2.2",
"mocha": "^3.5.0", "mocha": "^3.5.0",
"mocha-typescript": "^1.1.9", "mocha-typescript": "^1.1.9",
@ -80,6 +80,8 @@
"test-tsc-es2016": "npm run tsc -- -p tsconfig.public.es2016.json", "test-tsc-es2016": "npm run tsc -- -p tsconfig.public.es2016.json",
"tslint": "tslint --config build/tslint.json 'tns-core-modules/**/*.ts' 'tests/**/*.ts' 'apps/**/*.ts' -e '**/node_modules/**' -e '**/platforms/**'", "tslint": "tslint --config build/tslint.json 'tns-core-modules/**/*.ts' 'tests/**/*.ts' 'apps/**/*.ts' -e '**/node_modules/**' -e '**/platforms/**'",
"madge-ios": "tsc --skipLibCheck && tns prepare ios --path tests && madge --circular tests/platforms/ios/tests/app/tns_modules/tns-core-modules", "madge-ios": "tsc --skipLibCheck && tns prepare ios --path tests && madge --circular tests/platforms/ios/tests/app/tns_modules/tns-core-modules",
"madge-android": "tsc --skipLibCheck && tns prepare android --path tests && madge --circular tests/platforms/android/src/main/assets/app/tns_modules/tns-core-modules" "madge-ios-image": "tsc --skipLibCheck && tns prepare ios --path tests && madge --image graph-tests-ios.svg tests/platforms/ios/tests/app/tns_modules/tns-core-modules",
"madge-android": "tsc --skipLibCheck && tns prepare android --path tests && madge --circular tests/platforms/android/src/main/assets/app/tns_modules/tns-core-modules",
"madge-android-image": "tsc --skipLibCheck && tns prepare android --path tests && madge --image graph-tests-android.svg tests/platforms/android/src/main/assets/app/tns_modules/tns-core-modules"
} }
} }

View File

@ -19,6 +19,8 @@ export { Observable };
import { UnhandledErrorEventData, iOSApplication, AndroidApplication, CssChangedEventData, LoadAppCSSEventData } from "."; import { UnhandledErrorEventData, iOSApplication, AndroidApplication, CssChangedEventData, LoadAppCSSEventData } from ".";
export { UnhandledErrorEventData, CssChangedEventData, LoadAppCSSEventData };
export const launchEvent = "launch"; export const launchEvent = "launch";
export const suspendEvent = "suspend"; export const suspendEvent = "suspend";
export const displayedEvent = "displayed"; export const displayedEvent = "displayed";
@ -54,7 +56,11 @@ export function setApplication(instance: iOSApplication | AndroidApplication): v
} }
export function livesync() { export function livesync() {
events.notify(<EventData>{ eventName: "livesync", object: app }); events.notify(<EventData>{ eventName: "livesync", object: app });
const liveSyncCore = global.__onLiveSyncCore;
if (liveSyncCore) {
liveSyncCore();
}
} }
export function setCssFileName(cssFileName: string) { export function setCssFileName(cssFileName: string) {
@ -76,4 +82,4 @@ export function addCss(cssText: string): void {
global.__onUncaughtError = function (error: NativeScriptError) { global.__onUncaughtError = function (error: NativeScriptError) {
events.notify(<UnhandledErrorEventData>{ eventName: uncaughtErrorEvent, object: app, android: error, ios: error, error: error }); events.notify(<UnhandledErrorEventData>{ eventName: uncaughtErrorEvent, object: app, android: error, ios: error, error: error });
} }

View File

@ -2,7 +2,7 @@ import { PlatformContext, FileNameResolver as FileNameResolverDefinition } from
import { screen, device } from "../../platform"; import { screen, device } from "../../platform";
import { path as fsPath, Folder, File } from "../file-system"; import { path as fsPath, Folder, File } from "../file-system";
import * as trace from "../../trace"; import * as trace from "../../trace";
import * as appModule from "../../application"; import * as appCommonModule from "../../application/application-common";
const MIN_WH: string = "minWH"; const MIN_WH: string = "minWH";
const MIN_W: string = "minW"; const MIN_W: string = "minW";
@ -234,5 +234,5 @@ export function resolveFileName(path: string, ext: string): string {
return resolverInstance.resolveFileName(path, ext); return resolverInstance.resolveFileName(path, ext);
} }
appModule.on("cssChanged", args => resolverInstance = undefined); appCommonModule.on("cssChanged", args => resolverInstance = undefined);
appModule.on("livesync", args => resolverInstance && resolverInstance.clearCache()); appCommonModule.on("livesync", args => resolverInstance && resolverInstance.clearCache());

View File

@ -1,15 +1,13 @@
import * as textModule from "../text"; import { encoding as textEncoding } from "../text";
import * as utilsModule from "../utils/utils"; import { ios } from "../utils/utils";
import * as utils from "../utils/utils";
// TODO: Implement all the APIs receiving callback using async blocks // TODO: Implement all the APIs receiving callback using async blocks
// TODO: Check whether we need try/catch blocks for the iOS implementation // TODO: Check whether we need try/catch blocks for the iOS implementation
export class FileSystemAccess { export class FileSystemAccess {
public getLastModified(path: string): Date { public getLastModified(path: string): Date {
var fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); const fileManager = ios.getter(NSFileManager, NSFileManager.defaultManager);
var attributes = fileManager.attributesOfItemAtPathError(path); const attributes = fileManager.attributesOfItemAtPathError(path);
if (attributes) { if (attributes) {
return attributes.objectForKey("NSFileModificationDate"); return attributes.objectForKey("NSFileModificationDate");
@ -20,18 +18,17 @@ export class FileSystemAccess {
public getParent(path: string, onError?: (error: any) => any): { path: string; name: string } { public getParent(path: string, onError?: (error: any) => any): { path: string; name: string } {
try { try {
var fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); const fileManager = ios.getter(NSFileManager, NSFileManager.defaultManager);
var nsString = NSString.stringWithString(path); const nsString = NSString.stringWithString(path);
var parentPath = nsString.stringByDeletingLastPathComponent; const parentPath = nsString.stringByDeletingLastPathComponent;
var name = fileManager.displayNameAtPath(parentPath); const name = fileManager.displayNameAtPath(parentPath);
return { return {
path: parentPath.toString(), path: parentPath.toString(),
name: name name: name
}; };
} } catch (exception) {
catch (exception) {
if (onError) { if (onError) {
onError(exception); onError(exception);
} }
@ -42,13 +39,13 @@ export class FileSystemAccess {
public getFile(path: string, onError?: (error: any) => any): { path: string; name: string; extension: string } { public getFile(path: string, onError?: (error: any) => any): { path: string; name: string; extension: string } {
try { try {
var fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); const fileManager = ios.getter(NSFileManager, NSFileManager.defaultManager);
var exists = fileManager.fileExistsAtPath(path); const exists = fileManager.fileExistsAtPath(path);
if (!exists) { if (!exists) {
var parentPath = this.getParent(path, onError).path; const parentPath = this.getParent(path, onError).path;
if (!fileManager.createDirectoryAtPathWithIntermediateDirectoriesAttributesError(parentPath, true, null) || if (!fileManager.createDirectoryAtPathWithIntermediateDirectoriesAttributesError(parentPath, true, null)
!fileManager.createFileAtPathContentsAttributes(path, null, null)) { || !fileManager.createFileAtPathContentsAttributes(path, null, null)) {
if (onError) { if (onError) {
onError(new Error("Failed to create file at path '" + path + "'")); onError(new Error("Failed to create file at path '" + path + "'"));
} }
@ -56,15 +53,14 @@ export class FileSystemAccess {
} }
} }
var fileName = fileManager.displayNameAtPath(path); const fileName = fileManager.displayNameAtPath(path);
return { return {
path: path, path: path,
name: fileName, name: fileName,
extension: this.getFileExtension(path) extension: this.getFileExtension(path)
}; };
} } catch (exception) {
catch (exception) {
if (onError) { if (onError) {
onError(exception); onError(exception);
} }
@ -75,8 +71,8 @@ export class FileSystemAccess {
public getFolder(path: string, onError?: (error: any) => any): { path: string; name: string } { public getFolder(path: string, onError?: (error: any) => any): { path: string; name: string } {
try { try {
var fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); const fileManager = ios.getter(NSFileManager, NSFileManager.defaultManager);
var exists = this.folderExists(path); const exists = this.folderExists(path);
if (!exists) { if (!exists) {
try { try {
@ -91,14 +87,13 @@ export class FileSystemAccess {
} }
} }
var dirName = fileManager.displayNameAtPath(path); const dirName = fileManager.displayNameAtPath(path);
return { return {
path: path, path: path,
name: dirName name: dirName
}; };
} } catch (ex) {
catch (ex) {
if (onError) { if (onError) {
onError(new Error("Failed to create folder at path '" + path + "'")); onError(new Error("Failed to create folder at path '" + path + "'"));
} }
@ -107,29 +102,27 @@ export class FileSystemAccess {
} }
} }
public getExistingFolder(path: string, onError?: (error: any) => any): { path: string; name: string } { public getExistingFolder(path: string, onError?: (error: any) => any): { path: string; name: string } {
try { try {
var fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); const fileManager = ios.getter(NSFileManager, NSFileManager.defaultManager);
var exists = this.folderExists(path); const exists = this.folderExists(path);
if (exists) { if (exists) {
var dirName = fileManager.displayNameAtPath(path); const dirName = fileManager.displayNameAtPath(path);
return { return {
path: path, path: path,
name: dirName name: dirName
}; };
} }
return undefined; return undefined;
} } catch (ex) {
catch (ex) {
if (onError) { if (onError) {
onError(new Error("Failed to get folder at path '" + path + "'")); onError(new Error("Failed to get folder at path '" + path + "'"));
} }
return undefined; return undefined;
} }
} }
public eachEntity(path: string, onEntity: (file: { path: string; name: string; extension: string }) => any, onError?: (error: any) => any) { public eachEntity(path: string, onEntity: (file: { path: string; name: string; extension: string }) => any, onError?: (error: any) => any) {
if (!onEntity) { if (!onEntity) {
@ -140,15 +133,15 @@ export class FileSystemAccess {
} }
public getEntities(path: string, onError?: (error: any) => any): Array<{ path: string; name: string; extension: string }> { 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 }>(); const fileInfos = new Array<{ path: string; name: string; extension: string }>();
var onEntity = function (entity: { path: string; name: string; extension: string }): boolean { const onEntity = function (entity: { path: string; name: string; extension: string }): boolean {
fileInfos.push(entity); fileInfos.push(entity);
return true; return true;
} }
var errorOccurred; let errorOccurred;
var localError = function (error: any) { const localError = function (error: any) {
if (onError) { if (onError) {
onError(error); onError(error);
} }
@ -166,31 +159,25 @@ export class FileSystemAccess {
} }
public fileExists(path: string): boolean { public fileExists(path: string): boolean {
var result = this.exists(path); const result = this.exists(path);
return result.exists; return result.exists;
} }
public folderExists(path: string): boolean { public folderExists(path: string): boolean {
var result = this.exists(path); const result = this.exists(path);
return result.exists && result.isDirectory; return result.exists && result.isDirectory;
} }
private exists(path: string): { exists: boolean, isDirectory: boolean } { private exists(path: string): { exists: boolean, isDirectory: boolean } {
var fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); const fileManager = ios.getter(NSFileManager, NSFileManager.defaultManager);
var isDirectory = new interop.Reference(interop.types.bool, false); const isDirectory = new interop.Reference(interop.types.bool, false);
var exists = fileManager.fileExistsAtPathIsDirectory(path, isDirectory); const exists = fileManager.fileExistsAtPathIsDirectory(path, isDirectory);
return { exists: exists, isDirectory: isDirectory.value }; return { exists: exists, isDirectory: isDirectory.value };
} }
public concatPath(left: string, right: string): string { public concatPath(left: string, right: string): string {
var utils: typeof utilsModule = require("utils/utils"); return NSString.pathWithComponents(<any>[left, right]).toString();
// TODO: This probably is not efficient, we may try concatenation with the "/" character
var nsArray = utils.ios.collections.jsArrayToNSArray([left, right]);
var nsString = NSString.pathWithComponents(nsArray);
return nsString.toString();
} }
public deleteFile(path: string, onError?: (error: any) => any) { public deleteFile(path: string, onError?: (error: any) => any) {
@ -202,15 +189,14 @@ export class FileSystemAccess {
} }
public emptyFolder(path: string, onError?: (error: any) => any) { public emptyFolder(path: string, onError?: (error: any) => any) {
var fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); const fileManager = ios.getter(NSFileManager, NSFileManager.defaultManager);
var entities = this.getEntities(path, onError); const entities = this.getEntities(path, onError);
if (!entities) { if (!entities) {
return; return;
} }
var i; for (let i = 0; i < entities.length; i++) {
for (i = 0; i < entities.length; i++) {
try { try {
fileManager.removeItemAtPathError(entities[i].path); fileManager.removeItemAtPathError(entities[i].path);
} }
@ -225,12 +211,11 @@ export class FileSystemAccess {
} }
public rename(path: string, newPath: string, onError?: (error: any) => any) { public rename(path: string, newPath: string, onError?: (error: any) => any) {
var fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); const fileManager = ios.getter(NSFileManager, NSFileManager.defaultManager);
try { try {
fileManager.moveItemAtPathToPathError(path, newPath); fileManager.moveItemAtPathToPathError(path, newPath);
} } catch (ex) {
catch (ex) {
if (onError) { if (onError) {
onError(new Error("Failed to rename '" + path + "' to '" + newPath + "': " + ex)); onError(new Error("Failed to rename '" + path + "' to '" + newPath + "': " + ex));
} }
@ -238,8 +223,8 @@ export class FileSystemAccess {
} }
public getLogicalRootPath(): string { public getLogicalRootPath(): string {
let mainBundlePath = utils.ios.getter(NSBundle, NSBundle.mainBundle).bundlePath; const mainBundlePath = ios.getter(NSBundle, NSBundle.mainBundle).bundlePath;
let resolvedPath = NSString.stringWithString(mainBundlePath).stringByResolvingSymlinksInPath; const resolvedPath = NSString.stringWithString(mainBundlePath).stringByResolvingSymlinksInPath;
return resolvedPath; return resolvedPath;
} }
@ -250,32 +235,18 @@ export class FileSystemAccess {
public getTempFolderPath(): string { public getTempFolderPath(): string {
return this.getKnownPath(NSSearchPathDirectory.CachesDirectory); return this.getKnownPath(NSSearchPathDirectory.CachesDirectory);
} }
public getCurrentAppPath(): string {
const currentDir = __dirname;
const tnsModulesIndex = currentDir.indexOf("/tns_modules");
// Module not hosted in ~/tns_modules when bundled. Use current dir. public getCurrentAppPath(): string {
let appPath = currentDir; return ios.getCurrentAppPath();
if (tnsModulesIndex !== -1) {
// Strip part after tns_modules to obtain app root
appPath = currentDir.substring(0, tnsModulesIndex);
}
return appPath;
} }
public readText(path: string, onError?: (error: any) => any, encoding?: any) { public readText(path: string, onError?: (error: any) => any, encoding?: any) {
var actualEncoding = encoding; const actualEncoding = encoding || textEncoding.UTF_8;
if (!actualEncoding) {
actualEncoding = textModule.encoding.UTF_8;
}
try { try {
var nsString = NSString.stringWithContentsOfFileEncodingError(path, actualEncoding); const nsString = NSString.stringWithContentsOfFileEncodingError(path, actualEncoding);
return nsString.toString(); return nsString.toString();
} } catch (ex) {
catch (ex) {
if (onError) { if (onError) {
onError(new Error("Failed to read file at path '" + path + "': " + ex)); onError(new Error("Failed to read file at path '" + path + "': " + ex));
} }
@ -285,8 +256,7 @@ export class FileSystemAccess {
public read(path: string, onError?: (error: any) => any): NSData { public read(path: string, onError?: (error: any) => any): NSData {
try { try {
return NSData.dataWithContentsOfFile(path); return NSData.dataWithContentsOfFile(path);
} } catch (ex) {
catch (ex) {
if (onError) { if (onError) {
onError(new Error("Failed to read file at path '" + path + "': " + ex)); onError(new Error("Failed to read file at path '" + path + "': " + ex));
} }
@ -294,18 +264,14 @@ export class FileSystemAccess {
} }
public writeText(path: string, content: string, onError?: (error: any) => any, encoding?: any) { public writeText(path: string, content: string, onError?: (error: any) => any, encoding?: any) {
var nsString = NSString.stringWithString(content); const nsString = NSString.stringWithString(content);
var actualEncoding = encoding; const actualEncoding = encoding || textEncoding.UTF_8;
if (!actualEncoding) {
actualEncoding = textModule.encoding.UTF_8;
}
// TODO: verify the useAuxiliaryFile parameter should be false // TODO: verify the useAuxiliaryFile parameter should be false
try { try {
nsString.writeToFileAtomicallyEncodingError(path, false, actualEncoding); nsString.writeToFileAtomicallyEncodingError(path, false, actualEncoding);
} } catch (ex) {
catch (ex) {
if (onError) { if (onError) {
onError(new Error("Failed to write to file '" + path + "': " + ex)); onError(new Error("Failed to write to file '" + path + "': " + ex));
} }
@ -315,8 +281,7 @@ export class FileSystemAccess {
public write(path: string, content: NSData, onError?: (error: any) => any) { public write(path: string, content: NSData, onError?: (error: any) => any) {
try { try {
content.writeToFileAtomically(path, true); content.writeToFileAtomically(path, true);
} } catch (ex) {
catch (ex) {
if (onError) { if (onError) {
onError(new Error("Failed to write to file '" + path + "': " + ex)); onError(new Error("Failed to write to file '" + path + "': " + ex));
} }
@ -324,10 +289,10 @@ export class FileSystemAccess {
} }
private getKnownPath(folderType: number): string { private getKnownPath(folderType: number): string {
var fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); const fileManager = ios.getter(NSFileManager, NSFileManager.defaultManager);
var paths = fileManager.URLsForDirectoryInDomains(folderType, NSSearchPathDomainMask.UserDomainMask); const paths = fileManager.URLsForDirectoryInDomains(folderType, NSSearchPathDomainMask.UserDomainMask);
var url = paths.objectAtIndex(0); const url = paths.objectAtIndex(0);
return url.path; return url.path;
} }
@ -335,15 +300,15 @@ export class FileSystemAccess {
// Make it in a separate file / module so it can be reused from both implementations. // Make it in a separate file / module so it can be reused from both implementations.
private getFileExtension(path: string): string { private getFileExtension(path: string): string {
// TODO [For Panata]: The definitions currently specify "any" as a return value of this method // TODO [For Panata]: The definitions currently specify "any" as a return value of this method
//var nsString = Foundation.NSString.stringWithString(path); //const nsString = Foundation.NSString.stringWithString(path);
//var extension = nsString.pathExtension(); //const extension = nsString.pathExtension();
//if (extension && extension.length > 0) { //if (extension && extension.length > 0) {
// extension = extension.concat(".", extension); // extension = extension.concat(".", extension);
//} //}
//return extension; //return extension;
var dotIndex = path.lastIndexOf("."); const dotIndex = path.lastIndexOf(".");
if (dotIndex && dotIndex >= 0 && dotIndex < path.length) { if (dotIndex && dotIndex >= 0 && dotIndex < path.length) {
return path.substring(dotIndex); return path.substring(dotIndex);
} }
@ -352,11 +317,10 @@ export class FileSystemAccess {
} }
private deleteEntity(path: string, onError?: (error: any) => any) { private deleteEntity(path: string, onError?: (error: any) => any) {
var fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); const fileManager = ios.getter(NSFileManager, NSFileManager.defaultManager);
try { try {
fileManager.removeItemAtPathError(path); fileManager.removeItemAtPathError(path);
} } catch (ex) {
catch (ex) {
if (onError) { if (onError) {
onError(new Error("Failed to delete file at path '" + path + "': " + ex)); onError(new Error("Failed to delete file at path '" + path + "': " + ex));
} }
@ -365,11 +329,11 @@ export class FileSystemAccess {
private enumEntities(path: string, callback: (entity: { path: string; name: string; extension: string }) => boolean, onError?: (error) => any) { private enumEntities(path: string, callback: (entity: { path: string; name: string; extension: string }) => boolean, onError?: (error) => any) {
try { try {
var fileManager = utils.ios.getter(NSFileManager, NSFileManager.defaultManager); const fileManager = ios.getter(NSFileManager, NSFileManager.defaultManager);
let files: NSArray<string>;
try { try {
var files = fileManager.contentsOfDirectoryAtPathError(path); files = fileManager.contentsOfDirectoryAtPathError(path);
} } catch (ex) {
catch (ex) {
if (onError) { if (onError) {
onError(new Error("Failed to enum files for folder '" + path + "': " + ex)); onError(new Error("Failed to enum files for folder '" + path + "': " + ex));
} }
@ -377,31 +341,26 @@ export class FileSystemAccess {
return; return;
} }
var file; for (let i = 0; i < files.count; i++) {
var i; const file = files.objectAtIndex(i);
var info;
var retVal;
for (i = 0; i < files.count; i++) { const info = {
file = files.objectAtIndex(i);
info = {
path: this.concatPath(path, file), path: this.concatPath(path, file),
name: file name: file,
extension: ''
}; };
if (!this.folderExists(this.joinPath(path, file))) { if (!this.folderExists(this.joinPath(path, file))) {
info.extension = this.getFileExtension(info.path); info.extension = this.getFileExtension(info.path);
} }
retVal = callback(info); const retVal = callback(info);
if (retVal === false) { if (retVal === false) {
// the callback returned false meaning we should stop the iteration // the callback returned false meaning we should stop the iteration
break; break;
} }
} }
} } catch (ex) {
catch (ex) {
if (onError) { if (onError) {
onError(ex); onError(ex);
} }
@ -413,30 +372,18 @@ export class FileSystemAccess {
} }
public normalizePath(path: string): string { public normalizePath(path: string): string {
var nsString: NSString = NSString.stringWithString(path); const nsString: NSString = NSString.stringWithString(path);
var normalized = nsString.stringByStandardizingPath; const normalized = nsString.stringByStandardizingPath;
return normalized; return normalized;
} }
public joinPath(left: string, right: string): string { public joinPath(left: string, right: string): string {
var nsString: NSString = NSString.stringWithString(left); const nsString: NSString = NSString.stringWithString(left);
return nsString.stringByAppendingPathComponent(right); return nsString.stringByAppendingPathComponent(right);
} }
public joinPaths(paths: string[]): string { public joinPaths(paths: string[]): string {
if (!paths || paths.length === 0) { return ios.joinPaths(...paths);
return "";
}
var nsArray = NSMutableArray.alloc<string>().initWithCapacity(paths.length);
var i;
for (i = 0; i < paths.length; i++) {
nsArray.addObject(paths[i]);
}
var nsString = NSString.stringWithString(NSString.pathWithComponents(nsArray));
return nsString.stringByStandardizingPath;
} }
} }

View File

@ -1,4 +1,4 @@
import * as image from "../image-source"; import { ImageSource } from "../image-source";
import * as httpRequest from "./http-request"; import * as httpRequest from "./http-request";
global.moduleMerge(httpRequest, exports); global.moduleMerge(httpRequest, exports);
@ -31,7 +31,7 @@ export function getJSON<T>(arg: any): Promise<T> {
}); });
} }
export function getImage(arg: any): Promise<image.ImageSource> { export function getImage(arg: any): Promise<ImageSource> {
return httpRequest return httpRequest
.request(typeof arg === "string" ? { url: arg, method: "GET" } : arg) .request(typeof arg === "string" ? { url: arg, method: "GET" } : arg)
.then(responce => responce.content.toImage()); .then(responce => responce.content.toImage());
@ -49,4 +49,4 @@ export function getFile(arg: any, destinationFilePath?: string): Promise<any> {
} }
}, e => reject(e)); }, e => reject(e));
}); });
} }

View File

@ -148,6 +148,7 @@ export function fromBase64(source: string): ImageSource;
export function fromNativeSource(source: any): ImageSource; export function fromNativeSource(source: any): ImageSource;
/** /**
* Deprecated. Use http.getImage(url: string) instead.
* Downloads the image from the provided Url and creates a new ImageSource instance from it. * Downloads the image from the provided Url and creates a new ImageSource instance from it.
* @param url The link to the remote image object. This operation will download and decode the image. * @param url The link to the remote image object. This operation will download and decode the image.
*/ */

View File

@ -38,6 +38,7 @@ declare namespace NodeJS {
__inspector?: any; __inspector?: any;
__extends: any; __extends: any;
__onLiveSync: () => void; __onLiveSync: () => void;
__onLiveSyncCore: () => void;
__onUncaughtError: (error: NativeScriptError) => void; __onUncaughtError: (error: NativeScriptError) => void;
TNS_WEBPACK?: boolean; TNS_WEBPACK?: boolean;
__requireOverride?: (name: string, dir: string) => any; __requireOverride?: (name: string, dir: string) => any;

View File

@ -9,7 +9,7 @@ import { escapeRegexSymbols } from "../../../utils/utils";
import { isEnabled as traceEnabled, write as traceWrite, categories as traceCategories, notifyEvent as traceNotifyEvent, isCategorySet, messageType as traceMessageType } from "../../../trace"; import { isEnabled as traceEnabled, write as traceWrite, categories as traceCategories, notifyEvent as traceNotifyEvent, isCategorySet, messageType as traceMessageType } from "../../../trace";
import * as types from "../../../utils/types"; import * as types from "../../../utils/types";
import * as application from "../../../application"; import * as applicationCommon from "../../../application/application-common";
import * as polymerExpressions from "../../../js-libs/polymer-expressions"; import * as polymerExpressions from "../../../js-libs/polymer-expressions";
export { export {
@ -357,7 +357,7 @@ export class Binding {
let context = this.source && this.source.get && this.source.get() || global; let context = this.source && this.source.get && this.source.get() || global;
let model = {}; let model = {};
let addedProps = []; let addedProps = [];
const resources = application.getResources(); const resources = applicationCommon.getResources();
for (let prop in resources) { for (let prop in resources) {
if (resources.hasOwnProperty(prop) && !context.hasOwnProperty(prop)) { if (resources.hasOwnProperty(prop) && !context.hasOwnProperty(prop)) {
context[prop] = resources[prop]; context[prop] = resources[prop];

View File

@ -6,13 +6,12 @@ import { Order, FlexGrow, FlexShrink, FlexWrapBefore, AlignSelf } from "../../la
import { KeyframeAnimation } from "../../animation/keyframe-animation"; import { KeyframeAnimation } from "../../animation/keyframe-animation";
// Types. // Types.
import { Source } from "../../../utils/debug";
import { Property, CssProperty, CssAnimationProperty, InheritedProperty, Style, clearInheritedProperties, propagateInheritableProperties, propagateInheritableCssProperties, resetCSSProperties, initNativeView, resetNativeView } from "../properties"; import { Property, CssProperty, CssAnimationProperty, InheritedProperty, Style, clearInheritedProperties, propagateInheritableProperties, propagateInheritableCssProperties, resetCSSProperties, initNativeView, resetNativeView } from "../properties";
import { Source } from "../../../utils/debug";
import { Binding, BindingOptions, Observable, WrappedValue, PropertyChangeData, traceEnabled, traceWrite, traceCategories, traceNotifyEvent } from "../bindable"; import { Binding, BindingOptions, Observable, WrappedValue, PropertyChangeData, traceEnabled, traceWrite, traceCategories, traceNotifyEvent } from "../bindable";
import { isIOS, isAndroid } from "../../../platform"; import { isIOS, isAndroid } from "../../../platform";
import { layout } from "../../../utils/utils"; import { layout } from "../../../utils/utils";
import { Length, paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty } from "../../styling/style-properties"; import { Length, paddingTopProperty, paddingRightProperty, paddingBottomProperty, paddingLeftProperty } from "../../styling/style-properties";
import { DOMNode } from "../../../debugger/dom-node";
// TODO: Remove this import! // TODO: Remove this import!
import * as types from "../../../utils/types"; import * as types from "../../../utils/types";
@ -27,6 +26,16 @@ export * from "../properties";
import * as ssm from "../../styling/style-scope"; import * as ssm from "../../styling/style-scope";
// import { DOMNode } from "../../../debugger/dom-node";
import * as dnm from "../../../debugger/dom-node";
let domNodeModule: typeof dnm;
function ensuredomNodeModule(): void {
if (!domNodeModule) {
domNodeModule = require("../../../debugger/dom-node");
}
}
let styleScopeModule: typeof ssm; let styleScopeModule: typeof ssm;
function ensureStyleScopeModule() { function ensureStyleScopeModule() {
if (!styleScopeModule) { if (!styleScopeModule) {
@ -142,7 +151,7 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
private _visualState: string; private _visualState: string;
private __nativeView: any; private __nativeView: any;
// private _disableNativeViewRecycling: boolean; // private _disableNativeViewRecycling: boolean;
public domNode: DOMNode; public domNode: dnm.DOMNode;
public recycleNativeView: "always" | "never" | "auto"; public recycleNativeView: "always" | "never" | "auto";
public bindingContext: any; public bindingContext: any;
@ -271,7 +280,8 @@ export abstract class ViewBase extends Observable implements ViewBaseDefinition
public ensureDomNode() { public ensureDomNode() {
if (!this.domNode) { if (!this.domNode) {
this.domNode = new DOMNode(this); ensuredomNodeModule();
this.domNode = new domNodeModule.DOMNode(this);
} }
} }

View File

@ -1,12 +1,13 @@
// Definitions. // Definitions.
import { View as ViewDefinition, Point, Size, Color, dip } from "."; import { View as ViewDefinition, Point, Size, Color, dip } from ".";
import { HorizontalAlignment, VerticalAlignment, Visibility, Length, PercentLength } from "../../styling/style-properties";
import { import {
ViewBase, Property, booleanConverter, EventData, layout, ViewBase, Property, booleanConverter, EventData, layout,
getEventOrGestureName, traceEnabled, traceWrite, traceCategories getEventOrGestureName, traceEnabled, traceWrite, traceCategories
} from "../view-base"; } from "../view-base";
import { HorizontalAlignment, VerticalAlignment, Visibility, Length, PercentLength } from "../../styling/style-properties";
import { import {
observe as gestureObserve, observe as gestureObserve,
GesturesObserver, GesturesObserver,
@ -807,4 +808,4 @@ export const isEnabledProperty = new Property<ViewCommon, boolean>({
isEnabledProperty.register(ViewCommon); isEnabledProperty.register(ViewCommon);
export const isUserInteractionEnabledProperty = new Property<ViewCommon, boolean>({ name: "isUserInteractionEnabled", defaultValue: true, valueConverter: booleanConverter }); export const isUserInteractionEnabledProperty = new Property<ViewCommon, boolean>({ name: "isUserInteractionEnabled", defaultValue: true, valueConverter: booleanConverter });
isUserInteractionEnabledProperty.register(ViewCommon); isUserInteractionEnabledProperty.register(ViewCommon);

View File

@ -1,11 +1,12 @@
// Definitions. // Definitions.
import { Point, View as ViewDefinition, dip } from "."; import { Point, View as ViewDefinition, dip } from ".";
import { ios, Background } from "../../styling/background";
import { import {
ViewCommon, layout, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty, ViewCommon, layout, isEnabledProperty, originXProperty, originYProperty, automationTextProperty, isUserInteractionEnabledProperty,
traceEnabled, traceWrite, traceCategories traceEnabled, traceWrite, traceCategories
} from "./view-common"; } from "./view-common";
import { ios, Background } from "../../styling/background";
import { import {
Visibility, Visibility,
visibilityProperty, opacityProperty, visibilityProperty, opacityProperty,

View File

@ -7,34 +7,10 @@ import { View, CustomLayoutView, isIOS, isAndroid, traceEnabled, traceWrite, tra
import { resolveFileName } from "../../file-system/file-name-resolver"; import { resolveFileName } from "../../file-system/file-name-resolver";
import { knownFolders, path } from "../../file-system"; import { knownFolders, path } from "../../file-system";
import { parse, loadPage } from "../builder"; import { parse, loadPage } from "../builder";
import * as application from "../../application";
import { profile } from "../../profiling"; import { profile } from "../../profiling";
export { application };
export * from "../core/view"; export * from "../core/view";
function onLivesync(args: EventData): void {
// give time to allow fileNameResolver & css to reload.
setTimeout(() => {
let g = <any>global;
// Close the error page if available and remove the reference from global context.
if (g.errorPage) {
g.errorPage.closeModal();
g.errorPage = undefined;
}
try {
g.__onLiveSyncCore();
} catch (ex) {
// Show the error as modal page, save reference to the page in global context.
g.errorPage = parse(`<Page><ScrollView><Label text="${ex}" textWrap="true" style="color: red;" /></ScrollView></Page>`);
g.errorPage.showModal();
}
});
}
application.on("livesync", onLivesync);
let frameStack: Array<FrameBase> = []; let frameStack: Array<FrameBase> = [];
function buildEntryFromArgs(arg: any): NavigationEntry { function buildEntryFromArgs(arg: any): NavigationEntry {
@ -626,4 +602,4 @@ export function goBack(): boolean {
export function stack(): Array<FrameBase> { export function stack(): Array<FrameBase> {
return frameStack; return frameStack;
} }

View File

@ -6,7 +6,8 @@ import {
import { Page } from "../page"; import { Page } from "../page";
// Types. // Types.
import { FrameBase, application, NavigationContext, stack, goBack, View, Observable, traceEnabled, traceWrite, traceCategories } from "./frame-common"; import * as application from "../../application";
import { FrameBase, NavigationContext, stack, goBack, View, Observable, traceEnabled, traceWrite, traceCategories } from "./frame-common";
import { DIALOG_FRAGMENT_TAG } from "../page/constants"; import { DIALOG_FRAGMENT_TAG } from "../page/constants";
import { import {
_setAndroidFragmentTransitions, _onFragmentCreateAnimator, _setAndroidFragmentTransitions, _onFragmentCreateAnimator,

View File

@ -4,7 +4,7 @@ import { Page } from "../page";
import { profile } from "../../profiling"; import { profile } from "../../profiling";
//Types. //Types.
import { FrameBase, View, application, layout, traceEnabled, traceWrite, traceCategories, isCategorySet } from "./frame-common"; import { FrameBase, View, topmost, layout, traceEnabled, traceWrite, traceCategories, isCategorySet } from "./frame-common";
import { _createIOSAnimatedTransitioning } from "./fragment.transitions"; import { _createIOSAnimatedTransitioning } from "./fragment.transitions";
// HACK: Webpack. Use a fully-qualified import to allow resolve.extensions(.ios.js) to // HACK: Webpack. Use a fully-qualified import to allow resolve.extensions(.ios.js) to
// kick in. `../utils` doesn't seem to trigger the webpack extensions mechanism. // kick in. `../utils` doesn't seem to trigger the webpack extensions mechanism.
@ -20,6 +20,39 @@ const DELEGATE = "_delegate";
let navDepth = -1; let navDepth = -1;
class NotificationObserver2 extends NSObject {
private _onReceiveCallback: (notification: NSNotification) => void;
public static initWithCallback(onReceiveCallback: (notification: NSNotification) => void): NotificationObserver2 {
const observer = <NotificationObserver2>super.new();
observer._onReceiveCallback = onReceiveCallback;
return observer;
}
public onReceive(notification: NSNotification): void {
this._onReceiveCallback(notification);
}
public static ObjCExposedMethods = {
"onReceive": { returns: interop.types.void, params: [NSNotification] }
};
}
const observer = NotificationObserver2.initWithCallback(handleNotification);
const notificationCenter = utils.ios.getter(NSNotificationCenter, NSNotificationCenter.defaultCenter);
notificationCenter.addObserverSelectorNameObject(observer, "onReceive", UIApplicationDidChangeStatusBarFrameNotification, null);
function handleNotification(notification: NSNotification): void {
// When there is a 40px high "in-call" status bar, nobody moves the navigationBar top from 20 to 40 and it remains underneath the status bar.
const frame = topmost() as Frame;
if (frame) {
frame._handleHigherInCallStatusBarIfNeeded();
if (frame.currentPage) {
frame.currentPage.requestLayout();
}
}
}
export class Frame extends FrameBase { export class Frame extends FrameBase {
private _ios: iOSFrame; private _ios: iOSFrame;
private _paramToNavigate: any; private _paramToNavigate: any;
@ -37,18 +70,6 @@ export class Frame extends FrameBase {
super(); super();
this._ios = new iOSFrame(this); this._ios = new iOSFrame(this);
this.nativeViewProtected = this._ios.controller.view; this.nativeViewProtected = this._ios.controller.view;
// When there is a 40px high "in-call" status bar, nobody moves the navigationBar top from 20 to 40 and it remains underneath the status bar.
let frameRef = new WeakRef(this);
application.ios.addNotificationObserver(UIApplicationDidChangeStatusBarFrameNotification, (notification: NSNotification) => {
let frame = frameRef.get();
if (frame) {
frame._handleHigherInCallStatusBarIfNeeded();
if (frame.currentPage) {
frame.currentPage.requestLayout();
}
}
});
} }
@profile @profile
@ -730,4 +751,4 @@ class iOSFrame implements iOSFrameDefinition {
public set navBarVisibility(value: "auto" | "never" | "always") { public set navBarVisibility(value: "auto" | "never" | "always") {
this._navBarVisibility = value; this._navBarVisibility = value;
} }
} }

View File

@ -1,4 +1,8 @@
// Types // Types
import { unsetValue, Style,
CssProperty, CssAnimationProperty,
ShorthandProperty, InheritedCssProperty,
makeValidator, makeParser } from "../core/properties";
import { import {
Transformation, Transformation,
TransformationValue, TransformationValue,
@ -9,15 +13,10 @@ import { dip, px, percent } from "../core/view";
import { Color } from "../../color"; import { Color } from "../../color";
import { Font, parseFont, FontStyle, FontWeight } from "../../ui/styling/font"; import { Font, parseFont, FontStyle, FontWeight } from "../../ui/styling/font";
import { layout } from "../../utils/utils"; import { layout, hasDuplicates } from "../../utils/utils";
import { Background } from "../../ui/styling/background"; import { Background } from "../../ui/styling/background";
import { isIOS } from "../../platform"; import { isIOS } from "../../platform";
import { Style } from "./style";
import { unsetValue, CssProperty, CssAnimationProperty, ShorthandProperty, InheritedCssProperty, makeValidator, makeParser } from "../core/properties";
import { hasDuplicates } from "../../utils/utils";
import { radiansToDegrees } from "../../utils/number-utils"; import { radiansToDegrees } from "../../utils/number-utils";
import { import {
@ -1038,4 +1037,4 @@ export const visibilityProperty = new CssProperty<Style, Visibility>({
target.view.isCollapsed = (newValue === Visibility.COLLAPSE); target.view.isCollapsed = (newValue === Visibility.COLLAPSE);
} }
}); });
visibilityProperty.register(Style); visibilityProperty.register(Style);

View File

@ -28,7 +28,7 @@ import {
messageType as traceMessageType, messageType as traceMessageType,
} from "../../trace"; } from "../../trace";
import { File, knownFolders, path } from "../../file-system"; import { File, knownFolders, path } from "../../file-system";
import * as application from "../../application"; import * as applicationCommon from "../../application/application-common";
import { profile } from "../../profiling"; import { profile } from "../../profiling";
import * as kam from "../animation/keyframe-animation"; import * as kam from "../animation/keyframe-animation";
@ -216,7 +216,7 @@ class CSSSource {
} }
} }
const onCssChanged = profile('"style-scope".onCssChanged', (args: application.CssChangedEventData) => { const onCssChanged = profile('"style-scope".onCssChanged', (args: applicationCommon.CssChangedEventData) => {
if (args.cssText) { if (args.cssText) {
const parsed = CSSSource.fromSource(args.cssText, applicationKeyframes, args.cssFile).selectors; const parsed = CSSSource.fromSource(args.cssText, applicationKeyframes, args.cssFile).selectors;
if (parsed) { if (parsed) {
@ -228,8 +228,8 @@ const onCssChanged = profile('"style-scope".onCssChanged', (args: application.Cs
} }
}); });
function onLiveSync(args: application.CssChangedEventData): void { function onLiveSync(args: applicationCommon.CssChangedEventData): void {
loadCss(application.getCssFileName()); loadCss(applicationCommon.getCssFileName());
} }
const loadCss = profile(`"style-scope".loadCss`, (cssFile: string) => { const loadCss = profile(`"style-scope".loadCss`, (cssFile: string) => {
@ -244,18 +244,18 @@ const loadCss = profile(`"style-scope".loadCss`, (cssFile: string) => {
} }
}); });
application.on("cssChanged", onCssChanged); applicationCommon.on("cssChanged", onCssChanged);
application.on("livesync", onLiveSync); applicationCommon.on("livesync", onLiveSync);
export const loadAppCSS = profile('"style-scope".loadAppCSS', (args: application.LoadAppCSSEventData) => { export const loadAppCSS = profile('"style-scope".loadAppCSS', (args: applicationCommon.LoadAppCSSEventData) => {
loadCss(args.cssFile); loadCss(args.cssFile);
application.off("loadAppCss", loadAppCSS); applicationCommon.off("loadAppCss", loadAppCSS);
}); });
if (application.hasLaunched()) { if (applicationCommon.hasLaunched()) {
loadAppCSS({ eventName: "loadAppCss", object: <any>application, cssFile: application.getCssFileName() }); loadAppCSS({ eventName: "loadAppCss", object: <any>applicationCommon, cssFile: applicationCommon.getCssFileName() });
} else { } else {
application.on("loadAppCss", loadAppCSS); applicationCommon.on("loadAppCss", loadAppCSS);
} }
export class CssState { export class CssState {
@ -662,4 +662,4 @@ class InlineSelector implements SelectorCore {
public dynamic: boolean = false; public dynamic: boolean = false;
public ruleset: RuleSet; public ruleset: RuleSet;
public match(node: Node): boolean { return true; } public match(node: Node): boolean { return true; }
} }

View File

@ -31,7 +31,6 @@ export function convertString(value: any): any {
} }
export module layout { export module layout {
const MODE_SHIFT = 30; const MODE_SHIFT = 30;
const MODE_MASK = 0x3 << MODE_SHIFT; const MODE_MASK = 0x3 << MODE_SHIFT;
@ -48,11 +47,8 @@ export module layout {
switch (mode) { switch (mode) {
case layout.EXACTLY: case layout.EXACTLY:
return "Exact"; return "Exact";
case layout.AT_MOST: case layout.AT_MOST:
return "AtMost"; return "AtMost";
default: default:
return "Unspecified"; return "Unspecified";
} }
@ -67,23 +63,17 @@ export module layout {
} }
export function measureSpecToString(measureSpec: number): string { export function measureSpecToString(measureSpec: number): string {
let mode = getMeasureSpecMode(measureSpec); const mode = getMeasureSpecMode(measureSpec);
let size = getMeasureSpecSize(measureSpec); const size = getMeasureSpecSize(measureSpec);
let text = "MeasureSpec: "; let text = "MeasureSpec: ";
if (mode === UNSPECIFIED) { if (mode === UNSPECIFIED) {
text += "UNSPECIFIED "; text += "UNSPECIFIED ";
} } else if (mode === EXACTLY) {
else if (mode === EXACTLY) {
text += "EXACTLY "; text += "EXACTLY ";
} } else if (mode === AT_MOST) {
else if (mode === AT_MOST) {
text += "AT_MOST "; text += "AT_MOST ";
} }
else {
text += mode + " ";
}
text += size; text += size;
return text; return text;
@ -126,9 +116,9 @@ export function mergeSort(arr, compareFunc) {
return arr; return arr;
} }
let middle = arr.length / 2; const middle = arr.length / 2;
let left = arr.slice(0, middle); const left = arr.slice(0, middle);
let right = arr.slice(middle, arr.length); const right = arr.slice(middle, arr.length);
return merge(mergeSort(left, compareFunc), mergeSort(right, compareFunc), compareFunc); return merge(mergeSort(left, compareFunc), mergeSort(right, compareFunc), compareFunc);
} }
@ -160,4 +150,4 @@ export function hasDuplicates(arr: Array<any>): boolean {
export function eliminateDuplicates(arr: Array<any>): Array<any> { export function eliminateDuplicates(arr: Array<any>): Array<any> {
return Array.from(new Set(arr)); return Array.from(new Set(arr));
} }

View File

@ -233,7 +233,20 @@ export module ios {
* Opens file with associated application. * Opens file with associated application.
* @param filePath The file path. * @param filePath The file path.
*/ */
export function openFile(filePath: string): boolean export function openFile(filePath: string): boolean;
/**
* Joins an array of file paths.
* @param paths An array of paths.
* Returns the joined path.
*/
export function joinPaths(...paths: string[]): string;
/**
* Gets the root folder for the current application. This Folder is private for the application and not accessible from Users/External apps.
* iOS - this folder is read-only and contains the app and all its resources.
*/
export function getCurrentAppPath(): string;
} }
/** /**

View File

@ -72,9 +72,9 @@ export module ios {
} }
export function isLandscape(): boolean { export function isLandscape(): boolean {
var device = getter(UIDevice, UIDevice.currentDevice); const device = getter(UIDevice, UIDevice.currentDevice);
var statusBarOrientation = getter(UIApplication, UIApplication.sharedApplication).statusBarOrientation; const statusBarOrientation = getter(UIApplication, UIApplication.sharedApplication).statusBarOrientation;
var isStatusBarOrientationLandscape = isOrientationLandscape(statusBarOrientation); const isStatusBarOrientationLandscape = isOrientationLandscape(statusBarOrientation);
return isOrientationLandscape(device.orientation) || isStatusBarOrientationLandscape; return isOrientationLandscape(device.orientation) || isStatusBarOrientationLandscape;
} }
@ -82,10 +82,10 @@ export module ios {
export function openFile(filePath: string): boolean { export function openFile(filePath: string): boolean {
try { try {
var fs: typeof fsModule = require("file-system"); const appPath = getCurrentAppPath();
var path = filePath.replace("~", fs.knownFolders.currentApp().path) const path = filePath.replace("~", appPath)
var controller = UIDocumentInteractionController.interactionControllerWithURL(NSURL.fileURLWithPath(path)); const controller = UIDocumentInteractionController.interactionControllerWithURL(NSURL.fileURLWithPath(path));
controller.delegate = new UIDocumentInteractionControllerDelegateImpl(); controller.delegate = new UIDocumentInteractionControllerDelegateImpl();
return controller.presentPreviewAnimated(true); return controller.presentPreviewAnimated(true);
} }
@ -94,6 +94,28 @@ export module ios {
} }
return false; return false;
} }
export function getCurrentAppPath(): string {
const currentDir = __dirname;
const tnsModulesIndex = currentDir.indexOf("/tns_modules");
// Module not hosted in ~/tns_modules when bundled. Use current dir.
let appPath = currentDir;
if (tnsModulesIndex !== -1) {
// Strip part after tns_modules to obtain app root
appPath = currentDir.substring(0, tnsModulesIndex);
}
return appPath;
}
export function joinPaths(...paths: string[]): string {
if (!paths || paths.length === 0) {
return "";
}
return NSString.stringWithString(NSString.pathWithComponents(<any>paths)).stringByStandardizingPath;
}
} }
export function GC() { export function GC() {
@ -118,8 +140,8 @@ class UIDocumentInteractionControllerDelegateImpl extends NSObject implements UI
public static ObjCProtocols = [UIDocumentInteractionControllerDelegate]; public static ObjCProtocols = [UIDocumentInteractionControllerDelegate];
public getViewController(): UIViewController { public getViewController(): UIViewController {
var frame = require("ui/frame"); const app = ios.getter(UIApplication, UIApplication.sharedApplication);
return frame.topmost().currentPage.ios; return app.keyWindow.rootViewController;
} }
public documentInteractionControllerViewControllerForPreview(controller: UIDocumentInteractionController) { public documentInteractionControllerViewControllerForPreview(controller: UIDocumentInteractionController) {
@ -135,4 +157,4 @@ class UIDocumentInteractionControllerDelegateImpl extends NSObject implements UI
} }
} }
mainScreenScale = ios.getter(UIScreen, UIScreen.mainScreen).scale; mainScreenScale = ios.getter(UIScreen, UIScreen.mainScreen).scale;