diff --git a/e2e/modal-navigation-ng/.gitignore b/e2e/modal-navigation-ng/.gitignore new file mode 100644 index 000000000..06947f093 --- /dev/null +++ b/e2e/modal-navigation-ng/.gitignore @@ -0,0 +1,8 @@ +platforms +node_modules +hooks + +app/**/*.js +e2e/**/*.js +e2e/reports +test-results.xml diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/AndroidManifest.xml b/e2e/modal-navigation-ng/app/App_Resources/Android/AndroidManifest.xml new file mode 100644 index 000000000..9db832151 --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/Android/AndroidManifest.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/app.gradle b/e2e/modal-navigation-ng/app/App_Resources/Android/app.gradle new file mode 100644 index 000000000..924f7c70f --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/Android/app.gradle @@ -0,0 +1,16 @@ +// Add your native dependencies here: + +// Uncomment to add recyclerview-v7 dependency +//dependencies { +// compile 'com.android.support:recyclerview-v7:+' +//} + +android { + defaultConfig { + generatedDensities = [] + applicationId = "org.nativescript.modalnavigationng" + } + aaptOptions { + additionalParameters "--no-version-vectors" + } +} diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-hdpi/background.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-hdpi/background.png new file mode 100644 index 000000000..eb381c258 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-hdpi/background.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-hdpi/icon.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-hdpi/icon.png new file mode 100755 index 000000000..9cde84cd5 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-hdpi/icon.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-hdpi/logo.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-hdpi/logo.png new file mode 100644 index 000000000..5218f4c90 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-hdpi/logo.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-ldpi/background.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-ldpi/background.png new file mode 100644 index 000000000..748b2adf5 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-ldpi/background.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-ldpi/icon.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-ldpi/icon.png new file mode 100755 index 000000000..4d6a674b3 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-ldpi/icon.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-ldpi/logo.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-ldpi/logo.png new file mode 100644 index 000000000..b9e102a76 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-ldpi/logo.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-mdpi/background.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-mdpi/background.png new file mode 100644 index 000000000..efeaf2907 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-mdpi/background.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-mdpi/icon.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-mdpi/icon.png new file mode 100755 index 000000000..92ccc85a6 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-mdpi/icon.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-mdpi/logo.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-mdpi/logo.png new file mode 100644 index 000000000..626338766 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-mdpi/logo.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-nodpi/splash_screen.xml b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-nodpi/splash_screen.xml new file mode 100644 index 000000000..ada77f92c --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-nodpi/splash_screen.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xhdpi/background.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xhdpi/background.png new file mode 100644 index 000000000..612bbd072 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xhdpi/background.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xhdpi/icon.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xhdpi/icon.png new file mode 100644 index 000000000..8bcde6277 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xhdpi/icon.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xhdpi/logo.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xhdpi/logo.png new file mode 100644 index 000000000..ad8ee2f4b Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xhdpi/logo.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxhdpi/background.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxhdpi/background.png new file mode 100644 index 000000000..0fa88e235 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxhdpi/background.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxhdpi/icon.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxhdpi/icon.png new file mode 100644 index 000000000..9d81c85dc Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxhdpi/icon.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxhdpi/logo.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxhdpi/logo.png new file mode 100644 index 000000000..668327832 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxhdpi/logo.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxxhdpi/background.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxxhdpi/background.png new file mode 100644 index 000000000..c650f6438 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxxhdpi/background.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxxhdpi/icon.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxxhdpi/icon.png new file mode 100644 index 000000000..9a34d0d43 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxxhdpi/icon.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxxhdpi/logo.png b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxxhdpi/logo.png new file mode 100644 index 000000000..fa6331c8d Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/Android/drawable-xxxhdpi/logo.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/values-v21/colors.xml b/e2e/modal-navigation-ng/app/App_Resources/Android/values-v21/colors.xml new file mode 100644 index 000000000..a64641a9d --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/Android/values-v21/colors.xml @@ -0,0 +1,4 @@ + + + #3d5afe + \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/values-v21/styles.xml b/e2e/modal-navigation-ng/app/App_Resources/Android/values-v21/styles.xml new file mode 100644 index 000000000..dac8727c8 --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/Android/values-v21/styles.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/values/colors.xml b/e2e/modal-navigation-ng/app/App_Resources/Android/values/colors.xml new file mode 100644 index 000000000..74ad8829c --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/Android/values/colors.xml @@ -0,0 +1,7 @@ + + + #F5F5F5 + #757575 + #33B5E5 + #272734 + \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/App_Resources/Android/values/styles.xml b/e2e/modal-navigation-ng/app/App_Resources/Android/values/styles.xml new file mode 100644 index 000000000..c793e6d4c --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/Android/values/styles.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..4034b76e6 --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "icon-29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "icon-29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "icon-29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon-40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon-40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon-60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon-60@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "icon-29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "icon-29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "icon-40.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "icon-40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon-76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "icon-83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "icon-1024.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png new file mode 100644 index 000000000..a1d7eb479 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png new file mode 100644 index 000000000..bb9b9e86d Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png new file mode 100644 index 000000000..ec609dcf3 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png new file mode 100644 index 000000000..a97180800 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png new file mode 100644 index 000000000..214800ee6 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png new file mode 100644 index 000000000..8554b88a8 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png new file mode 100644 index 000000000..a22626bae Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png new file mode 100644 index 000000000..a22626bae Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png new file mode 100644 index 000000000..492c9c8e8 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png new file mode 100644 index 000000000..9208113cf Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png new file mode 100644 index 000000000..24415e5a3 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png new file mode 100644 index 000000000..b3ef1bf0c Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/Contents.json b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/Contents.json new file mode 100644 index 000000000..da4a164c9 --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 000000000..11bfcf55c --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,176 @@ +{ + "images" : [ + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "2436h", + "filename" : "Default-1125h.png", + "minimum-system-version" : "11.0", + "orientation" : "portrait", + "scale" : "3x" + }, + { + "orientation" : "landscape", + "idiom" : "iphone", + "extent" : "full-screen", + "filename" : "Default-Landscape-X.png", + "minimum-system-version" : "11.0", + "subtype" : "2436h", + "scale" : "3x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "736h", + "filename" : "Default-736h@3x.png", + "minimum-system-version" : "8.0", + "orientation" : "portrait", + "scale" : "3x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "736h", + "filename" : "Default-Landscape@3x.png", + "minimum-system-version" : "8.0", + "orientation" : "landscape", + "scale" : "3x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "667h", + "filename" : "Default-667h@2x.png", + "minimum-system-version" : "8.0", + "orientation" : "portrait", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "filename" : "Default@2x.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "retina4", + "filename" : "Default-568h@2x.png", + "minimum-system-version" : "7.0", + "orientation" : "portrait", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "filename" : "Default-Portrait.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "filename" : "Default-Landscape.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "filename" : "Default-Portrait@2x.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "filename" : "Default-Landscape@2x.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "filename" : "Default.png", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "filename" : "Default@2x.png", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "filename" : "Default-568h@2x.png", + "extent" : "full-screen", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "to-status-bar", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "filename" : "Default-Portrait.png", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "to-status-bar", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "filename" : "Default-Landscape.png", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "to-status-bar", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "filename" : "Default-Portrait@2x.png", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "to-status-bar", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "filename" : "Default-Landscape@2x.png", + "extent" : "full-screen", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-1125h.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-1125h.png new file mode 100644 index 000000000..2913f85d9 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-1125h.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png new file mode 100644 index 000000000..d7f17fcd2 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png new file mode 100644 index 000000000..b88415405 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png new file mode 100644 index 000000000..faab4b631 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-X.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-X.png new file mode 100644 index 000000000..cd94a3ac2 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-X.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png new file mode 100644 index 000000000..3365ba3cd Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png new file mode 100644 index 000000000..a44945c1a Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png new file mode 100644 index 000000000..e6dca6269 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png new file mode 100644 index 000000000..1a5007962 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png new file mode 100644 index 000000000..73d8b920f Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png new file mode 100644 index 000000000..9f1f6ce3e Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png new file mode 100644 index 000000000..514fc5cde Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json new file mode 100644 index 000000000..4f4e9c506 --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchScreen-AspectFill.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchScreen-AspectFill@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png new file mode 100644 index 000000000..c293f9c7a Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png new file mode 100644 index 000000000..233693a6e Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json new file mode 100644 index 000000000..23c0ffd7a --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchScreen-Center.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchScreen-Center@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png new file mode 100644 index 000000000..a5a775a2b Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png new file mode 100644 index 000000000..154c19343 Binary files /dev/null and b/e2e/modal-navigation-ng/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png differ diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/Info.plist b/e2e/modal-navigation-ng/app/App_Resources/iOS/Info.plist new file mode 100644 index 000000000..ea3e3ea23 --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/iOS/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIRequiresFullScreen + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/LaunchScreen.storyboard b/e2e/modal-navigation-ng/app/App_Resources/iOS/LaunchScreen.storyboard new file mode 100644 index 000000000..c4e5a3f39 --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/iOS/LaunchScreen.storyboard @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/e2e/modal-navigation-ng/app/App_Resources/iOS/build.xcconfig b/e2e/modal-navigation-ng/app/App_Resources/iOS/build.xcconfig new file mode 100644 index 000000000..4b0118490 --- /dev/null +++ b/e2e/modal-navigation-ng/app/App_Resources/iOS/build.xcconfig @@ -0,0 +1,7 @@ +// You can add custom settings here +// for example you can uncomment the following line to force distribution code signing +// CODE_SIGN_IDENTITY = iPhone Distribution +// To build for device with Xcode 8 you need to specify your development team. More info: https://developer.apple.com/library/prerelease/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html +// DEVELOPMENT_TEAM = YOUR_TEAM_ID; +ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; +ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; diff --git a/e2e/modal-navigation-ng/app/CODE_OF_CONDUCT.md b/e2e/modal-navigation-ng/app/CODE_OF_CONDUCT.md new file mode 100644 index 000000000..1c845d0b1 --- /dev/null +++ b/e2e/modal-navigation-ng/app/CODE_OF_CONDUCT.md @@ -0,0 +1,83 @@ +# NativeScript Community Code of Conduct + +Our community members come from all walks of life and are all at different stages of their personal and professional journeys. To support everyone, we've prepared a short code of conduct. Our mission is best served in an environment that is friendly, safe, and accepting; free from intimidation or harassment. + +Towards this end, certain behaviors and practices will not be tolerated. + +## tl;dr + +- Be respectful. +- We're here to help. +- Abusive behavior is never tolerated. +- Violations of this code may result in swift and permanent expulsion from the NativeScript community channels. + +## Administrators + +- Dan Wilson (@DanWilson on Slack) +- Jen Looper (@jen.looper on Slack) +- TJ VanToll (@tjvantoll on Slack) + +## Scope + +We expect all members of the NativeScript community, including administrators, users, facilitators, and vendors to abide by this Code of Conduct at all times in our community venues, online and in person, and in one-on-one communications pertaining to NativeScript affairs. + +This policy covers the usage of the NativeScript Slack community, as well as the NativeScript support forums, NativeScript GitHub repositories, the NativeScript website, and any NativeScript-related events. This Code of Conduct is in addition to, and does not in any way nullify or invalidate, any other terms or conditions related to use of NativeScript. + +The definitions of various subjective terms such as "discriminatory", "hateful", or "confusing" will be decided at the sole discretion of the NativeScript administrators. + +## Friendly, Harassment-Free Space + +We are committed to providing a friendly, safe, and welcoming environment for all, regardless of gender identity, sexual orientation, disability, ethnicity, religion, age, physical appearance, body size, race, or similar personal characteristics. + +We ask that you please respect that people have differences of opinion regarding technical choices, and acknowledge that every design or implementation choice carries a trade-off and numerous costs. There is seldom a single right answer. A difference of technology preferences is never a license to be rude. + +Any spamming, trolling, flaming, baiting, or other attention-stealing behaviour is not welcome, and will not be tolerated. + +Harassing other users of NativeScript is never tolerated, whether via public or private media. + +Avoid using offensive or harassing package names, nicknames, or other identifiers that might detract from a friendly, safe, and welcoming environment for all. + +Harassment includes, but is not limited to: harmful or prejudicial verbal or written comments related to gender identity, sexual orientation, disability, ethnicity, religion, age, physical appearance, body size, race, or similar personal characteristics; inappropriate use of nudity, sexual images, and/or sexually explicit language in public spaces; threats of physical or non-physical harm; deliberate intimidation, stalking or following; harassing photography or recording; sustained disruption of talks or other events; inappropriate physical contact; and unwelcome sexual attention. + +## Acceptable Content + +The NativeScript administrators reserve the right to make judgement calls about what is and isn't appropriate in published content. These are guidelines to help you be successful in our community. + +Content must contain something applicable to the previously stated goals of the NativeScript community. "Spamming", that is, publishing any form of content that is not applicable, is not allowed. + +Content must not contain illegal or infringing content. You should only publish content to NativeScript properties if you have the right to do so. This includes complying with all software license agreements or other intellectual property restrictions. For example, redistributing an MIT-licensed module with the copyright notice removed, would not be allowed. You will be responsible for any violation of laws or others’ intellectual property rights. + +Content must not be malware. For example, content (code, video, pictures, words, etc.) which is designed to maliciously exploit or damage computer systems, is not allowed. + +Content name, description, and other visible metadata must not include abusive, inappropriate, or harassing content. + +## Reporting Violations of this Code of Conduct + +If you believe someone is harassing you or has otherwise violated this Code of Conduct, please contact the administrators and send us an abuse report. If this is the initial report of a problem, please include as much detail as possible. It is easiest for us to address issues when we have more context. + +## Consequences + +All content published to the NativeScript community channels is hosted at the sole discretion of the NativeScript administrators. + +Unacceptable behavior from any community member, including sponsors, employees, customers, or others with decision-making authority, will not be tolerated. + +Anyone asked to stop unacceptable behavior is expected to comply immediately. + +If a community member engages in unacceptable behavior, the NativeScript administrators may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event or service). + +## Addressing Grievances + +If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify the administrators. We will do our best to ensure that your grievance is handled appropriately. + +In general, we will choose the course of action that we judge as being most in the interest of fostering a safe and friendly community. + +## Contact Info +Please contact Dan Wilson @DanWilson if you need to report a problem or address a grievance related to an abuse report. + +You are also encouraged to contact us if you are curious about something that might be "on the line" between appropriate and inappropriate content. We are happy to provide guidance to help you be a successful part of our community. + +## Credit and License + +This Code of Conduct borrows heavily from the WADE Code of Conduct, which is derived from the NodeBots Code of Conduct, which in turn borrows from the npm Code of Conduct, which was derived from the Stumptown Syndicate Citizen's Code of Conduct, and the Rust Project Code of Conduct. + +This document may be reused under a Creative Commons Attribution-ShareAlike License. \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/LICENSE b/e2e/modal-navigation-ng/app/LICENSE new file mode 100755 index 000000000..ced13b45c --- /dev/null +++ b/e2e/modal-navigation-ng/app/LICENSE @@ -0,0 +1,201 @@ +Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "{}" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright (c) 2015-2018 Telerik AD + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/README.md b/e2e/modal-navigation-ng/app/README.md new file mode 100644 index 000000000..132ede3b0 --- /dev/null +++ b/e2e/modal-navigation-ng/app/README.md @@ -0,0 +1,25 @@ +# NativeScript Angular Template + +This template creates a "Hello, world" NativeScript app using TypeScript and Angular. + +You can create a new app that uses this template with either the `--template` option. + +``` +tns create my-app-name --template tns-template-hello-world-ng +``` + +Or the `--ng` shorthand. + +``` +tns create my-app-name --ng +``` + +> Note: Both commands will create a new NativeScript app that uses the latest version of this template published to [npm] (https://www.npmjs.com/package/tns-template-hello-world-ng). + +If you want to create a new app that uses the source of the template from the `master` branch, you can execute the following: + +``` +tns create my-app-name --template https://github.com/NativeScript/template-hello-world-ng.git#master +``` + +**NB:** Please, have in mind that the master branch may refer to dependencies that are not on NPM yet! diff --git a/e2e/modal-navigation-ng/app/app.component.html b/e2e/modal-navigation-ng/app/app.component.html new file mode 100644 index 000000000..8a2c1a75e --- /dev/null +++ b/e2e/modal-navigation-ng/app/app.component.html @@ -0,0 +1,2 @@ + + diff --git a/e2e/modal-navigation-ng/app/app.component.ts b/e2e/modal-navigation-ng/app/app.component.ts new file mode 100644 index 000000000..b95dd6f01 --- /dev/null +++ b/e2e/modal-navigation-ng/app/app.component.ts @@ -0,0 +1,8 @@ +import { Component } from "@angular/core"; + +@Component({ + selector: "ns-app", + templateUrl: "app.component.html", +}) + +export class AppComponent { } diff --git a/e2e/modal-navigation-ng/app/app.css b/e2e/modal-navigation-ng/app/app.css new file mode 100644 index 000000000..d23504c4e --- /dev/null +++ b/e2e/modal-navigation-ng/app/app.css @@ -0,0 +1,12 @@ +/* +In NativeScript, the app.css file is where you place CSS rules that +you would like to apply to your entire application. Check out +http://docs.nativescript.org/ui/styling for a full list of the CSS +selectors and properties you can use to style UI components. + +/* +In many cases you may want to use the NativeScript core theme instead +of writing your own CSS rules. For a full list of class names in the theme +refer to http://docs.nativescript.org/ui/theme. +*/ +@import '~nativescript-theme-core/css/core.light.css'; diff --git a/e2e/modal-navigation-ng/app/app.module.ngfactory.d.ts b/e2e/modal-navigation-ng/app/app.module.ngfactory.d.ts new file mode 100644 index 000000000..793157de3 --- /dev/null +++ b/e2e/modal-navigation-ng/app/app.module.ngfactory.d.ts @@ -0,0 +1,4 @@ +/** + * A dynamically generated module when compiled with AoT. + */ +export const AppModuleNgFactory: any; \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/app.module.ts b/e2e/modal-navigation-ng/app/app.module.ts new file mode 100644 index 000000000..5f3f2e17a --- /dev/null +++ b/e2e/modal-navigation-ng/app/app.module.ts @@ -0,0 +1,39 @@ +import { NgModule, NO_ERRORS_SCHEMA } from "@angular/core"; +import { NativeScriptModule } from "nativescript-angular/nativescript.module"; +import { AppRoutingModule } from "./app.routing"; +import { AppComponent } from "./app.component"; + +import { ItemService } from "./item/item.service"; +import { ItemsComponent } from "./item/items.component"; +import { ItemDetailComponent } from "./item/item-detail.component"; + +// Uncomment and add to NgModule imports if you need to use two-way binding +// import { NativeScriptFormsModule } from "nativescript-angular/forms"; + +// Uncomment and add to NgModule imports if you need to use the HTTP wrapper +// import { NativeScriptHttpModule } from "nativescript-angular/http"; + +@NgModule({ + bootstrap: [ + AppComponent + ], + imports: [ + NativeScriptModule, + AppRoutingModule + ], + declarations: [ + AppComponent, + ItemsComponent, + ItemDetailComponent + ], + providers: [ + ItemService + ], + schemas: [ + NO_ERRORS_SCHEMA + ] +}) +/* +Pass your application module to the bootstrapModule function located in main.ts to start your app +*/ +export class AppModule { } diff --git a/e2e/modal-navigation-ng/app/app.routing.ts b/e2e/modal-navigation-ng/app/app.routing.ts new file mode 100644 index 000000000..26c691b5d --- /dev/null +++ b/e2e/modal-navigation-ng/app/app.routing.ts @@ -0,0 +1,18 @@ +import { NgModule } from "@angular/core"; +import { NativeScriptRouterModule } from "nativescript-angular/router"; +import { Routes } from "@angular/router"; + +import { ItemsComponent } from "./item/items.component"; +import { ItemDetailComponent } from "./item/item-detail.component"; + +const routes: Routes = [ + { path: "", redirectTo: "/items", pathMatch: "full" }, + { path: "items", component: ItemsComponent }, + { path: "item/:id", component: ItemDetailComponent }, +]; + +@NgModule({ + imports: [NativeScriptRouterModule.forRoot(routes)], + exports: [NativeScriptRouterModule] +}) +export class AppRoutingModule { } \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/item/item-detail.component.html b/e2e/modal-navigation-ng/app/item/item-detail.component.html new file mode 100644 index 000000000..3bbd174c0 --- /dev/null +++ b/e2e/modal-navigation-ng/app/item/item-detail.component.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/e2e/modal-navigation-ng/app/item/item-detail.component.ts b/e2e/modal-navigation-ng/app/item/item-detail.component.ts new file mode 100644 index 000000000..9183f7876 --- /dev/null +++ b/e2e/modal-navigation-ng/app/item/item-detail.component.ts @@ -0,0 +1,24 @@ +import { Component, OnInit } from "@angular/core"; +import { ActivatedRoute } from "@angular/router"; + +import { Item } from "./item"; +import { ItemService } from "./item.service"; + +@Component({ + selector: "ns-details", + moduleId: module.id, + templateUrl: "./item-detail.component.html", +}) +export class ItemDetailComponent implements OnInit { + item: Item; + + constructor( + private itemService: ItemService, + private route: ActivatedRoute + ) { } + + ngOnInit(): void { + const id = +this.route.snapshot.params["id"]; + this.item = this.itemService.getItem(id); + } +} diff --git a/e2e/modal-navigation-ng/app/item/item.service.ts b/e2e/modal-navigation-ng/app/item/item.service.ts new file mode 100644 index 000000000..0feb6c5ff --- /dev/null +++ b/e2e/modal-navigation-ng/app/item/item.service.ts @@ -0,0 +1,39 @@ +import { Injectable } from "@angular/core"; + +import { Item } from "./item"; + +@Injectable() +export class ItemService { + private items = new Array( + { id: 1, name: "Ter Stegen", role: "Goalkeeper" }, + { id: 3, name: "Piqué", role: "Defender" }, + { id: 4, name: "I. Rakitic", role: "Midfielder" }, + { id: 5, name: "Sergio", role: "Midfielder" }, + { id: 6, name: "Denis Suárez", role: "Midfielder" }, + { id: 7, name: "Arda", role: "Midfielder" }, + { id: 8, name: "A. Iniesta", role: "Midfielder" }, + { id: 9, name: "Suárez", role: "Forward" }, + { id: 10, name: "Messi", role: "Forward" }, + { id: 11, name: "Neymar", role: "Forward" }, + { id: 12, name: "Rafinha", role: "Midfielder" }, + { id: 13, name: "Cillessen", role: "Goalkeeper" }, + { id: 14, name: "Mascherano", role: "Defender" }, + { id: 17, name: "Paco Alcácer", role: "Forward" }, + { id: 18, name: "Jordi Alba", role: "Defender" }, + { id: 19, name: "Digne", role: "Defender" }, + { id: 20, name: "Sergi Roberto", role: "Midfielder" }, + { id: 21, name: "André Gomes", role: "Midfielder" }, + { id: 22, name: "Aleix Vidal", role: "Midfielder" }, + { id: 23, name: "Umtiti", role: "Defender" }, + { id: 24, name: "Mathieu", role: "Defender" }, + { id: 25, name: "Masip", role: "Goalkeeper" }, + ); + + getItems(): Item[] { + return this.items; + } + + getItem(id: number): Item { + return this.items.filter(item => item.id === id)[0]; + } +} diff --git a/e2e/modal-navigation-ng/app/item/item.ts b/e2e/modal-navigation-ng/app/item/item.ts new file mode 100644 index 000000000..950fba446 --- /dev/null +++ b/e2e/modal-navigation-ng/app/item/item.ts @@ -0,0 +1,5 @@ +export interface Item { + id: number; + name: string; + role: string; +} diff --git a/e2e/modal-navigation-ng/app/item/items.component.html b/e2e/modal-navigation-ng/app/item/items.component.html new file mode 100644 index 000000000..55e87e3ab --- /dev/null +++ b/e2e/modal-navigation-ng/app/item/items.component.html @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + diff --git a/e2e/modal-navigation-ng/app/item/items.component.ts b/e2e/modal-navigation-ng/app/item/items.component.ts new file mode 100644 index 000000000..0ea98c8c5 --- /dev/null +++ b/e2e/modal-navigation-ng/app/item/items.component.ts @@ -0,0 +1,21 @@ +import { Component, OnInit } from "@angular/core"; + +import { Item } from "./item"; +import { ItemService } from "./item.service"; + +@Component({ + selector: "ns-items", + moduleId: module.id, + templateUrl: "./items.component.html", +}) +export class ItemsComponent implements OnInit { + items: Item[]; + + // This pattern makes use of Angular’s dependency injection implementation to inject an instance of the ItemService service into this class. + // Angular knows about this service because it is included in your app’s main NgModule, defined in app.module.ts. + constructor(private itemService: ItemService) { } + + ngOnInit(): void { + this.items = this.itemService.getItems(); + } +} \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/main.aot.ts b/e2e/modal-navigation-ng/app/main.aot.ts new file mode 100644 index 000000000..d5ff77a77 --- /dev/null +++ b/e2e/modal-navigation-ng/app/main.aot.ts @@ -0,0 +1,7 @@ +// this import should be first in order to load some required settings (like globals and reflect-metadata) +import { platformNativeScript } from "nativescript-angular/platform-static"; + +// "./app.module.ngfactory" is a dynamically generated module when compiled with AoT. +import { AppModuleNgFactory } from "./app.module.ngfactory"; + +platformNativeScript().bootstrapModuleFactory(AppModuleNgFactory); diff --git a/e2e/modal-navigation-ng/app/main.ts b/e2e/modal-navigation-ng/app/main.ts new file mode 100644 index 000000000..a84cb8844 --- /dev/null +++ b/e2e/modal-navigation-ng/app/main.ts @@ -0,0 +1,10 @@ +// this import should be first in order to load some required settings (like globals and reflect-metadata) +import { platformNativeScriptDynamic } from "nativescript-angular/platform"; + +import { AppModule } from "./app.module"; + +// A traditional NativeScript application starts by initializing global objects, setting up global CSS rules, creating, and navigating to the main page. +// Angular applications need to take care of their own initialization: modules, components, directives, routes, DI providers. +// A NativeScript Angular app needs to make both paradigms work together, so we provide a wrapper platform object, platformNativeScriptDynamic, +// that sets up a NativeScript application and can bootstrap the Angular framework. +platformNativeScriptDynamic().bootstrapModule(AppModule); diff --git a/e2e/modal-navigation-ng/app/package.json b/e2e/modal-navigation-ng/app/package.json new file mode 100644 index 000000000..826903ec1 --- /dev/null +++ b/e2e/modal-navigation-ng/app/package.json @@ -0,0 +1,8 @@ +{ + "android": { + "v8Flags": "--expose_gc" + }, + "main": "main.js", + "name": "tns-template-hello-world-ng", + "version": "3.4.3" +} \ No newline at end of file diff --git a/e2e/modal-navigation-ng/app/vendor-platform.android.ts b/e2e/modal-navigation-ng/app/vendor-platform.android.ts new file mode 100644 index 000000000..719f26498 --- /dev/null +++ b/e2e/modal-navigation-ng/app/vendor-platform.android.ts @@ -0,0 +1,9 @@ +require("application"); +if (!global["__snapshot"]) { + // In case snapshot generation is enabled these modules will get into the bundle + // but will not be required/evaluated. + // The snapshot webpack plugin will add them to the tns-java-classes.js bundle file. + // This way, they will be evaluated on app start as early as possible. + require("ui/frame"); + require("ui/frame/activity"); +} diff --git a/e2e/modal-navigation-ng/app/vendor-platform.ios.ts b/e2e/modal-navigation-ng/app/vendor-platform.ios.ts new file mode 100644 index 000000000..5ce49d815 --- /dev/null +++ b/e2e/modal-navigation-ng/app/vendor-platform.ios.ts @@ -0,0 +1,3 @@ +// There is a bug in angular: https://github.com/angular/angular-cli/pull/8589/files +// Legendary stuff, its webpack plugin pretty much doesn't work with empty TypeScript files in v1.8.3 +void 0; diff --git a/e2e/modal-navigation-ng/app/vendor.ts b/e2e/modal-navigation-ng/app/vendor.ts new file mode 100644 index 000000000..4526eca9b --- /dev/null +++ b/e2e/modal-navigation-ng/app/vendor.ts @@ -0,0 +1,20 @@ +// Snapshot the ~/app.css and the theme +const application = require("application"); +require("ui/styling/style-scope"); +const appCssContext = require.context("~/", false, /^\.\/app\.(css|scss|less|sass)$/); +global.registerWebpackModules(appCssContext); +application.loadAppCss(); + +require("./vendor-platform"); + +require("reflect-metadata"); +require("@angular/platform-browser"); +require("@angular/core"); +require("@angular/common"); +require("@angular/forms"); +require("@angular/http"); +require("@angular/router"); + +require("nativescript-angular/platform-static"); +require("nativescript-angular/forms"); +require("nativescript-angular/router"); diff --git a/e2e/modal-navigation-ng/e2e/config/appium.capabilities.json b/e2e/modal-navigation-ng/e2e/config/appium.capabilities.json new file mode 100644 index 000000000..64f28061b --- /dev/null +++ b/e2e/modal-navigation-ng/e2e/config/appium.capabilities.json @@ -0,0 +1,98 @@ +{ + "android19": { + "platformName": "Android", + "platformVersion": "4.4", + "deviceName": "Emulator-Api19-Default", + "avd": "Emulator-Api19-Default", + "lt": 60000, + "appActivity": "com.tns.NativeScriptActivity", + "newCommandTimeout": 720, + "noReset": true, + "fullReset": false, + "app": "" + }, + "android21": { + "platformName": "Android", + "platformVersion": "5.0", + "deviceName": "Emulator-Api21-Default", + "avd": "Emulator-Api21-Default", + "lt": 60000, + "appActivity": "com.tns.NativeScriptActivity", + "newCommandTimeout": 720, + "noReset": true, + "fullReset": false, + "app": "" + }, + "android23": { + "platformName": "Android", + "platformVersion": "6.0", + "deviceName": "Emulator-Api23-Default", + "avd": "Emulator-Api23-Default", + "lt": 60000, + "appActivity": "com.tns.NativeScriptActivity", + "newCommandTimeout": 720, + "noReset": true, + "fullReset": false, + "app": "" + }, + "android24": { + "platformName": "Android", + "platformVersion": "7.0", + "deviceName": "Emulator-Api24-Default", + "avd": "Emulator-Api24-Default", + "lt": 60000, + "appActivity": "com.tns.NativeScriptActivity", + "newCommandTimeout": 720, + "noReset": true, + "fullReset": false, + "app": "" + }, + "android25": { + "platformName": "Android", + "platformVersion": "7.1", + "deviceName": "Emulator-Api25-Google", + "avd": "Emulator-Api25-Google", + "lt": 60000, + "appActivity": "com.tns.NativeScriptActivity", + "newCommandTimeout": 720, + "noReset": true, + "fullReset": false, + "app": "" + }, + "android26": { + "platformName": "Android", + "platformVersion": "8.0", + "deviceName": "Emulator-Api26-Google", + "avd": "Emulator-Api26-Google", + "lt": 60000, + "appActivity": "com.tns.NativeScriptActivity", + "newCommandTimeout": 720, + "noReset": true, + "fullReset": false, + "app": "" + }, + "sim.iPhone7.iOS100": { + "platformName": "iOS", + "platformVersion": "10.0", + "deviceName": "iPhone 7 100", + "noReset": true, + "fullReset": false, + "app": "" + }, + "sim.iPhone8.iOS110": { + "platformName": "iOS", + "platformVersion": "11.0", + "deviceName": "iPhone 8 110", + "noReset": true, + "fullReset": false, + "app": "" + }, + "sim.iPhoneX.iOS110": { + "platformName": "iOS", + "platformVersion": "11.0", + "deviceName": "iPhone X", + "noReset": true, + "fullReset": false, + "app": "" + } +} diff --git a/e2e/modal-navigation-ng/e2e/config/mocha.opts b/e2e/modal-navigation-ng/e2e/config/mocha.opts new file mode 100644 index 000000000..796ec4724 --- /dev/null +++ b/e2e/modal-navigation-ng/e2e/config/mocha.opts @@ -0,0 +1,4 @@ +--timeout 80000 +--recursive e2e +--reporter mocha-multi +--reporter-options spec=-,mocha-junit-reporter=test-results.xml \ No newline at end of file diff --git a/e2e/modal-navigation-ng/e2e/sample.e2e-spec.ts b/e2e/modal-navigation-ng/e2e/sample.e2e-spec.ts new file mode 100644 index 000000000..45bda4c9a --- /dev/null +++ b/e2e/modal-navigation-ng/e2e/sample.e2e-spec.ts @@ -0,0 +1,44 @@ +import { AppiumDriver, createDriver, SearchOptions } from "nativescript-dev-appium"; +import { assert } from "chai"; + +describe("sample scenario", () => { + const defaultWaitTime = 5000; + let driver: AppiumDriver; + + before(async () => { + driver = await createDriver(); + }); + + after(async () => { + await driver.quit(); + console.log("Quit driver!"); + }); + + afterEach(async function () { + if (this.currentTest.state === "failed") { + await driver.logScreenshot(this.currentTest.title); + } + }); + + it("should find an element by text", async () => { + const btnTap = await driver.findElementByText("TAP", SearchOptions.exact); + await btnTap.click(); + + const message = " taps left"; + const lblMessage = await driver.findElementByText(message, SearchOptions.contains); + assert.equal(await lblMessage.text(), "41" + message); + + // Image verification + // const screen = await driver.compareScreen("hello-world-41"); + // assert.isTrue(screen); + }); + + it("should find an element by type", async () => { + const btnTap = await driver.findElementByClassName(driver.locators.button); + await btnTap.click(); + + const message = " taps left"; + const lblMessage = await driver.findElementByText(message, SearchOptions.contains); + assert.equal(await lblMessage.text(), "40" + message); + }); +}); \ No newline at end of file diff --git a/e2e/modal-navigation-ng/e2e/setup.ts b/e2e/modal-navigation-ng/e2e/setup.ts new file mode 100644 index 000000000..8b26e66e9 --- /dev/null +++ b/e2e/modal-navigation-ng/e2e/setup.ts @@ -0,0 +1,9 @@ +import { startServer, stopServer } from "nativescript-dev-appium"; + +before("start server", async () => { + await startServer(); +}); + +after("stop server", async () => { + await stopServer(); +}); diff --git a/e2e/modal-navigation-ng/e2e/tsconfig.json b/e2e/modal-navigation-ng/e2e/tsconfig.json new file mode 100644 index 000000000..c297b2347 --- /dev/null +++ b/e2e/modal-navigation-ng/e2e/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "importHelpers": false, + "types": [ + "node", + "mocha", + "chai" + ], + "lib": [ + "es2015", + "dom" + ] + } +} \ No newline at end of file diff --git a/e2e/modal-navigation-ng/package.json b/e2e/modal-navigation-ng/package.json new file mode 100644 index 000000000..f70caca81 --- /dev/null +++ b/e2e/modal-navigation-ng/package.json @@ -0,0 +1,61 @@ +{ + "description": "NativeScript Application", + "license": "SEE LICENSE IN ", + "readme": "NativeScript Application", + "repository": "", + "nativescript": { + "id": "org.nativescript.modalnavigationng", + "tns-android": { + "version": "next" + }, + "tns-ios": { + "version": "next" + } + }, + "dependencies": { + "@angular/animations": "~5.2.0", + "@angular/common": "~5.2.0", + "@angular/compiler": "~5.2.0", + "@angular/core": "~5.2.0", + "@angular/forms": "~5.2.0", + "@angular/http": "~5.2.0", + "@angular/platform-browser": "~5.2.0", + "@angular/platform-browser-dynamic": "~5.2.0", + "@angular/router": "~5.2.0", + "nativescript-angular": "file:../../nativescript-angular", + "nativescript-theme-core": "~1.0.4", + "reflect-metadata": "~0.1.8", + "rxjs": "~5.5.2", + "tns-core-modules": "next", + "zone.js": "~0.8.2" + }, + "devDependencies": { + "@angular/compiler-cli": "~5.2.0", + "@ngtools/webpack": "~1.9.4", + "@types/chai": "^4.0.2", + "@types/mocha": "^2.2.41", + "@types/node": "^7.0.5", + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "copy-webpack-plugin": "~4.3.0", + "css-loader": "~0.28.7", + "extract-text-webpack-plugin": "~3.0.2", + "lazy": "1.0.11", + "nativescript-dev-appium": "next", + "nativescript-dev-typescript": "next", + "nativescript-dev-webpack": "next", + "nativescript-worker-loader": "~0.8.1", + "raw-loader": "~0.5.1", + "resolve-url-loader": "~2.2.1", + "typescript": "~2.6.2", + "uglifyjs-webpack-plugin": "~1.1.6", + "webpack": "~3.10.0", + "webpack-bundle-analyzer": "^2.9.1", + "webpack-sources": "~1.1.0" + }, + "scripts": { + "e2e": "tsc -p e2e && mocha --opts ./e2e/config/mocha.opts", + "e2e-watch": "tsc -p e2e --watch" + } +} diff --git a/e2e/modal-navigation-ng/tsconfig.json b/e2e/modal-navigation-ng/tsconfig.json new file mode 100644 index 000000000..f251eb444 --- /dev/null +++ b/e2e/modal-navigation-ng/tsconfig.json @@ -0,0 +1,29 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "noEmitHelpers": true, + "noEmitOnError": true, + "lib": [ + "es6", + "dom", + "es2015.iterable" + ], + "baseUrl": ".", + "paths": { + "*": [ + "./node_modules/tns-core-modules/*", + "./node_modules/*" + ], + "~/*": [ + "app/*" + ] + } + }, + "exclude": [ + "node_modules", + "platforms" + ] +} \ No newline at end of file diff --git a/e2e/modal-navigation-ng/webpack.config.js b/e2e/modal-navigation-ng/webpack.config.js new file mode 100644 index 000000000..c0ae70653 --- /dev/null +++ b/e2e/modal-navigation-ng/webpack.config.js @@ -0,0 +1,169 @@ +const { resolve, join } = require("path"); + +const webpack = require("webpack"); +const nsWebpack = require("nativescript-dev-webpack"); +const nativescriptTarget = require("nativescript-dev-webpack/nativescript-target"); +const CopyWebpackPlugin = require("copy-webpack-plugin"); +const ExtractTextPlugin = require("extract-text-webpack-plugin"); +const { BundleAnalyzerPlugin } = require("webpack-bundle-analyzer"); +const { NativeScriptWorkerPlugin } = require("nativescript-worker-loader/NativeScriptWorkerPlugin"); +const UglifyJsPlugin = require("uglifyjs-webpack-plugin"); + +module.exports = env => { + const platform = env && (env.android && "android" || env.ios && "ios"); + if (!platform) { + throw new Error("You need to provide a target platform!"); + } + const platforms = ["ios", "android"]; + const { snapshot, uglify, report, aot } = env; + const ngToolsWebpackOptions = { tsConfigPath: join(__dirname, "tsconfig.json") }; + + const config = { + context: resolve(__dirname, "app"), + watchOptions: { + ignored: [ + resolve(__dirname, "./app/App_Resources"), + // Don't watch hidden files + "**/.*", + ] + }, + target: nativescriptTarget, + entry: { + bundle: aot ? "./main.aot.ts" : "./main.ts", + vendor: "./vendor", + }, + output: { + pathinfo: true, + // Default destination inside platforms//... + path: resolve(nsWebpack.getAppPath(platform)), + libraryTarget: "commonjs2", + filename: "[name].js", + }, + resolve: { + extensions: [".ts", ".js", ".scss", ".css"], + // Resolve {N} system modules from tns-core-modules + modules: [ + "node_modules/tns-core-modules", + "node_modules", + ], + alias: { + '~': resolve("./app") + }, + // don't resolve symlinks to symlinked modules + symlinks: false + }, + resolveLoader: { + // don't resolve symlinks to symlinked loaders + symlinks: false + }, + node: { + // Disable node shims that conflict with NativeScript + "http": false, + "timers": false, + "setImmediate": false, + "fs": "empty", + }, + module: { + rules: [ + { test: /\.html$|\.xml$/, use: "raw-loader" }, + + // tns-core-modules reads the app.css and its imports using css-loader + { + test: /[\/|\\]app\.css$/, + use: { + loader: "css-loader", + options: { minimize: false, url: false }, + } + }, + { + test: /[\/|\\]app\.scss$/, + use: [ + { loader: "css-loader", options: { minimize: false, url: false } }, + "sass-loader" + ] + }, + + // Angular components reference css files and their imports using raw-loader + { test: /\.css$/, exclude: /[\/|\\]app\.css$/, use: "raw-loader" }, + { test: /\.scss$/, exclude: /[\/|\\]app\.scss$/, use: ["raw-loader", "resolve-url-loader", "sass-loader"] }, + + // Compile TypeScript files with ahead-of-time compiler. + { test: /.ts$/, use: [ + "nativescript-dev-webpack/moduleid-compat-loader", + { loader: "@ngtools/webpack", options: ngToolsWebpackOptions }, + ]}, + ], + }, + plugins: [ + // Vendor libs go to the vendor.js chunk + new webpack.optimize.CommonsChunkPlugin({ + name: ["vendor"], + }), + // Define useful constants like TNS_WEBPACK + new webpack.DefinePlugin({ + "global.TNS_WEBPACK": "true", + }), + // Copy assets to out dir. Add your own globs as needed. + new CopyWebpackPlugin([ + { from: "App_Resources/**" }, + { from: "fonts/**" }, + { from: "**/*.jpg" }, + { from: "**/*.png" }, + { from: "**/*.xml" }, + ]), + // Generate a bundle starter script and activate it in package.json + new nsWebpack.GenerateBundleStarterPlugin([ + "./vendor", + "./bundle", + ]), + // Support for web workers since v3.2 + new NativeScriptWorkerPlugin(), + // AngularCompilerPlugin with augmented NativeScript filesystem to handle platform specific resource resolution. + new nsWebpack.NativeScriptAngularCompilerPlugin( + Object.assign({ + entryModule: resolve(__dirname, "app/app.module#AppModule"), + skipCodeGeneration: !aot, + platformOptions: { + platform, + platforms, + // ignore: ["App_Resources"] + }, + }, ngToolsWebpackOptions) + ), + // Does IPC communication with the {N} CLI to notify events when running in watch mode. + new nsWebpack.WatchStateLoggerPlugin(), + ], + }; + if (report) { + // Generate report files for bundles content + config.plugins.push(new BundleAnalyzerPlugin({ + analyzerMode: "static", + openAnalyzer: false, + generateStatsFile: true, + reportFilename: join(__dirname, "report", `report.html`), + statsFilename: join(__dirname, "report", `stats.json`), + })); + } + if (snapshot) { + config.plugins.push(new nsWebpack.NativeScriptSnapshotPlugin({ + chunk: "vendor", + projectRoot: __dirname, + webpackConfig: config, + targetArchs: ["arm", "arm64", "ia32"], + tnsJavaClassesOptions: { packages: ["tns-core-modules" ] }, + useLibs: false + })); + } + if (uglify) { + config.plugins.push(new webpack.LoaderOptionsPlugin({ minimize: true })); + + // Work around an Android issue by setting compress = false + const compress = platform !== "android"; + config.plugins.push(new UglifyJsPlugin({ + uglifyOptions: { + compress, + } + })); + } + return config; +}; diff --git a/e2e/renderer/app/app.module.ngfactory.d.ts b/e2e/renderer/app/app.module.ngfactory.d.ts new file mode 100644 index 000000000..793157de3 --- /dev/null +++ b/e2e/renderer/app/app.module.ngfactory.d.ts @@ -0,0 +1,4 @@ +/** + * A dynamically generated module when compiled with AoT. + */ +export const AppModuleNgFactory: any; \ No newline at end of file diff --git a/e2e/renderer/app/app.module.ts b/e2e/renderer/app/app.module.ts index c5bf7e4dd..92d302565 100644 --- a/e2e/renderer/app/app.module.ts +++ b/e2e/renderer/app/app.module.ts @@ -9,9 +9,11 @@ import { import { AppComponent } from "./app.component"; import { ItemsService } from "./items.service"; -import { rendererTraceCategory, viewUtilCategory } from "nativescript-angular/trace"; -import { setCategories, enable } from "trace"; -setCategories(rendererTraceCategory + "," + viewUtilCategory); +import { rendererTraceCategory, viewUtilCategory, bootstrapCategory } from "nativescript-angular/trace"; +import { addCategories, enable } from "trace"; +addCategories(bootstrapCategory); +// addCategories(rendererTraceCategory); +// addCategories(viewUtilCategory); enable(); @NgModule({ diff --git a/e2e/router-tab-view/.gitignore b/e2e/router-tab-view/.gitignore new file mode 100644 index 000000000..dbb747daa --- /dev/null +++ b/e2e/router-tab-view/.gitignore @@ -0,0 +1,12 @@ +.vscode + +platforms +node_modules +hooks + +/**/*.js +/**/*.map +e2e/reports +test-results.xml + +instrumentscli*.trace \ No newline at end of file diff --git a/e2e/router-tab-view/app/App_Resources/Android/AndroidManifest.xml b/e2e/router-tab-view/app/App_Resources/Android/AndroidManifest.xml new file mode 100644 index 000000000..9db832151 --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/Android/AndroidManifest.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/e2e/router-tab-view/app/App_Resources/Android/app.gradle b/e2e/router-tab-view/app/App_Resources/Android/app.gradle new file mode 100644 index 000000000..095407c3b --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/Android/app.gradle @@ -0,0 +1,16 @@ +// Add your native dependencies here: + +// Uncomment to add recyclerview-v7 dependency +//dependencies { +// compile 'com.android.support:recyclerview-v7:+' +//} + +android { + defaultConfig { + generatedDensities = [] + applicationId = "org.nativescript.routertabview" + } + aaptOptions { + additionalParameters "--no-version-vectors" + } +} diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-hdpi/background.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-hdpi/background.png new file mode 100644 index 000000000..eb381c258 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-hdpi/background.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-hdpi/icon.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-hdpi/icon.png new file mode 100755 index 000000000..9cde84cd5 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-hdpi/icon.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-hdpi/logo.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-hdpi/logo.png new file mode 100644 index 000000000..5218f4c90 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-hdpi/logo.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-ldpi/background.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-ldpi/background.png new file mode 100644 index 000000000..748b2adf5 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-ldpi/background.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-ldpi/icon.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-ldpi/icon.png new file mode 100755 index 000000000..4d6a674b3 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-ldpi/icon.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-ldpi/logo.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-ldpi/logo.png new file mode 100644 index 000000000..b9e102a76 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-ldpi/logo.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-mdpi/background.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-mdpi/background.png new file mode 100644 index 000000000..efeaf2907 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-mdpi/background.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-mdpi/icon.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-mdpi/icon.png new file mode 100755 index 000000000..92ccc85a6 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-mdpi/icon.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-mdpi/logo.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-mdpi/logo.png new file mode 100644 index 000000000..626338766 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-mdpi/logo.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-nodpi/splash_screen.xml b/e2e/router-tab-view/app/App_Resources/Android/drawable-nodpi/splash_screen.xml new file mode 100644 index 000000000..ada77f92c --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/Android/drawable-nodpi/splash_screen.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-xhdpi/background.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-xhdpi/background.png new file mode 100644 index 000000000..612bbd072 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-xhdpi/background.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-xhdpi/icon.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-xhdpi/icon.png new file mode 100644 index 000000000..8bcde6277 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-xhdpi/icon.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-xhdpi/logo.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-xhdpi/logo.png new file mode 100644 index 000000000..ad8ee2f4b Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-xhdpi/logo.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-xxhdpi/background.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-xxhdpi/background.png new file mode 100644 index 000000000..0fa88e235 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-xxhdpi/background.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-xxhdpi/icon.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-xxhdpi/icon.png new file mode 100644 index 000000000..9d81c85dc Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-xxhdpi/icon.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-xxhdpi/logo.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-xxhdpi/logo.png new file mode 100644 index 000000000..668327832 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-xxhdpi/logo.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-xxxhdpi/background.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-xxxhdpi/background.png new file mode 100644 index 000000000..c650f6438 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-xxxhdpi/background.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-xxxhdpi/icon.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-xxxhdpi/icon.png new file mode 100644 index 000000000..9a34d0d43 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-xxxhdpi/icon.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/drawable-xxxhdpi/logo.png b/e2e/router-tab-view/app/App_Resources/Android/drawable-xxxhdpi/logo.png new file mode 100644 index 000000000..fa6331c8d Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/Android/drawable-xxxhdpi/logo.png differ diff --git a/e2e/router-tab-view/app/App_Resources/Android/values-v21/colors.xml b/e2e/router-tab-view/app/App_Resources/Android/values-v21/colors.xml new file mode 100644 index 000000000..a64641a9d --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/Android/values-v21/colors.xml @@ -0,0 +1,4 @@ + + + #3d5afe + \ No newline at end of file diff --git a/e2e/router-tab-view/app/App_Resources/Android/values-v21/styles.xml b/e2e/router-tab-view/app/App_Resources/Android/values-v21/styles.xml new file mode 100644 index 000000000..dac8727c8 --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/Android/values-v21/styles.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/e2e/router-tab-view/app/App_Resources/Android/values/colors.xml b/e2e/router-tab-view/app/App_Resources/Android/values/colors.xml new file mode 100644 index 000000000..74ad8829c --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/Android/values/colors.xml @@ -0,0 +1,7 @@ + + + #F5F5F5 + #757575 + #33B5E5 + #272734 + \ No newline at end of file diff --git a/e2e/router-tab-view/app/App_Resources/Android/values/styles.xml b/e2e/router-tab-view/app/App_Resources/Android/values/styles.xml new file mode 100644 index 000000000..c793e6d4c --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/Android/values/styles.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 000000000..4034b76e6 --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,98 @@ +{ + "images" : [ + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "icon-29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "icon-29@2x.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "icon-29@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon-40@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "icon-40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon-60@2x.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "icon-60@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "icon-29.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "icon-29@2x.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "icon-40.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "icon-40@2x.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon-76.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "icon-76@2x.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "icon-83.5@2x.png", + "scale" : "2x" + }, + { + "size" : "1024x1024", + "idiom" : "ios-marketing", + "filename" : "icon-1024.png", + "scale" : "1x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png new file mode 100644 index 000000000..a1d7eb479 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-1024.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png new file mode 100644 index 000000000..bb9b9e86d Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png new file mode 100644 index 000000000..ec609dcf3 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png new file mode 100644 index 000000000..a97180800 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png new file mode 100644 index 000000000..214800ee6 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png new file mode 100644 index 000000000..8554b88a8 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png new file mode 100644 index 000000000..a22626bae Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png new file mode 100644 index 000000000..a22626bae Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png new file mode 100644 index 000000000..492c9c8e8 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png new file mode 100644 index 000000000..9208113cf Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png new file mode 100644 index 000000000..24415e5a3 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png new file mode 100644 index 000000000..b3ef1bf0c Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/Contents.json b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/Contents.json new file mode 100644 index 000000000..da4a164c9 --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json new file mode 100644 index 000000000..11bfcf55c --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Contents.json @@ -0,0 +1,176 @@ +{ + "images" : [ + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "2436h", + "filename" : "Default-1125h.png", + "minimum-system-version" : "11.0", + "orientation" : "portrait", + "scale" : "3x" + }, + { + "orientation" : "landscape", + "idiom" : "iphone", + "extent" : "full-screen", + "filename" : "Default-Landscape-X.png", + "minimum-system-version" : "11.0", + "subtype" : "2436h", + "scale" : "3x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "736h", + "filename" : "Default-736h@3x.png", + "minimum-system-version" : "8.0", + "orientation" : "portrait", + "scale" : "3x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "736h", + "filename" : "Default-Landscape@3x.png", + "minimum-system-version" : "8.0", + "orientation" : "landscape", + "scale" : "3x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "667h", + "filename" : "Default-667h@2x.png", + "minimum-system-version" : "8.0", + "orientation" : "portrait", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "filename" : "Default@2x.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "extent" : "full-screen", + "idiom" : "iphone", + "subtype" : "retina4", + "filename" : "Default-568h@2x.png", + "minimum-system-version" : "7.0", + "orientation" : "portrait", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "filename" : "Default-Portrait.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "filename" : "Default-Landscape.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "filename" : "Default-Portrait@2x.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "filename" : "Default-Landscape@2x.png", + "extent" : "full-screen", + "minimum-system-version" : "7.0", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "filename" : "Default.png", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "filename" : "Default@2x.png", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "iphone", + "filename" : "Default-568h@2x.png", + "extent" : "full-screen", + "subtype" : "retina4", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "to-status-bar", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "filename" : "Default-Portrait.png", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "to-status-bar", + "scale" : "1x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "filename" : "Default-Landscape.png", + "extent" : "full-screen", + "scale" : "1x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "extent" : "to-status-bar", + "scale" : "2x" + }, + { + "orientation" : "portrait", + "idiom" : "ipad", + "filename" : "Default-Portrait@2x.png", + "extent" : "full-screen", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "extent" : "to-status-bar", + "scale" : "2x" + }, + { + "orientation" : "landscape", + "idiom" : "ipad", + "filename" : "Default-Landscape@2x.png", + "extent" : "full-screen", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-1125h.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-1125h.png new file mode 100644 index 000000000..2913f85d9 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-1125h.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png new file mode 100644 index 000000000..d7f17fcd2 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-568h@2x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png new file mode 100644 index 000000000..b88415405 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-667h@2x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png new file mode 100644 index 000000000..faab4b631 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-736h@3x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-X.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-X.png new file mode 100644 index 000000000..cd94a3ac2 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape-X.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png new file mode 100644 index 000000000..3365ba3cd Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png new file mode 100644 index 000000000..a44945c1a Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@2x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png new file mode 100644 index 000000000..e6dca6269 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Landscape@3x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png new file mode 100644 index 000000000..1a5007962 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png new file mode 100644 index 000000000..73d8b920f Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default-Portrait@2x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png new file mode 100644 index 000000000..9f1f6ce3e Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png new file mode 100644 index 000000000..514fc5cde Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchImage.launchimage/Default@2x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json new file mode 100644 index 000000000..4f4e9c506 --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchScreen-AspectFill.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchScreen-AspectFill@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png new file mode 100644 index 000000000..c293f9c7a Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png new file mode 100644 index 000000000..233693a6e Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.AspectFill.imageset/LaunchScreen-AspectFill@2x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json new file mode 100644 index 000000000..23c0ffd7a --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "LaunchScreen-Center.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "LaunchScreen-Center@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png new file mode 100644 index 000000000..a5a775a2b Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png new file mode 100644 index 000000000..154c19343 Binary files /dev/null and b/e2e/router-tab-view/app/App_Resources/iOS/Assets.xcassets/LaunchScreen.Center.imageset/LaunchScreen-Center@2x.png differ diff --git a/e2e/router-tab-view/app/App_Resources/iOS/Info.plist b/e2e/router-tab-view/app/App_Resources/iOS/Info.plist new file mode 100644 index 000000000..ea3e3ea23 --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/iOS/Info.plist @@ -0,0 +1,47 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleDisplayName + ${PRODUCT_NAME} + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + ${PRODUCT_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleSignature + ???? + CFBundleVersion + 1.0 + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIRequiresFullScreen + + UIRequiredDeviceCapabilities + + armv7 + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff --git a/e2e/router-tab-view/app/App_Resources/iOS/LaunchScreen.storyboard b/e2e/router-tab-view/app/App_Resources/iOS/LaunchScreen.storyboard new file mode 100644 index 000000000..2ad9471e1 --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/iOS/LaunchScreen.storyboard @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/e2e/router-tab-view/app/App_Resources/iOS/build.xcconfig b/e2e/router-tab-view/app/App_Resources/iOS/build.xcconfig new file mode 100644 index 000000000..4b0118490 --- /dev/null +++ b/e2e/router-tab-view/app/App_Resources/iOS/build.xcconfig @@ -0,0 +1,7 @@ +// You can add custom settings here +// for example you can uncomment the following line to force distribution code signing +// CODE_SIGN_IDENTITY = iPhone Distribution +// To build for device with Xcode 8 you need to specify your development team. More info: https://developer.apple.com/library/prerelease/content/releasenotes/DeveloperTools/RN-Xcode/Introduction.html +// DEVELOPMENT_TEAM = YOUR_TEAM_ID; +ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; +ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; diff --git a/e2e/router-tab-view/app/app.component.html b/e2e/router-tab-view/app/app.component.html new file mode 100644 index 000000000..e148fd408 --- /dev/null +++ b/e2e/router-tab-view/app/app.component.html @@ -0,0 +1,13 @@ + + + + + + + \ No newline at end of file diff --git a/e2e/router-tab-view/app/app.component.ts b/e2e/router-tab-view/app/app.component.ts new file mode 100644 index 000000000..e0b5f980e --- /dev/null +++ b/e2e/router-tab-view/app/app.component.ts @@ -0,0 +1,38 @@ +import { Component, OnInit, AfterViewInit, AfterContentInit, ViewChild } from "@angular/core"; +import { TabViewDirective } from "nativescript-angular/directives"; +import { Router, NavigationEnd } from "@angular/router"; +import { NSLocationStrategy } from "nativescript-angular/router/ns-location-strategy"; + + +@Component({ + selector: "ns-app", + templateUrl: "app.component.html", +}) + +export class AppComponent { + private isInitialNavigation = true; + + @ViewChild(TabViewDirective) tabView: TabViewDirective; + + constructor(router: Router, location: NSLocationStrategy) { + router.events.subscribe(e => { + // console.log("[ROUTER]: " + e.toString()); + + if (e instanceof NavigationEnd) { + this.isInitialNavigation = false; + console.log("[ROUTER]: " + e.toString()); + // console.log("[ROUTER] NAVIGATION END. Location history:"); + location._getStates().forEach(state => { + console.log(`[page: ${state.isPageNavigation}] ${state.url}`); + }); + } + }) + } + + onActivate(tabIndex: number) { + // if (!this.isInitialNavigation && this.tabView.selectedIndex !== tabIndex) { + // console.log(`---> onActivate changing tabIndex from: ${this.tabView.selectedIndex} to: ${tabIndex}`); + // this.tabView.selectedIndex = tabIndex; + // } + } +} diff --git a/e2e/router-tab-view/app/app.css b/e2e/router-tab-view/app/app.css new file mode 100644 index 000000000..d23504c4e --- /dev/null +++ b/e2e/router-tab-view/app/app.css @@ -0,0 +1,12 @@ +/* +In NativeScript, the app.css file is where you place CSS rules that +you would like to apply to your entire application. Check out +http://docs.nativescript.org/ui/styling for a full list of the CSS +selectors and properties you can use to style UI components. + +/* +In many cases you may want to use the NativeScript core theme instead +of writing your own CSS rules. For a full list of class names in the theme +refer to http://docs.nativescript.org/ui/theme. +*/ +@import '~nativescript-theme-core/css/core.light.css'; diff --git a/e2e/router-tab-view/app/app.module.ngfactory.d.ts b/e2e/router-tab-view/app/app.module.ngfactory.d.ts new file mode 100644 index 000000000..793157de3 --- /dev/null +++ b/e2e/router-tab-view/app/app.module.ngfactory.d.ts @@ -0,0 +1,4 @@ +/** + * A dynamically generated module when compiled with AoT. + */ +export const AppModuleNgFactory: any; \ No newline at end of file diff --git a/e2e/router-tab-view/app/app.module.ts b/e2e/router-tab-view/app/app.module.ts new file mode 100644 index 000000000..7f98a48a2 --- /dev/null +++ b/e2e/router-tab-view/app/app.module.ts @@ -0,0 +1,44 @@ +import { NgModule, NO_ERRORS_SCHEMA, ErrorHandler } from "@angular/core"; +import { NativeScriptModule } from "nativescript-angular/nativescript.module"; +import { AppRoutingModule, COMPONENTS } from "./app.routing"; +import { AppComponent } from "./app.component"; + +import { DataService } from "./data.service"; + +import { enable as traceEnable, addCategories } from "tns-core-modules/trace"; +import { routerTraceCategory } from "nativescript-angular/trace"; + +// addCategories(routerTraceCategory); +traceEnable(); + +class MyErrorHandler implements ErrorHandler { + handleError(error) { + console.log("### ErrorHandler Error: " + error.toString()); + console.log("### ErrorHandler Stack: " + error.stack); + } +} + +@NgModule({ + bootstrap: [ + AppComponent + ], + imports: [ + NativeScriptModule, + AppRoutingModule + ], + declarations: [ + AppComponent, + ...COMPONENTS + ], + providers: [ + DataService, + { provide: ErrorHandler, useClass: MyErrorHandler } + ], + schemas: [ + NO_ERRORS_SCHEMA + ] +}) +/* +Pass your application module to the bootstrapModule function located in main.ts to start your app +*/ +export class AppModule { } \ No newline at end of file diff --git a/e2e/router-tab-view/app/app.routing.ts b/e2e/router-tab-view/app/app.routing.ts new file mode 100644 index 000000000..64f157a47 --- /dev/null +++ b/e2e/router-tab-view/app/app.routing.ts @@ -0,0 +1,26 @@ +import { NgModule } from "@angular/core"; +import { NativeScriptRouterModule } from "nativescript-angular/router"; +import { Routes } from "@angular/router"; + +import { PlayerComponent } from "./player/players.component"; +import { PlayerDetailComponent } from "./player/player-detail.component"; +import { TeamsComponent } from "./team/teams.component"; +import { TeamDetailComponent } from "./team/team-detail.component"; + +export const COMPONENTS = [PlayerComponent, PlayerDetailComponent, TeamsComponent, TeamDetailComponent]; + +const routes: Routes = [ + { path: "", redirectTo: "/(playerTab:players//teamTab:teams)", pathMatch: "full" }, + + { path: "players", component: PlayerComponent, outlet: "playerTab" }, + { path: "player/:id", component: PlayerDetailComponent, outlet: "playerTab" }, + + { path: "teams", component: TeamsComponent, outlet: "teamTab" }, + { path: "team/:id", component: TeamDetailComponent, outlet: "teamTab" }, +]; + +@NgModule({ + imports: [NativeScriptRouterModule.forRoot(routes)], + exports: [NativeScriptRouterModule], +}) +export class AppRoutingModule {} diff --git a/e2e/router-tab-view/app/data.service.ts b/e2e/router-tab-view/app/data.service.ts new file mode 100644 index 000000000..583a37013 --- /dev/null +++ b/e2e/router-tab-view/app/data.service.ts @@ -0,0 +1,37 @@ +import { Injectable } from "@angular/core"; + +export interface DataItem { + id: number; + name: string; +} + +@Injectable() +export class DataService { + private players = new Array( + { id: 1, name: "Player One" }, + { id: 2, name: "Player Two" }, + { id: 3, name: "Player Three" }, + ); + + private teams = new Array( + { id: 1, name: "Team One" }, + { id: 2, name: "Team Two" }, + { id: 3, name: "Team Three" }, + ); + + getPlayers(): DataItem[] { + return this.players; + } + + getPlayer(id: number): DataItem { + return this.players.filter(item => item.id === id)[0]; + } + + getTeams(): DataItem[] { + return this.teams; + } + + getTeam(id: number): DataItem { + return this.teams.filter(item => item.id === id)[0]; + } +} diff --git a/e2e/router-tab-view/app/main.aot.ts b/e2e/router-tab-view/app/main.aot.ts new file mode 100644 index 000000000..d5ff77a77 --- /dev/null +++ b/e2e/router-tab-view/app/main.aot.ts @@ -0,0 +1,7 @@ +// this import should be first in order to load some required settings (like globals and reflect-metadata) +import { platformNativeScript } from "nativescript-angular/platform-static"; + +// "./app.module.ngfactory" is a dynamically generated module when compiled with AoT. +import { AppModuleNgFactory } from "./app.module.ngfactory"; + +platformNativeScript().bootstrapModuleFactory(AppModuleNgFactory); diff --git a/e2e/router-tab-view/app/main.ts b/e2e/router-tab-view/app/main.ts new file mode 100644 index 000000000..a84cb8844 --- /dev/null +++ b/e2e/router-tab-view/app/main.ts @@ -0,0 +1,10 @@ +// this import should be first in order to load some required settings (like globals and reflect-metadata) +import { platformNativeScriptDynamic } from "nativescript-angular/platform"; + +import { AppModule } from "./app.module"; + +// A traditional NativeScript application starts by initializing global objects, setting up global CSS rules, creating, and navigating to the main page. +// Angular applications need to take care of their own initialization: modules, components, directives, routes, DI providers. +// A NativeScript Angular app needs to make both paradigms work together, so we provide a wrapper platform object, platformNativeScriptDynamic, +// that sets up a NativeScript application and can bootstrap the Angular framework. +platformNativeScriptDynamic().bootstrapModule(AppModule); diff --git a/e2e/router-tab-view/app/package.json b/e2e/router-tab-view/app/package.json new file mode 100644 index 000000000..826903ec1 --- /dev/null +++ b/e2e/router-tab-view/app/package.json @@ -0,0 +1,8 @@ +{ + "android": { + "v8Flags": "--expose_gc" + }, + "main": "main.js", + "name": "tns-template-hello-world-ng", + "version": "3.4.3" +} \ No newline at end of file diff --git a/e2e/router-tab-view/app/player/player-detail.component.html b/e2e/router-tab-view/app/player/player-detail.component.html new file mode 100644 index 000000000..25be11a6d --- /dev/null +++ b/e2e/router-tab-view/app/player/player-detail.component.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/e2e/router-tab-view/app/player/player-detail.component.ts b/e2e/router-tab-view/app/player/player-detail.component.ts new file mode 100644 index 000000000..bc465acef --- /dev/null +++ b/e2e/router-tab-view/app/player/player-detail.component.ts @@ -0,0 +1,31 @@ +import { Component, OnInit } from "@angular/core"; +import { ActivatedRoute } from "@angular/router"; + +import { DataService, DataItem } from "../data.service"; +import { Subscription } from "rxjs/Subscription"; + +@Component({ + selector: "ns-player-details", + moduleId: module.id, + templateUrl: "./player-detail.component.html", +}) +export class PlayerDetailComponent implements OnInit { + item: DataItem; + subscription: Subscription; + + constructor( + private data: DataService, + private route: ActivatedRoute + ) { } + + ngOnInit(): void { + this.subscription = this.route.params.subscribe(params => { + const id = +params["id"]; + this.item = this.data.getPlayer(id); + }) + } + + ngOnDestroy() { + this.subscription.unsubscribe(); + } +} diff --git a/e2e/router-tab-view/app/player/players.component.html b/e2e/router-tab-view/app/player/players.component.html new file mode 100644 index 000000000..532703892 --- /dev/null +++ b/e2e/router-tab-view/app/player/players.component.html @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + diff --git a/e2e/router-tab-view/app/player/players.component.ts b/e2e/router-tab-view/app/player/players.component.ts new file mode 100644 index 000000000..fc9ba8575 --- /dev/null +++ b/e2e/router-tab-view/app/player/players.component.ts @@ -0,0 +1,22 @@ +import { Component, OnInit } from "@angular/core"; +import { DataService, DataItem } from "../data.service"; +import { RouterExtensions } from "nativescript-angular/router"; + +@Component({ + selector: "ns-players", + moduleId: module.id, + templateUrl: "./players.component.html", +}) +export class PlayerComponent implements OnInit { + items: DataItem[]; + + constructor(private itemService: DataService, private router: RouterExtensions) { } + + ngOnInit(): void { + this.items = this.itemService.getPlayers(); + } + + navigateAbs() { + this.router.navigateByUrl("/(playerTab:players//teamTab:team/3)") + } +} \ No newline at end of file diff --git a/e2e/router-tab-view/app/team/team-detail.component.html b/e2e/router-tab-view/app/team/team-detail.component.html new file mode 100644 index 000000000..40d2f72fd --- /dev/null +++ b/e2e/router-tab-view/app/team/team-detail.component.html @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/e2e/router-tab-view/app/team/team-detail.component.ts b/e2e/router-tab-view/app/team/team-detail.component.ts new file mode 100644 index 000000000..383020919 --- /dev/null +++ b/e2e/router-tab-view/app/team/team-detail.component.ts @@ -0,0 +1,31 @@ +import { Component, OnInit } from "@angular/core"; +import { ActivatedRoute } from "@angular/router"; + +import { DataService, DataItem } from "../data.service"; +import { Subscription } from "rxjs/Subscription"; + +@Component({ + selector: "ns-team-details", + moduleId: module.id, + templateUrl: "./team-detail.component.html", +}) +export class TeamDetailComponent implements OnInit { + item: DataItem; + subscription: Subscription; + + constructor( + private data: DataService, + private route: ActivatedRoute + ) { } + + ngOnInit(): void { + this.subscription = this.route.params.subscribe(params => { + const id = +params["id"]; + this.item = this.data.getTeam(id); + }) + } + + ngOnDestroy() { + this.subscription.unsubscribe(); + } +} diff --git a/e2e/router-tab-view/app/team/teams.component.html b/e2e/router-tab-view/app/team/teams.component.html new file mode 100644 index 000000000..dea20ffc7 --- /dev/null +++ b/e2e/router-tab-view/app/team/teams.component.html @@ -0,0 +1,10 @@ + + + + + + + + + diff --git a/e2e/router-tab-view/app/team/teams.component.ts b/e2e/router-tab-view/app/team/teams.component.ts new file mode 100644 index 000000000..119d1d2fe --- /dev/null +++ b/e2e/router-tab-view/app/team/teams.component.ts @@ -0,0 +1,17 @@ +import { Component, OnInit } from "@angular/core"; +import { DataService, DataItem } from "../data.service"; + +@Component({ + selector: "ns-teams", + moduleId: module.id, + templateUrl: "./teams.component.html", +}) +export class TeamsComponent implements OnInit { + items: DataItem[]; + + constructor(private itemService: DataService) { } + + ngOnInit(): void { + this.items = this.itemService.getTeams(); + } +} \ No newline at end of file diff --git a/e2e/router-tab-view/e2e/config/appium.capabilities.json b/e2e/router-tab-view/e2e/config/appium.capabilities.json new file mode 100644 index 000000000..080553981 --- /dev/null +++ b/e2e/router-tab-view/e2e/config/appium.capabilities.json @@ -0,0 +1,106 @@ +{ + "android19": { + "platformName": "Android", + "platformVersion": "4.4", + "deviceName": "Emulator-Api19-Default", + "avd": "Emulator-Api19-Default", + "lt": 60000, + "appActivity": "com.tns.NativeScriptActivity", + "newCommandTimeout": 720, + "noReset": true, + "fullReset": false, + "app": "" + }, + "android21": { + "platformName": "Android", + "platformVersion": "5.0", + "deviceName": "Emulator-Api21-Default", + "avd": "Emulator-Api21-Default", + "lt": 60000, + "appActivity": "com.tns.NativeScriptActivity", + "newCommandTimeout": 720, + "noReset": true, + "fullReset": false, + "app": "" + }, + "android23": { + "platformName": "Android", + "platformVersion": "6.0", + "deviceName": "Emulator-Api23-Default", + "avd": "Emulator-Api23-Default", + "lt": 60000, + "appActivity": "com.tns.NativeScriptActivity", + "newCommandTimeout": 720, + "noReset": true, + "fullReset": false, + "app": "" + }, + "android24": { + "platformName": "Android", + "platformVersion": "7.0", + "deviceName": "Emulator-Api24-Default", + "avd": "Emulator-Api24-Default", + "lt": 60000, + "appActivity": "com.tns.NativeScriptActivity", + "newCommandTimeout": 720, + "noReset": true, + "fullReset": false, + "app": "" + }, + "android25": { + "platformName": "Android", + "platformVersion": "7.1", + "deviceName": "Emulator-Api25-Google", + "avd": "Emulator-Api25-Google", + "lt": 60000, + "appActivity": "com.tns.NativeScriptActivity", + "newCommandTimeout": 720, + "noReset": true, + "fullReset": false, + "app": "" + }, + "android26": { + "platformName": "Android", + "platformVersion": "8.0", + "deviceName": "Emulator-Api26-Google", + "avd": "Emulator-Api26-Google", + "lt": 60000, + "appActivity": "com.tns.NativeScriptActivity", + "newCommandTimeout": 720, + "noReset": true, + "fullReset": false, + "app": "" + }, + "sim.iPhone7.iOS100": { + "platformName": "iOS", + "platformVersion": "10.0", + "deviceName": "iPhone 7 100", + "noReset": true, + "fullReset": false, + "app": "" + }, + "sim.iPhone7.iOS112": { + "platformName": "iOS", + "platformVersion": "11.2", + "deviceName": "iPhone 7", + "noReset": true, + "fullReset": false, + "app": "" + }, + "sim.iPhone8.iOS110": { + "platformName": "iOS", + "platformVersion": "11.0", + "deviceName": "iPhone 8 110", + "noReset": true, + "fullReset": false, + "app": "" + }, + "sim.iPhoneX.iOS110": { + "platformName": "iOS", + "platformVersion": "11.0", + "deviceName": "iPhone X", + "noReset": true, + "fullReset": false, + "app": "" + } +} diff --git a/e2e/router-tab-view/e2e/config/mocha.opts b/e2e/router-tab-view/e2e/config/mocha.opts new file mode 100644 index 000000000..796ec4724 --- /dev/null +++ b/e2e/router-tab-view/e2e/config/mocha.opts @@ -0,0 +1,4 @@ +--timeout 80000 +--recursive e2e +--reporter mocha-multi +--reporter-options spec=-,mocha-junit-reporter=test-results.xml \ No newline at end of file diff --git a/e2e/router-tab-view/e2e/setup.ts b/e2e/router-tab-view/e2e/setup.ts new file mode 100644 index 000000000..8b26e66e9 --- /dev/null +++ b/e2e/router-tab-view/e2e/setup.ts @@ -0,0 +1,9 @@ +import { startServer, stopServer } from "nativescript-dev-appium"; + +before("start server", async () => { + await startServer(); +}); + +after("stop server", async () => { + await stopServer(); +}); diff --git a/e2e/router-tab-view/e2e/tab-view-navigation.e2e-spec.ts b/e2e/router-tab-view/e2e/tab-view-navigation.e2e-spec.ts new file mode 100644 index 000000000..3bafee864 --- /dev/null +++ b/e2e/router-tab-view/e2e/tab-view-navigation.e2e-spec.ts @@ -0,0 +1,193 @@ +import { AppiumDriver, createDriver, SearchOptions } from "nativescript-dev-appium"; +import { assert } from "chai"; + +describe("TabView with page-router-outlet in each tab", () => { + let driver: AppiumDriver; + + before(async () => { + driver = await createDriver(); + }); + + after(async () => { + await driver.quit(); + console.log("Quit driver!"); + }); + + afterEach(async function () { + if (this.currentTest.state === "failed") { + await driver.logScreenshot(this.currentTest.title); + } + }); + + it("should find an tabs by text", async () => { + await driver.findElementByText("Players", SearchOptions.exact); + await driver.findElementByText("Teams", SearchOptions.exact); + await driver.findElementByText("Player List", SearchOptions.exact); + }); + + it("should be able to switch between tabs", async () => { + await driver.findElementByText("Player List", SearchOptions.exact); + + await selectTeamTab(driver); + + await selectPlayerTab(driver); + }); + + it("should go forward and go back on first(player) tab", async () => { + await driver.findElementByText("Player List", SearchOptions.exact); + + await navigateToPlayerItem(driver, "Player One", "1"); + + await driver.navBack(); + await driver.findElementByText("Player List", SearchOptions.exact); + }); + + it("should go forward and go back on second(team) tab", async () => { + await driver.findElementByText("Player List", SearchOptions.exact); + + await selectTeamTab(driver); + + await navigateToTeamItem(driver, "Team Two", "2"); + + await driver.navBack(); + await driver.findElementByText("Team List", SearchOptions.exact); + + await selectPlayerTab(driver); + }); + + it("should navigate first(player) tab, second(team) tab and back in the same order ", async () => { + await driver.findElementByText("Player List", SearchOptions.exact); + + // Go forward in player tab + await navigateToPlayerItem(driver, "Player Three", "3"); + + // Go forward in team tab + await selectTeamTab(driver); + await navigateToTeamItem(driver, "Team One", "1"); + + // Check both tabs + await selectPlayerTab(driver, false); + await selectTeamTab(driver, false); + + // Go back in team tab + await driver.navBack(); + await driver.findElementByText("Team List", SearchOptions.exact); + + // Go back in player tab + await selectPlayerTab(driver, false); + await driver.navBack(); + await driver.findElementByText("Player List", SearchOptions.exact); + }); + + it("should navigate second(team) tab, first(player) and back in the same order ", async () => { + await driver.findElementByText("Player List", SearchOptions.exact); + + // Go forward in team tab + await selectTeamTab(driver); + await navigateToTeamItem(driver, "Team One", "1"); + + // Go forward in player tab + await selectPlayerTab(driver); + await navigateToPlayerItem(driver, "Player Three", "3"); + + // Check both tabs + await selectTeamTab(driver, false); + await selectPlayerTab(driver, false); + + // Go back in player tab + await driver.navBack(); + await driver.findElementByText("Player List", SearchOptions.exact); + + // Go back in team tab + await selectTeamTab(driver, false); + await driver.navBack(); + await driver.findElementByText("Team List", SearchOptions.exact); + + await selectPlayerTab(driver); + }); + + it("should navigate first(player) tab, second(team) tab and back in reverse order ", async () => { + await driver.findElementByText("Player List", SearchOptions.exact); + + // Go forward in player tab + await navigateToPlayerItem(driver, "Player Three", "3"); + + // Go forward in team tab + await selectTeamTab(driver); + await navigateToTeamItem(driver, "Team One", "1"); + + // Go back in player tab + await selectPlayerTab(driver, false); + await driver.navBack(); + await driver.findElementByText("Player List", SearchOptions.exact); + + // Go back in player tab + await selectTeamTab(driver, false); + await driver.findElementByText("1", SearchOptions.exact); + await driver.findElementByText("Team One", SearchOptions.exact); + + await driver.navBack(); + await driver.findElementByText("Team List", SearchOptions.exact); + + await selectPlayerTab(driver); + }); + + it("should navigate second(team) tab, first(player) tab and back in reverse order ", async () => { + await driver.findElementByText("Player List", SearchOptions.exact); + + // Go forward in team tab + await selectTeamTab(driver); + await navigateToTeamItem(driver, "Team One", "1"); + + // Go forward in player tab + await selectPlayerTab(driver); + await navigateToPlayerItem(driver, "Player Three", "3"); + + // Go back in team tab + await selectTeamTab(driver, false); + await driver.navBack(); + await driver.findElementByText("Team List", SearchOptions.exact); + + // Go back in player tab + await selectPlayerTab(driver, false); + await driver.findElementByText("3", SearchOptions.exact); + await driver.findElementByText("Player Three", SearchOptions.exact); + + await driver.navBack(); + await driver.findElementByText("Player List", SearchOptions.exact); + }); + +}); + +async function navigateToTeamItem(driver: AppiumDriver, name: string, id: string) { + const team = await driver.findElementByText(name, SearchOptions.exact); + await team.click(); + await driver.findElementByText("Team Details", SearchOptions.exact); + await driver.findElementByText(id, SearchOptions.exact); + await driver.findElementByText(name, SearchOptions.exact); +} + +async function navigateToPlayerItem(driver: AppiumDriver, name: string, id: string) { + let player = await driver.findElementByText(name, SearchOptions.exact); + await player.click(); + + await driver.findElementByText("Player Details", SearchOptions.exact); + await driver.findElementByText(id, SearchOptions.exact); + await driver.findElementByText(name, SearchOptions.exact); +} + +async function selectTeamTab(driver: AppiumDriver, expectList = true) { + const teamsTab = await driver.findElementByText("Teams", SearchOptions.exact); + await teamsTab.click(); + + const expectedTitle = expectList ? "Team List" : "Team Details"; + await driver.findElementByText(expectedTitle, SearchOptions.exact); +} + +async function selectPlayerTab(driver: AppiumDriver, expectList = true) { + const playerTab = await driver.findElementByText("Players", SearchOptions.exact); + await playerTab.click(); + + const expectedTitle = expectList ? "Player List" : "Player Details"; + await driver.findElementByText(expectedTitle, SearchOptions.exact); +} diff --git a/e2e/router-tab-view/e2e/tsconfig.json b/e2e/router-tab-view/e2e/tsconfig.json new file mode 100644 index 000000000..c297b2347 --- /dev/null +++ b/e2e/router-tab-view/e2e/tsconfig.json @@ -0,0 +1,18 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es6", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "importHelpers": false, + "types": [ + "node", + "mocha", + "chai" + ], + "lib": [ + "es2015", + "dom" + ] + } +} \ No newline at end of file diff --git a/e2e/router-tab-view/package.json b/e2e/router-tab-view/package.json new file mode 100644 index 000000000..08c23c0ca --- /dev/null +++ b/e2e/router-tab-view/package.json @@ -0,0 +1,45 @@ +{ + "description": "NativeScript Application", + "license": "SEE LICENSE IN ", + "readme": "NativeScript Application", + "repository": "", + "nativescript": { + "id": "org.nativescript.routertabview", + "tns-android": { + "version": "3.4.1-2018-02-06-02" + }, + "tns-ios": { + "version": "3.4.1" + } + }, + "dependencies": { + "@angular/animations": "~5.2.0", + "@angular/common": "~5.2.0", + "@angular/compiler": "~5.2.0", + "@angular/core": "~5.2.0", + "@angular/forms": "~5.2.0", + "@angular/http": "~5.2.0", + "@angular/platform-browser": "~5.2.0", + "@angular/platform-browser-dynamic": "~5.2.0", + "@angular/router": "~5.2.0", + "nativescript-angular": "file:../../nativescript-angular", + "nativescript-theme-core": "~1.0.4", + "reflect-metadata": "~0.1.8", + "rxjs": "~5.5.2", + "tns-core-modules": "next", + "zone.js": "~0.8.2" + }, + "devDependencies": { + "babel-traverse": "6.26.0", + "babel-types": "6.26.0", + "babylon": "6.18.0", + "lazy": "1.0.11", + "nativescript-dev-appium": "^3.1.0", + "nativescript-dev-typescript": "~0.6.0", + "typescript": "~2.6.2" + }, + "scripts": { + "e2e": "tsc -p e2e && mocha --opts ./e2e/config/mocha.opts", + "compile-tests": "tsc -p e2e --watch" + } +} diff --git a/e2e/router-tab-view/tsconfig.json b/e2e/router-tab-view/tsconfig.json new file mode 100644 index 000000000..357c35626 --- /dev/null +++ b/e2e/router-tab-view/tsconfig.json @@ -0,0 +1,26 @@ +{ + "compilerOptions": { + "module": "commonjs", + "target": "es5", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "noEmitHelpers": true, + "noEmitOnError": true, + "lib": [ + "es6", + "dom", + "es2015.iterable" + ], + "baseUrl": ".", + "paths": { + "*": [ + "./node_modules/tns-core-modules/*", + "./node_modules/*" + ] + } + }, + "exclude": [ + "node_modules", + "platforms" + ] +} \ No newline at end of file diff --git a/e2e/router/app/app.module.ngfactory.d.ts b/e2e/router/app/app.module.ngfactory.d.ts new file mode 100644 index 000000000..793157de3 --- /dev/null +++ b/e2e/router/app/app.module.ngfactory.d.ts @@ -0,0 +1,4 @@ +/** + * A dynamically generated module when compiled with AoT. + */ +export const AppModuleNgFactory: any; \ No newline at end of file diff --git a/nativescript-angular/app-host-view.ts b/nativescript-angular/app-host-view.ts new file mode 100644 index 000000000..021567e3a --- /dev/null +++ b/nativescript-angular/app-host-view.ts @@ -0,0 +1,6 @@ +import { ContentView } from "tns-core-modules/ui/content-view"; +import { ViewBase } from "tns-core-modules/ui/core/view/view"; + +export class AppHostView extends ContentView { + ngAppRoot: ViewBase; +} diff --git a/nativescript-angular/common.ts b/nativescript-angular/common.ts index c6b119eef..5e2b78745 100644 --- a/nativescript-angular/common.ts +++ b/nativescript-angular/common.ts @@ -12,6 +12,7 @@ import { defaultDeviceProvider, defaultFrameProvider, defaultPageProvider, + FrameService, } from "./platform-providers"; import { NS_DIRECTIVES } from "./directives"; @@ -25,6 +26,7 @@ import { NS_DIRECTIVES } from "./directives"; defaultDeviceProvider, defaultFrameProvider, defaultPageProvider, + FrameService, ], imports: [ CommonModule, diff --git a/nativescript-angular/common/detached-loader.ts b/nativescript-angular/common/detached-loader.ts index d4ae6a73f..214b0caf1 100644 --- a/nativescript-angular/common/detached-loader.ts +++ b/nativescript-angular/common/detached-loader.ts @@ -31,7 +31,7 @@ export class DetachedLoader { // tslint:disable-line:component-class-suffix const componentRef = this.containerRef.createComponent( factory, this.containerRef.length, this.containerRef.parentInjector); - // Component is created, buit may not be checked if we are loading + // Component is created, built may not be checked if we are loading // inside component with OnPush CD strategy. Mark us for check to be sure CD will reach us. // We are inside a promise here so no need for setTimeout - CD should trigger // after the promise. diff --git a/nativescript-angular/directives/dialogs.ts b/nativescript-angular/directives/dialogs.ts index 8012cf1d1..8907f44cb 100644 --- a/nativescript-angular/directives/dialogs.ts +++ b/nativescript-angular/directives/dialogs.ts @@ -10,8 +10,9 @@ import { } from "@angular/core"; import { Page } from "tns-core-modules/ui/page"; -import { View } from "tns-core-modules/ui/core/view"; +import { View, ViewBase } from "tns-core-modules/ui/core/view"; +import { AppHostView } from "../app-host-view"; import { DetachedLoader } from "../common/detached-loader"; import { PageFactory, PAGE_FACTORY } from "../platform-providers"; @@ -35,7 +36,7 @@ interface ShowDialogOptions { doneCallback; fullscreen: boolean; pageFactory: PageFactory; - parentPage: Page; + parentView: ViewBase; resolver: ComponentFactoryResolver; type: Type; } @@ -43,7 +44,7 @@ interface ShowDialogOptions { @Injectable() export class ModalDialogService { public showModal(type: Type, - {viewContainerRef, moduleRef, context, fullscreen}: ModalDialogOptions + { viewContainerRef, moduleRef, context, fullscreen }: ModalDialogOptions ): Promise { if (!viewContainerRef) { throw new Error( @@ -52,11 +53,15 @@ export class ModalDialogService { ); } - const parentPage: Page = viewContainerRef.injector.get(Page); + let parentView = viewContainerRef.element.nativeElement; + if (parentView instanceof AppHostView && parentView.ngAppRoot) { + parentView = parentView.ngAppRoot; + } + const pageFactory: PageFactory = viewContainerRef.injector.get(PAGE_FACTORY); // resolve from particular module (moduleRef) - // or from same module as parentPage (viewContainerRef) + // or from same module as parentView (viewContainerRef) const componentContainer = moduleRef || viewContainerRef; const resolver = componentContainer.injector.get(ComponentFactoryResolver); @@ -67,7 +72,7 @@ export class ModalDialogService { doneCallback: resolve, fullscreen, pageFactory, - parentPage, + parentView, resolver, type, }), 10); @@ -80,7 +85,7 @@ export class ModalDialogService { doneCallback, fullscreen, pageFactory, - parentPage, + parentView, resolver, type, }: ShowDialogOptions): void { @@ -113,7 +118,7 @@ export class ModalDialogService { } page.content = componentView; - parentPage.showModal(page, context, closeCallback, fullscreen); + parentView.showModal(page, context, closeCallback, fullscreen); }); } } diff --git a/nativescript-angular/element-registry.ts b/nativescript-angular/element-registry.ts index 3a86b93f2..41a1eaf30 100644 --- a/nativescript-angular/element-registry.ts +++ b/nativescript-angular/element-registry.ts @@ -1,5 +1,7 @@ import { View } from "tns-core-modules/ui/core/view"; import { LayoutBase } from "tns-core-modules/ui/layouts/layout-base"; +import { Page } from "tns-core-modules/ui/page"; +import { Frame } from "tns-core-modules/ui/frame"; export type NgView = (View & ViewExtensions); @@ -157,6 +159,19 @@ export function getSingleViewRecursive(nodes: Array, nestLevel: number): Vi return rootLayout; } +const frameMeta: ViewClassMeta = { + insertChild: (parent: Frame, child: NgView, next: any) => { + // Page cannot be added to Frame with _addChildFromBuilder (trows "use defaultPage" error) + if (isInvisibleNode(child)) { + return; + } else if (child instanceof Page) { + parent.navigate({ create: () => child }); + } else { + throw new Error("Only a Page can be a child of Frame"); + } + } +}; + // Register default NativeScript components // Note: ActionBar related components are registerd together with action-bar directives. registerElement("AbsoluteLayout", () => require("tns-core-modules/ui/layouts/absolute-layout").AbsoluteLayout); @@ -166,6 +181,7 @@ registerElement("Button", () => require("tns-core-modules/ui/button").Button); registerElement("ContentView", () => require("tns-core-modules/ui/content-view").ContentView); registerElement("DatePicker", () => require("tns-core-modules/ui/date-picker").DatePicker); registerElement("DockLayout", () => require("tns-core-modules/ui/layouts/dock-layout").DockLayout); +registerElement("Frame", () => require("tns-core-modules/ui/frame").Frame, frameMeta); registerElement("GridLayout", () => require("tns-core-modules/ui/layouts/grid-layout").GridLayout); registerElement("HtmlView", () => require("tns-core-modules/ui/html-view").HtmlView); registerElement("Image", () => require("tns-core-modules/ui/image").Image); @@ -198,3 +214,5 @@ registerElement("Span", () => require("tns-core-modules/text/span").Span); registerElement("DetachedContainer", () => require("tns-core-modules/ui/proxy-view-container").ProxyViewContainer, { skipAddToDom: true }); + +registerElement("page-router-outlet", () => require("tns-core-modules/ui/frame").Frame); diff --git a/nativescript-angular/package.json b/nativescript-angular/package.json index 39c4e6608..3eb35f4db 100644 --- a/nativescript-angular/package.json +++ b/nativescript-angular/package.json @@ -29,9 +29,10 @@ "url": "https://github.com/NativeScript/nativescript-angular.git" }, "scripts": { - "tslint": "tslint --project tsconfig.json --config tslint.json --type-check", + "tslint": "tslint --project tsconfig.json --config tslint.json", "postinstall": "node postinstall.js", "tsc": "tsc -p tsconfig.json", + "tsc-w": "tsc -p tsconfig.json -w", "ngc": "ngc -p tsconfig.json", "prepare": "npm run ngc" }, @@ -52,7 +53,7 @@ "@angular/platform-browser": "~5.2.0", "@angular/router": "~5.2.0", "rxjs": "^5.5.0", - "tns-core-modules": "^3.4.0 || >4.0.0-", + "tns-core-modules": "^4.0.0 || >4.0.0- || >4.1.0-", "zone.js": "^0.8.4", "typescript": "~2.6.2" }, diff --git a/nativescript-angular/platform-common.ts b/nativescript-angular/platform-common.ts index 30f7d6f66..935abf880 100644 --- a/nativescript-angular/platform-common.ts +++ b/nativescript-angular/platform-common.ts @@ -6,7 +6,7 @@ import "./zone-js/dist/zone-nativescript"; import "reflect-metadata"; import "./polyfills/array"; import "./polyfills/console"; -import { profile, log, uptime } from "tns-core-modules/profiling"; +import { profile, uptime } from "tns-core-modules/profiling"; import { Type, @@ -18,27 +18,30 @@ import { EventEmitter, Sanitizer, InjectionToken, - StaticProvider + StaticProvider, } from "@angular/core"; import { DOCUMENT } from "@angular/common"; -import { rendererLog, rendererError } from "./trace"; -import { - PAGE_FACTORY, - PageFactory, - defaultPageFactoryProvider, - setRootPage -} from "./platform-providers"; +import { bootstrapLog, bootstrapLogError } from "./trace"; +import { defaultPageFactoryProvider, setRootPage } from "./platform-providers"; +import { AppHostView } from "./app-host-view"; -import { start, setCssFileName } from "tns-core-modules/application"; -import { topmost, NavigationEntry } from "tns-core-modules/ui/frame"; -import { Page } from "tns-core-modules/ui/page"; +import { + setCssFileName, + run as applicationRun, + _resetRootView as applicationRerun, + on, + off, + launchEvent, + LaunchEventData, +} from "tns-core-modules/application"; import { TextView } from "tns-core-modules/ui/text-view"; import "nativescript-intl"; +import { Color, View } from "tns-core-modules/ui/core/view/view"; export const onBeforeLivesync = new EventEmitter>(); -export const onAfterLivesync = new EventEmitter>(); +export const onAfterLivesync = new EventEmitter<{ moduleRef?: NgModuleRef; error?: Error }>(); let lastBootstrappedModule: WeakRef>; type BootstrapperAction = () => Promise>; @@ -65,7 +68,7 @@ export class NativeScriptSanitizer extends Sanitizer { // Add a fake polyfill for the document object (global).document = (global).document || {}; const doc = (global).document; -doc.body = Object.assign((doc.body || {}), { +doc.body = Object.assign(doc.body || {}, { isOverride: true, }); @@ -84,7 +87,7 @@ export const COMMON_PROVIDERS = [ export class NativeScriptPlatformRef extends PlatformRef { private _bootstrapper: BootstrapperAction; - constructor(private platform: PlatformRef, private appOptions?: AppOptions) { + constructor(private platform: PlatformRef, private appOptions: AppOptions = {}) { super(); } @@ -101,7 +104,7 @@ export class NativeScriptPlatformRef extends PlatformRef { bootstrapModule( moduleType: Type, compilerOptions: CompilerOptions | CompilerOptions[] = [] - ): Promise> { + ): Promise> { this._bootstrapper = () => this.platform.bootstrapModule(moduleType, compilerOptions); this.bootstrapApp(); @@ -111,39 +114,15 @@ export class NativeScriptPlatformRef extends PlatformRef { @profile private bootstrapApp() { - (global).__onLiveSyncCore = () => this.livesyncModule(); - - const mainPageEntry = this.createNavigationEntry(this._bootstrapper); + (global).__onLiveSyncCore = () => { + this.livesync(); + }; if (this.appOptions && typeof this.appOptions.cssFile === "string") { - // TODO: All exported fields in ES6 modules should be read-only - // Change the case when tns-core-modules become ES6 compatible and there is a legal way to set cssFile setCssFileName(this.appOptions.cssFile); } - start(mainPageEntry); - } - - livesyncModule(): void { - rendererLog("ANGULAR LiveSync Started"); - - onBeforeLivesync.next(lastBootstrappedModule ? lastBootstrappedModule.get() : null); - - const mainPageEntry = this.createNavigationEntry( - this._bootstrapper, - compRef => onAfterLivesync.next(compRef), - error => onAfterLivesync.error(error), - true - ); - mainPageEntry.animated = false; - mainPageEntry.clearHistory = true; - const frame = topmost(); - if (frame) { - if (frame.currentPage && frame.currentPage.modal) { - frame.currentPage.modal.closeModal(); - } - frame.navigate(mainPageEntry); - } + this.bootstrapNativeScriptApp(); } onDestroy(callback: () => void): void { @@ -163,75 +142,116 @@ export class NativeScriptPlatformRef extends PlatformRef { } @profile - private createNavigationEntry( - bootstrapAction: BootstrapperAction, - resolve?: (comp: NgModuleRef) => void, - reject?: (e: Error) => void, - isLivesync: boolean = false, - isReboot: boolean = false): NavigationEntry { - - const pageFactory: PageFactory = this.platform.injector.get(PAGE_FACTORY); - - const navEntry: NavigationEntry = { - create: (): Page => { - const page = pageFactory({ isBootstrap: true, isLivesync }); - setRootPage(page); - if (this.appOptions) { - page.actionBarHidden = this.appOptions.startPageActionBarHidden; - } - - const initHandlerMethodName = - "nativescript-angular/platform-common.initHandler"; - const initHandler = profile(initHandlerMethodName, () => { - page.off(Page.navigatingToEvent, initHandler); - // profiling.stop("application-start"); - rendererLog("Page loaded"); - - // profiling.start("ng-bootstrap"); - rendererLog("BOOTSTRAPPING..."); - - const bootstrapMethodName = - "nativescript-angular/platform-common.postBootstrapAction"; - bootstrapAction().then(profile(bootstrapMethodName, moduleRef => { - // profiling.stop("ng-bootstrap"); - log(`ANGULAR BOOTSTRAP DONE. ${uptime()}`); + private bootstrapNativeScriptApp() { + // Create a temp page for root of the renderer + const tempAppHostView = new AppHostView(); + setRootPage(tempAppHostView); + let rootContent: View; + + bootstrapLog("NativeScriptPlatform bootstrap started."); + const launchCallback = profile( + "nativescript-angular/platform-common.launchCallback", + (args: LaunchEventData) => { + bootstrapLog("Application launch event fired"); + off(launchEvent, launchCallback); + + let bootstrapPromiseCompleted = false; + this._bootstrapper().then( + moduleRef => { + bootstrapPromiseCompleted = true; + + bootstrapLog(`Angular bootstrap bootstrap done. uptime: ${uptime()}`); + rootContent = tempAppHostView.content; + tempAppHostView.content = null; + tempAppHostView.ngAppRoot = rootContent; + rootContent.parentNode = tempAppHostView; lastBootstrappedModule = new WeakRef(moduleRef); + }, + err => { + bootstrapPromiseCompleted = true; - if (resolve) { - resolve(moduleRef); - } - return moduleRef; - }), err => { - rendererError("ERROR BOOTSTRAPPING ANGULAR"); const errorMessage = err.message + "\n\n" + err.stack; - rendererError(errorMessage); + bootstrapLogError("ERROR BOOTSTRAPPING ANGULAR"); + bootstrapLogError(errorMessage); - let view = new TextView(); - view.text = errorMessage; - page.content = view; + rootContent = this.createErrorUI(errorMessage); + } + ); - if (reject) { - reject(err); - } - }); + bootstrapLog("bootstrapAction called, draining micro tasks queue. Root: " + rootContent); + (global).Zone.drainMicroTaskQueue(); + bootstrapLog("bootstrapAction called, draining micro tasks queue finished! Root: " + rootContent); - (global).Zone.drainMicroTaskQueue(); - }); + if (!bootstrapPromiseCompleted) { + const errorMessage = "Bootstrap promise didn't resolve"; + bootstrapLogError(errorMessage); + rootContent = this.createErrorUI(errorMessage); + } - page.on(Page.navigatingToEvent, initHandler); + args.root = rootContent; + } + ); + on(launchEvent, launchCallback); + + applicationRun(); + } + + @profile + private livesync() { + bootstrapLog("Angular livesync started."); + + onBeforeLivesync.next(lastBootstrappedModule ? lastBootstrappedModule.get() : null); - return page; + const tempAppHostView = new AppHostView(); + setRootPage(tempAppHostView); + let rootContent: View; + + let bootstrapPromiseCompleted = false; + this._bootstrapper().then( + moduleRef => { + bootstrapPromiseCompleted = true; + bootstrapLog("Angular livesync done."); + onAfterLivesync.next({ moduleRef }); + + rootContent = tempAppHostView.content; + tempAppHostView.content = null; + tempAppHostView.ngAppRoot = rootContent; + rootContent.parentNode = tempAppHostView; + lastBootstrappedModule = new WeakRef(moduleRef); }, - animated: false - }; + error => { + bootstrapPromiseCompleted = true; + bootstrapLogError("ERROR LIVESYNC BOOTSTRAPPING ANGULAR"); + const errorMessage = error.message + "\n\n" + error.stack; + bootstrapLogError(errorMessage); + + rootContent = this.createErrorUI(errorMessage); + + onAfterLivesync.next({ error }); + } + ); + + bootstrapLog("livesync bootstrapAction called, draining micro tasks queue. Root: " + rootContent); + (global).Zone.drainMicroTaskQueue(); + bootstrapLog("livesync bootstrapAction called, draining micro tasks queue finished! Root: " + rootContent); + + if (!bootstrapPromiseCompleted) { + const errorMessage = "Livesync bootstrap promise didn't resolve"; + bootstrapLogError(errorMessage); + rootContent = this.createErrorUI(errorMessage); - if (isReboot) { - navEntry.clearHistory = true; + onAfterLivesync.next({ error: new Error(errorMessage) }); } - return navEntry; + applicationRerun({ + create: () => rootContent, + }); } - liveSyncApp() { + private createErrorUI(message: string): View { + const errorTextBox = new TextView(); + errorTextBox.text = message; + errorTextBox.color = new Color("red"); + return errorTextBox; } } diff --git a/nativescript-angular/platform-providers.ts b/nativescript-angular/platform-providers.ts index 86d47e0a2..fa58beb80 100644 --- a/nativescript-angular/platform-providers.ts +++ b/nativescript-angular/platform-providers.ts @@ -1,4 +1,4 @@ -import { InjectionToken } from "@angular/core"; +import { InjectionToken, Injectable } from "@angular/core"; import { topmost, Frame } from "tns-core-modules/ui/frame"; import { View } from "tns-core-modules/ui/core/view"; @@ -53,3 +53,11 @@ export const defaultPageFactory: PageFactory = function (_opts: PageFactoryOptio return new Page(); }; export const defaultPageFactoryProvider = { provide: PAGE_FACTORY, useValue: defaultPageFactory }; + +@Injectable() +export class FrameService { + // TODO: Add any methods that are needed to handle frame/page navigation + getFrame(): Frame { + return topmost(); + } +} diff --git a/nativescript-angular/renderer.ts b/nativescript-angular/renderer.ts index 405f1c91d..35d379a6c 100644 --- a/nativescript-angular/renderer.ts +++ b/nativescript-angular/renderer.ts @@ -7,7 +7,6 @@ import { import { Device } from "tns-core-modules/platform"; import { View } from "tns-core-modules/ui/core/view"; import { addCss } from "tns-core-modules/application"; -import { topmost } from "tns-core-modules/ui/frame"; import { profile } from "tns-core-modules/profiling"; import { APP_ROOT_VIEW, DEVICE, getRootPage } from "./platform-providers"; @@ -46,7 +45,7 @@ export class NativeScriptRendererFactory implements RendererFactory2 { private setRootNgView(rootView: any) { if (!rootView) { - rootView = getRootPage() || topmost().currentPage; + rootView = getRootPage(); } rootView.nodeName = "NONE"; diff --git a/nativescript-angular/router/ns-location-strategy.ts b/nativescript-angular/router/ns-location-strategy.ts index c474f2a24..ca26635e8 100644 --- a/nativescript-angular/router/ns-location-strategy.ts +++ b/nativescript-angular/router/ns-location-strategy.ts @@ -1,8 +1,9 @@ import { Injectable } from "@angular/core"; import { LocationStrategy } from "@angular/common"; import { routerLog } from "../trace"; -import { Frame, NavigationTransition } from "tns-core-modules/ui/frame"; +import { NavigationTransition } from "tns-core-modules/ui/frame"; import { isPresent } from "../lang-facade"; +import { FrameService } from "../platform-providers"; export interface NavigationOptions { clearHistory?: boolean; @@ -31,7 +32,7 @@ export class NSLocationStrategy extends LocationStrategy { private _isPageNavigationBack = false; private _currentNavigationOptions: NavigationOptions; - constructor(private frame: Frame) { + constructor(private frameService: FrameService) { super(); routerLog("NSLocationStrategy.constructor()"); } @@ -105,7 +106,8 @@ export class NSLocationStrategy extends LocationStrategy { // This was a page navigation - so navigate through frame. routerLog("NSLocationStrategy.back() while not navigating back but top" + " state is page - will call frame.goBack()"); - this.frame.goBack(); + const frame = this.frameService.getFrame(); + frame.goBack(); } else { // Nested navigation - just pop the state routerLog("NSLocationStrategy.back() while not navigating back but top" + diff --git a/nativescript-angular/router/ns-router-link.ts b/nativescript-angular/router/ns-router-link.ts index 0a5bfed50..c6b220151 100644 --- a/nativescript-angular/router/ns-router-link.ts +++ b/nativescript-angular/router/ns-router-link.ts @@ -1,13 +1,15 @@ -import { Directive, HostListener, Input, Optional, OnChanges } from "@angular/core"; +import { Directive, HostListener, Input } from "@angular/core"; import { NavigationExtras } from "@angular/router"; import { ActivatedRoute, Router, UrlTree } from "@angular/router"; import { routerLog } from "../trace"; -import { PageRoute } from "./page-router-outlet"; import { RouterExtensions } from "./router-extensions"; import { NavigationOptions } from "./ns-location-strategy"; import { NavigationTransition } from "tns-core-modules/ui/frame"; import { isString } from "tns-core-modules/utils/types"; +// Copied from "@angular/router/src/config" +export type QueryParamsHandling = "merge" | "preserve" | ""; + /** * The nsRouterLink directive lets you link to specific parts of your app. * @@ -33,30 +35,27 @@ import { isString } from "tns-core-modules/utils/types"; * And if the segment begins with `../`, the router will go up one level. */ @Directive({ selector: "[nsRouterLink]" }) -export class NSRouterLink implements OnChanges { // tslint:disable-line:directive-class-suffix - private commands: any[] = []; +export class NSRouterLink { // tslint:disable-line:directive-class-suffix @Input() target: string; @Input() queryParams: { [k: string]: any }; @Input() fragment: string; + @Input() queryParamsHandling: QueryParamsHandling; + @Input() preserveQueryParams: boolean; + @Input() preserveFragment: boolean; + @Input() skipLocationChange: boolean; + @Input() replaceUrl: boolean; + @Input() clearHistory: boolean; @Input() pageTransition: boolean | string | NavigationTransition = true; + @Input() pageTransitionDuration; - urlTree: UrlTree; - - private usePageRoute: boolean; - - private get currentRoute(): ActivatedRoute { - return this.usePageRoute ? this.pageRoute.activatedRoute.getValue() : this.route; - } + private commands: any[] = []; constructor( private router: Router, private navigator: RouterExtensions, - private route: ActivatedRoute, - @Optional() private pageRoute: PageRoute) { - - this.usePageRoute = (this.pageRoute && this.route === this.pageRoute.activatedRoute.getValue()); + private route: ActivatedRoute) { } @Input("nsRouterLink") @@ -68,12 +67,12 @@ export class NSRouterLink implements OnChanges { // tslint:disable-line:directiv } } - @HostListener("tap") onTap() { - routerLog("nsRouterLink.tapped: " + this.commands + " usePageRoute: " + - this.usePageRoute + " clearHistory: " + this.clearHistory + " transition: " + - JSON.stringify(this.pageTransition)); + routerLog(`nsRouterLink.tapped: ${this.commands} ` + + `clear: ${this.clearHistory} ` + + `transition: ${JSON.stringify(this.pageTransition)} ` + + `duration: ${this.pageTransitionDuration}`); const extras = this.getExtras(); this.navigator.navigateByUrl(this.urlTree, extras); @@ -82,43 +81,62 @@ export class NSRouterLink implements OnChanges { // tslint:disable-line:directiv private getExtras(): NavigationExtras & NavigationOptions { const transition = this.getTransition(); return { - queryParams: this.queryParams, - fragment: this.fragment, + skipLocationChange: attrBoolValue(this.skipLocationChange), + replaceUrl: attrBoolValue(this.replaceUrl), + clearHistory: this.convertClearHistory(this.clearHistory), animated: transition.animated, transition: transition.transition, - relativeTo: this.currentRoute, }; } + get urlTree(): UrlTree { + const urlTree = this.router.createUrlTree(this.commands, { + relativeTo: this.route, + queryParams: this.queryParams, + fragment: this.fragment, + preserveQueryParams: attrBoolValue(this.preserveQueryParams), + queryParamsHandling: this.queryParamsHandling, + preserveFragment: attrBoolValue(this.preserveFragment), + }); + + routerLog(`nsRouterLink urlTree created: ${urlTree}`); + + return urlTree; + } + + private convertClearHistory(value: boolean | string): boolean { return value === true || value === "true"; } private getTransition(): { animated: boolean, transition?: NavigationTransition } { + let transition: NavigationTransition = {}; + let animated: boolean; + if (typeof this.pageTransition === "boolean") { - return { animated: this.pageTransition }; + animated = this.pageTransition; } else if (isString(this.pageTransition)) { if (this.pageTransition === "none" || this.pageTransition === "false") { - return { animated: false }; + animated = false; } else { - return { animated: true, transition: { name: this.pageTransition } }; + animated = true; + transition.name = this.pageTransition; } } else { - return { - animated: true, - transition: this.pageTransition - }; + animated = true; + transition = this.pageTransition; } - } - ngOnChanges(_: {}): any { - this.updateUrlTree(); - } + let duration = +this.pageTransitionDuration; + if (!isNaN(duration)) { + transition.duration = duration; + } - private updateUrlTree(): void { - this.urlTree = this.router.createUrlTree( - this.commands, - { relativeTo: this.currentRoute, queryParams: this.queryParams, fragment: this.fragment }); + return { animated, transition }; } } + +function attrBoolValue(s: any): boolean { + return s === "" || !!s; +} diff --git a/nativescript-angular/router/page-router-outlet.ts b/nativescript-angular/router/page-router-outlet.ts index 3737dd7d5..f053218ce 100644 --- a/nativescript-angular/router/page-router-outlet.ts +++ b/nativescript-angular/router/page-router-outlet.ts @@ -3,7 +3,7 @@ import { ComponentFactory, ComponentFactoryResolver, ComponentRef, Directive, Inject, InjectionToken, Injector, OnDestroy, OnInit, EventEmitter, Output, - Type, ViewContainerRef, + Type, ViewContainerRef, ElementRef } from "@angular/core"; import { ActivatedRoute, @@ -105,12 +105,11 @@ function routeToString(activatedRoute: ActivatedRoute | ActivatedRouteSnapshot): export class PageRouterOutlet implements OnDestroy, OnInit { // tslint:disable-line:directive-class-suffix private activated: ComponentRef | null = null; private _activatedRoute: ActivatedRoute | null = null; - - private isInitialPage: boolean = true; private detachedLoaderFactory: ComponentFactory; private name: string; private viewUtil: ViewUtil; + private frame: Frame; @Output("activate") activateEvents = new EventEmitter(); // tslint:disable-line:no-output-rename @Output("deactivate") deactivateEvents = new EventEmitter(); // tslint:disable-line:no-output-rename @@ -146,12 +145,14 @@ export class PageRouterOutlet implements OnDestroy, OnInit { // tslint:disable-l private locationStrategy: NSLocationStrategy, private componentFactoryResolver: ComponentFactoryResolver, private resolver: ComponentFactoryResolver, - private frame: Frame, private changeDetector: ChangeDetectorRef, @Inject(DEVICE) device: Device, @Inject(PAGE_FACTORY) private pageFactory: PageFactory, - private routeReuseStrategy: NSRouteReuseStrategy + private routeReuseStrategy: NSRouteReuseStrategy, + elRef: ElementRef ) { + this.frame = elRef.nativeElement; + log("PageRouterOutlet.constructor frame:" + this.frame); this.name = name || PRIMARY_OUTLET; parentContexts.onChildOutletCreated(this.name, this); @@ -265,56 +266,31 @@ export class PageRouterOutlet implements OnDestroy, OnInit { // tslint:disable-l activatedRoute: ActivatedRoute, loadedResolver: ComponentFactoryResolver ): void { + log("PageRouterOutlet.activate() forward navigation - " + + "create detached loader in the loader container"); - const pageRoute = new PageRoute(activatedRoute); - const providers = this.initProvidersMap(activatedRoute, pageRoute); - - const childInjector = new ChildInjector(providers, this.location.injector); const factory = this.getComponentFactory(activatedRoute, loadedResolver); - - if (this.isInitialPage) { - log("PageRouterOutlet.activate() initial page - just load component"); - - this.isInitialPage = false; - - this.activated = this.location.createComponent( - factory, this.location.length, childInjector, []); - this.changeDetector.markForCheck(); - } else { - log("PageRouterOutlet.activate() forward navigation - " + - "create detached loader in the loader container"); - - const page = this.pageFactory({ - isNavigation: true, - componentType: factory.componentType, - }); - - providers.set(Page, page); - - const loaderRef = this.location.createComponent( - this.detachedLoaderFactory, this.location.length, childInjector, []); - this.changeDetector.markForCheck(); - - this.activated = loaderRef.instance.loadWithFactory(factory); - this.loadComponentInPage(page, this.activated); - - this.activated[loaderRefSymbol] = loaderRef; - } - } - - private initProvidersMap( - activatedRoute: ActivatedRoute, - pageRoute: PageRoute - ): ProviderMap { + const page = this.pageFactory({ + isNavigation: true, + componentType: factory.componentType, + }); const providers = new Map(); - providers.set(PageRoute, pageRoute); + providers.set(Page, page); + providers.set(Frame, this.frame); + providers.set(PageRoute, new PageRoute(activatedRoute)); providers.set(ActivatedRoute, activatedRoute); + providers.set(ChildrenOutletContexts, this.parentContexts.getOrCreateContext(this.name).children); + + const childInjector = new ChildInjector(providers, this.location.injector); + const loaderRef = this.location.createComponent( + this.detachedLoaderFactory, this.location.length, childInjector, []); + this.changeDetector.markForCheck(); - const childContexts = this.parentContexts.getOrCreateContext(this.name).children; - providers.set(ChildrenOutletContexts, childContexts); + this.activated = loaderRef.instance.loadWithFactory(factory); + this.loadComponentInPage(page, this.activated); - return providers; + this.activated[loaderRefSymbol] = loaderRef; } @profile diff --git a/nativescript-angular/router/router-extensions.ts b/nativescript-angular/router/router-extensions.ts index aa16e3649..9f12dcb67 100644 --- a/nativescript-angular/router/router-extensions.ts +++ b/nativescript-angular/router/router-extensions.ts @@ -1,7 +1,7 @@ import { Injectable } from "@angular/core"; import { Router, UrlTree, NavigationExtras } from "@angular/router"; import { NSLocationStrategy, NavigationOptions } from "./ns-location-strategy"; -import { Frame } from "tns-core-modules/ui/frame"; +import { FrameService } from "../platform-providers"; export type ExtendedNavigationExtras = NavigationExtras & NavigationOptions; @@ -11,7 +11,7 @@ export class RouterExtensions { constructor( public router: Router, public locationStrategy: NSLocationStrategy, - public frame: Frame + public frameService: FrameService ) { } public navigate(commands: any[], extras?: ExtendedNavigationExtras): Promise { @@ -37,10 +37,10 @@ export class RouterExtensions { } public backToPreviousPage() { - this.frame.goBack(); + this.frameService.getFrame().goBack(); } public canGoBackToPreviousPage(): boolean { - return this.frame.canGoBack(); + return this.frameService.getFrame().canGoBack(); } } diff --git a/nativescript-angular/router/router.module.ts b/nativescript-angular/router/router.module.ts index 066c437d0..d1dad1335 100644 --- a/nativescript-angular/router/router.module.ts +++ b/nativescript-angular/router/router.module.ts @@ -1,13 +1,6 @@ -import { - NgModule, - ModuleWithProviders, - NO_ERRORS_SCHEMA, - Optional, - SkipSelf, -} from "@angular/core"; +import { NgModule, ModuleWithProviders, NO_ERRORS_SCHEMA, Optional, SkipSelf } from "@angular/core"; import { RouterModule, Routes, ExtraOptions, RouteReuseStrategy } from "@angular/router"; import { LocationStrategy, PlatformLocation } from "@angular/common"; -import { Frame } from "tns-core-modules/ui/frame"; import { NSRouterLink } from "./ns-router-link"; import { NSRouterLinkActive } from "./ns-router-link-active"; import { PageRouterOutlet } from "./page-router-outlet"; @@ -16,6 +9,7 @@ import { NativescriptPlatformLocation } from "./ns-platform-location"; import { NSRouteReuseStrategy } from "./ns-route-reuse-strategy"; import { RouterExtensions } from "./router-extensions"; import { NativeScriptCommonModule } from "../common"; +import { FrameService } from "../platform-providers"; export { PageRoute } from "./page-router-outlet"; export { RouterExtensions } from "./router-extensions"; @@ -23,35 +17,23 @@ export { NSModuleFactoryLoader } from "./ns-module-factory-loader"; export type LocationState = LocationState; @NgModule({ - declarations: [ - NSRouterLink, - NSRouterLinkActive, - PageRouterOutlet - ], + declarations: [NSRouterLink, NSRouterLinkActive, PageRouterOutlet], providers: [ { provide: NSLocationStrategy, useFactory: provideLocationStrategy, - deps: [[NSLocationStrategy, new Optional(), new SkipSelf()], Frame] + deps: [[NSLocationStrategy, new Optional(), new SkipSelf()], FrameService], }, { provide: LocationStrategy, useExisting: NSLocationStrategy }, NativescriptPlatformLocation, { provide: PlatformLocation, useClass: NativescriptPlatformLocation }, RouterExtensions, NSRouteReuseStrategy, - { provide: RouteReuseStrategy, useExisting: NSRouteReuseStrategy } - ], - imports: [ - RouterModule, - NativeScriptCommonModule, - ], - exports: [ - RouterModule, - NSRouterLink, - NSRouterLinkActive, - PageRouterOutlet + { provide: RouteReuseStrategy, useExisting: NSRouteReuseStrategy }, ], - schemas: [NO_ERRORS_SCHEMA] + imports: [RouterModule, NativeScriptCommonModule], + exports: [RouterModule, NSRouterLink, NSRouterLinkActive, PageRouterOutlet], + schemas: [NO_ERRORS_SCHEMA], }) export class NativeScriptRouterModule { static forRoot(routes: Routes, config?: ExtraOptions): ModuleWithProviders { @@ -63,6 +45,9 @@ export class NativeScriptRouterModule { } } -export function provideLocationStrategy(locationStrategy: NSLocationStrategy, frame: Frame): NSLocationStrategy { - return locationStrategy ? locationStrategy : new NSLocationStrategy(frame); +export function provideLocationStrategy( + locationStrategy: NSLocationStrategy, + frameService: FrameService +): NSLocationStrategy { + return locationStrategy ? locationStrategy : new NSLocationStrategy(frameService); } diff --git a/nativescript-angular/trace.ts b/nativescript-angular/trace.ts index 8f81c0005..486943791 100644 --- a/nativescript-angular/trace.ts +++ b/nativescript-angular/trace.ts @@ -6,6 +6,7 @@ export const viewUtilCategory = "ns-view-util"; export const routerTraceCategory = "ns-router"; export const routeReuseStrategyTraceCategory = "ns-route-reuse-strategy"; export const listViewTraceCategory = "ns-list-view"; +export const bootstrapCategory = "bootstrap"; export function animationsLog(message: string): void { write(message, animationsTraceCategory); @@ -42,3 +43,11 @@ export function listViewLog(message: string): void { export function listViewError(message: string): void { write(message, listViewTraceCategory, messageType.error); } + +export function bootstrapLog(message: string): void { + write(message, bootstrapCategory); +} + +export function bootstrapLogError(message: string): void { + write(message, bootstrapCategory, messageType.error); +} diff --git a/ng-sample/.vscode/launch.json b/ng-sample/.vscode/launch.json index d36693af8..a12095658 100644 --- a/ng-sample/.vscode/launch.json +++ b/ng-sample/.vscode/launch.json @@ -22,7 +22,8 @@ "sourceMaps": true, "diagnosticLogging": false, "emulator": false, - "rebuild": true + "rebuild": true, + "stopOnEntry": true }, { "name": "Attach on iOS", @@ -54,7 +55,8 @@ "sourceMaps": true, "diagnosticLogging": false, "emulator": false, - "rebuild": true + "rebuild": true, + "stopOnEntry": true }, { "name": "Attach on Android", diff --git a/ng-sample/app/app.css b/ng-sample/app/app.css index 15ec392ba..a2f267c8c 100644 --- a/ng-sample/app/app.css +++ b/ng-sample/app/app.css @@ -40,4 +40,8 @@ button { .input { margin: 30px; color:#444; +} + +.test { + color: green; } \ No newline at end of file diff --git a/ng-sample/app/app.ts b/ng-sample/app/app.ts index 5e860f71c..f72e23952 100644 --- a/ng-sample/app/app.ts +++ b/ng-sample/app/app.ts @@ -2,8 +2,8 @@ import { NativeScriptModule } from "nativescript-angular/nativescript.module"; import { platformNativeScriptDynamic } from "nativescript-angular/platform"; import { NativeScriptAnimationsModule } from "nativescript-angular/animations"; import { onAfterLivesync, onBeforeLivesync } from "nativescript-angular/platform-common"; -import { NgModule } from "@angular/core"; -import { DOCUMENT } from '@angular/common'; +import { NgModule, ErrorHandler } from "@angular/core"; +import { DOCUMENT } from "@angular/common"; import { Router } from "@angular/router"; import { NativeScriptRouterModule } from "nativescript-angular/router"; import { NativeScriptFormsModule } from "nativescript-angular/forms"; @@ -15,18 +15,24 @@ import { routerTraceCategory, listViewTraceCategory, animationsTraceCategory, + viewUtilCategory, routeReuseStrategyTraceCategory, + bootstrapCategory, } from "nativescript-angular/trace"; import { PAGE_FACTORY, PageFactory, PageFactoryOptions } from "nativescript-angular/platform-providers"; import { Page } from "ui/page"; import { Color } from "color"; -import { setCategories, enable } from "trace"; -// setCategories( -// `${animationsTraceCategory},${rendererTraceCategory}` -// ); +import { log } from "tns-core-modules/profiling"; + +import { setCategories, addCategories, enable, categories } from "trace"; +addCategories(bootstrapCategory); +// addCategories(rendererTraceCategory); +// addCategories(routerTraceCategory); +// addCategories(categories.ViewHierarchy); +// addCategories(categories.Layout); // setCategories(routerTraceCategory); // setCategories(listViewTraceCategory); -setCategories(`${routeReuseStrategyTraceCategory}`); +// setCategories(`${routeReuseStrategyTraceCategory}, ${routerTraceCategory}, ${viewUtilCategory}`); enable(); import { RendererTest } from "./examples/renderer-test"; @@ -40,6 +46,7 @@ import { HttpTest } from "./examples/http/http-test"; import { HttpClientTest } from "./examples/http-client/http-client-test"; import { ActionBarTest } from "./examples/action-bar/action-bar-test"; import { ModalTest } from "./examples/modal/modal-test"; +import { ModalNestedTest } from "./examples/modal/modal-nested-test"; import { PlatfromDirectivesTest } from "./examples/platform-directives/platform-directives-test"; import { LivesyncApp } from "./examples/livesync-test/livesync-test-app"; @@ -57,10 +64,8 @@ import { AnimationNgClassTest } from "./examples/animation/animation-ngclass-tes import { AnimationStatesTest } from "./examples/animation/animation-states-test"; import { AnimationStatesMultiTest } from "./examples/animation/animation-states-multi-test"; - @NgModule({ - declarations: [ - ], + declarations: [], imports: [ NativeScriptModule, NativeScriptFormsModule, @@ -75,15 +80,12 @@ import { AnimationStatesMultiTest } from "./examples/animation/animation-states- NativeScriptHttpClientModule, NativeScriptRouterModule, ], - providers: [] + providers: [], }) -class ExampleModule { } +class ExampleModule {} function makeExampleModule(componentType) { - let imports: any[] = [ - NativeScriptAnimationsModule, - ExampleModule, - ]; + let imports: any[] = [NativeScriptAnimationsModule, ExampleModule]; if (componentType.routes) { imports.push(NativeScriptRouterModule.forRoot(componentType.routes)); } @@ -97,23 +99,20 @@ function makeExampleModule(componentType) { } entries.push(componentType); - let providers = []; + let providers = [{ provide: ErrorHandler, useClass: MyErrorHandler }]; if (componentType.providers) { - providers = [componentType.providers]; + providers = [...providers, componentType.providers]; } @NgModule({ bootstrap: [componentType], imports, entryComponents: entries, - declarations: [ - ...entries, - ...exports, - ], + declarations: [...entries, ...exports], providers, exports, }) - class ExampleModuleForComponent { } + class ExampleModuleForComponent {} return ExampleModuleForComponent; } @@ -124,9 +123,16 @@ const customPageFactoryProvider = { const page = new Page(); page.backgroundColor = opts.isModal ? new Color("lightblue") : new Color("lightgreen"); return page; - } + }, }; +class MyErrorHandler implements ErrorHandler { + handleError(error) { + console.log("### ErrorHandler Error: " + error.toString()); + console.log("### ErrorHandler Stack: " + error.stack); + } +} + // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(RendererTest)); // platformNativeScriptDynamic(undefined, [customPageFactoryProvider]).bootstrapModule(makeExampleModule(RendererTest)); // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(TabViewTest)); @@ -137,7 +143,7 @@ const customPageFactoryProvider = { // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(ImageTest)); // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(ModalTest)); // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(HttpTest)); -platformNativeScriptDynamic().bootstrapModule(makeExampleModule(HttpClientTest)); +// platformNativeScriptDynamic().bootstrapModule(makeExampleModule(HttpClientTest)); // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(PlatfromDirectivesTest)); // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(ActionBarTest)); @@ -157,23 +163,28 @@ platformNativeScriptDynamic().bootstrapModule(makeExampleModule(HttpClientTest)) // Livesync test let cachedUrl: string; -onBeforeLivesync.subscribe((moduleRef) => { - console.log("------- onBeforeLivesync"); - if (moduleRef) { - const router = moduleRef.injector.get(Router); - cachedUrl = router.url; - console.log("------- Caching URL: " + cachedUrl); - } +onBeforeLivesync.subscribe(moduleRef => { + console.log("#### onBeforeLivesync"); + // if (moduleRef) { + // const router = moduleRef.injector.get(Router); + // cachedUrl = router.url; + // log("-------> Caching URL: " + cachedUrl); + // } }); -onAfterLivesync.subscribe((moduleRef) => { - console.log("------- onAfterLivesync cachedUrl:"); - const router = moduleRef.injector.get(Router); - router.events.subscribe(e => console.log(e.toString())); - if (router && cachedUrl) { - setTimeout(() => { router.navigateByUrl(cachedUrl); }, 0); - } +onAfterLivesync.subscribe(({ moduleRef, error }) => { + console.log(`#### onAfterLivesync moduleRef: ${moduleRef} error: ${error}`); + // if (moduleRef) { + // const router = moduleRef.injector.get(Router); + // router.events.subscribe(e => log(e.toString())); + // if (router && cachedUrl) { + // setTimeout(() => { + // router.navigateByUrl(cachedUrl); + // }, 0); + // } + // } }); // platformNativeScriptDynamic().bootstrapModule(makeExampleModule(LivesyncApp)); -console.log("APP RESTART"); +// console.log("APP RESTART!!!! !!!"); +platformNativeScriptDynamic().bootstrapModule(makeExampleModule(ModalTest)); diff --git a/ng-sample/app/examples/modal/modal-content.ts b/ng-sample/app/examples/modal/modal-content.ts index 0b2d1f360..2e2a92515 100644 --- a/ng-sample/app/examples/modal/modal-content.ts +++ b/ng-sample/app/examples/modal/modal-content.ts @@ -1,5 +1,5 @@ -import {Component, Input} from "@angular/core"; -import {ModalDialogParams} from "nativescript-angular/directives/dialogs"; +import { Component, Input } from "@angular/core"; +import { ModalDialogParams } from "nativescript-angular/directives/dialogs"; @Component({ selector: "modal-content", @@ -14,7 +14,9 @@ import {ModalDialogParams} from "nativescript-angular/directives/dialogs"; ` }) export class ModalContent { + @Input() public prompt: string; + constructor(private params: ModalDialogParams) { console.log("ModalContent.constructor: " + JSON.stringify(params)); this.prompt = params.context.promptMsg; @@ -26,10 +28,10 @@ export class ModalContent { ngOnInit() { console.log("ModalContent.ngOnInit"); - } ngOnDestroy() { console.log("ModalContent.ngOnDestroy"); } + } diff --git a/ng-sample/app/examples/modal/modal-nested-test.ts b/ng-sample/app/examples/modal/modal-nested-test.ts new file mode 100644 index 000000000..0330d5525 --- /dev/null +++ b/ng-sample/app/examples/modal/modal-nested-test.ts @@ -0,0 +1,24 @@ +import { Component, ViewContainerRef } from "@angular/core"; +import * as dialogs from "ui/dialogs"; +import { ModalDialogService, ModalDialogOptions } from "nativescript-angular/directives/dialogs"; +import { ModalContent } from "./modal-content"; +import { ModalTest } from "./modal-test"; + +@Component({ + selector: "modal-nested-test", + template: ` + + ` +}) +export class ModalNestedTest { + + static entries = [ + ModalContent + ]; + + static exports = [ + ModalContent, + ModalTest + ]; + +} \ No newline at end of file diff --git a/ng-sample/app/examples/modal/modal-test.ts b/ng-sample/app/examples/modal/modal-test.ts index 74a31b62f..6851c333d 100644 --- a/ng-sample/app/examples/modal/modal-test.ts +++ b/ng-sample/app/examples/modal/modal-test.ts @@ -1,7 +1,7 @@ import { Component, ViewContainerRef } from "@angular/core"; import * as dialogs from "ui/dialogs"; import { ModalDialogService, ModalDialogOptions } from "nativescript-angular/directives/dialogs"; -import { ModalContent} from "./modal-content"; +import { ModalContent } from "./modal-content"; @Component({ selector: "modal-test", @@ -10,24 +10,22 @@ import { ModalContent} from "./modal-content"; - + - - ` }) export class ModalTest { + public result: string = "result"; - constructor(private modal: ModalDialogService, private vcRef: ViewContainerRef) { - } + constructor(private modal: ModalDialogService, private vcRef: ViewContainerRef) { } static entries = [ ModalContent @@ -110,4 +108,5 @@ export class ModalTest { "no result"; }); } + } diff --git a/ng-sample/app/examples/renderer-test.html b/ng-sample/app/examples/renderer-test.html index b0c17d6f8..41edcaee1 100644 --- a/ng-sample/app/examples/renderer-test.html +++ b/ng-sample/app/examples/renderer-test.html @@ -1,5 +1,5 @@ - - + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ng-sample/app/examples/renderer-test.ts b/ng-sample/app/examples/renderer-test.ts index 232aaed4a..2a98415d1 100644 --- a/ng-sample/app/examples/renderer-test.ts +++ b/ng-sample/app/examples/renderer-test.ts @@ -2,7 +2,6 @@ import { Component, Directive, Host, ElementRef, Input } from "@angular/core"; import { Observable } from "data/observable"; import { SegmentedBarItem } from "ui/segmented-bar"; - function createTabItem(title: string) { let item = new SegmentedBarItem(); item.title = title; @@ -20,11 +19,10 @@ export class TemplatedComponent { } @Directive({ - selector: "Progress", + selector: "Progress" }) export class ProgressDirective { - constructor(private element: ElementRef) { - } + constructor(private element: ElementRef) {} ngOnInit() { this.element.nativeElement.value = 90; @@ -44,16 +42,13 @@ export class RendererTest { public detailLines: Array = []; public isValid: boolean = true; public model: any; + public text: string = "initial"; public testModel = { mydate: new Date() }; - static entries = [ - TemplatedComponent, - ]; + static entries = [TemplatedComponent]; - static exports = [ - ProgressDirective - ]; + static exports = [ProgressDirective]; constructor() { this.buttonText = "Save..."; @@ -61,18 +56,16 @@ export class RendererTest { this.detailsText = "plain ng-if directive \ndetail 1-2-3..."; this.moreDetailsText = "More details:"; this.model = { - "test": "Jack", - "testBoolean": false, - "deliveryDate": new Date(), - "deliveryTime": new Date(), - "mydate": new Date(), - "sliderTest": 0, - "search": null, - "selectedIndex": 0, - "listPickerItems": [ - 1, 2, 3, 4 - ], - "segmentedBarItems": [ + test: "Jack", + testBoolean: false, + deliveryDate: new Date(), + deliveryTime: new Date(), + mydate: new Date(), + sliderTest: 0, + search: null, + selectedIndex: 0, + listPickerItems: [1, 2, 3, 4], + segmentedBarItems: [ createTabItem("first"), createTabItem("second"), createTabItem("third"), @@ -80,10 +73,7 @@ export class RendererTest { ] }; - this.detailLines = [ - "ngFor inside a ngIf 1", - "ngFor inside a ngIf 2", - ]; + this.detailLines = ["ngFor inside a ngIf 1", "ngFor inside a ngIf 2"]; } onSave($event, name, $el) { @@ -109,4 +99,15 @@ export class RendererTest { } return $event; } + count = 0; + onTap() { + console.log("On tap!!! count: " + this.count++); + this.text = "tapped ## : " + this.count; + } + + public show = true; + + toggle(){ + this.show = !this.show; + } } diff --git a/ng-sample/package.json b/ng-sample/package.json index ecd45f339..604cee800 100644 --- a/ng-sample/package.json +++ b/ng-sample/package.json @@ -2,10 +2,10 @@ "nativescript": { "id": "org.nativescript.ngsample", "tns-android": { - "version": "3.0.0" + "version": "next" }, "tns-ios": { - "version": "3.0.0" + "version": "next" } }, "name": "tns-template-hello-world", @@ -44,6 +44,7 @@ "nativescript-angular": "file:../nativescript-angular", "rxjs": "^5.5.0", "tns-core-modules": "next", + "tns-platform-declarations": "^3.4.0", "zone.js": "^0.8.4" }, "devDependencies": { @@ -52,7 +53,7 @@ "babylon": "6.8.1", "filewalker": "0.1.2", "lazy": "1.0.11", - "nativescript-dev-typescript": "^0.3.1", + "nativescript-dev-typescript": "next", "shelljs": "^0.7.0", "tslint": "^4.5.1", "typescript": "~2.6.2" @@ -61,4 +62,4 @@ "tslint": "tslint --project tsconfig.json --config tslint.json", "update-app-ng-deps": "update-app-ng-deps" } -} \ No newline at end of file +} diff --git a/ng-sample/tsconfig.json b/ng-sample/tsconfig.json index 7926095e1..4f07c2af2 100644 --- a/ng-sample/tsconfig.json +++ b/ng-sample/tsconfig.json @@ -21,7 +21,7 @@ "./node_modules/tns-core-modules/*", "./node_modules/*" ] - } + }, }, "exclude": [ "node_modules", diff --git a/tests/app/App_Resources/Android/app.gradle b/tests/app/App_Resources/Android/app.gradle index 5a83b0360..9096cbb7c 100644 --- a/tests/app/App_Resources/Android/app.gradle +++ b/tests/app/App_Resources/Android/app.gradle @@ -8,7 +8,7 @@ android { defaultConfig { generatedDensities = [] - applicationId = "org.nativescript.tests" + applicationId = "org.nativescript.ngtests" //override supported platforms // ndk { diff --git a/tests/app/main.ts b/tests/app/main.ts index f5c652ff7..6e7af754e 100644 --- a/tests/app/main.ts +++ b/tests/app/main.ts @@ -4,7 +4,7 @@ import { NativeScriptModule } from "nativescript-angular/nativescript.module"; import { platformNativeScriptDynamic } from "nativescript-angular/platform"; -import { NativeScriptRouterModule, NSModuleFactoryLoader } from "nativescript-angular/router"; +import { NativeScriptRouterModule } from "nativescript-angular/router"; import { NativeScriptFormsModule } from "nativescript-angular/forms"; import { AppComponent } from "./app.component"; @@ -33,17 +33,38 @@ import { rendererTraceCategory, routerTraceCategory } from "nativescript-angular import { BehaviorSubject } from "rxjs/BehaviorSubject"; -import trace = require("trace"); -trace.setCategories(rendererTraceCategory + "," + routerTraceCategory); +import { GridLayout, ItemSpec } from "tns-core-modules/ui/layouts/grid-layout/grid-layout"; + +import { enable, addCategories, categories } from "trace"; +import { Color } from "tns-core-modules/color/color"; + +addCategories(rendererTraceCategory); +// addCategories(routerTraceCategory); +addCategories(categories.ViewHierarchy); + // trace.setCategories(routerTraceCategory); -// trace.enable(); +enable(); // nativeScriptBootstrap(GestureComponent); // nativeScriptBootstrap(LayoutsComponent); // nativeScriptBootstrap(IconFontComponent); const platform = platformNativeScriptDynamic({ bootInExistingPage: true }); -const root = new StackLayout(); -const rootViewProvider = { provide: APP_ROOT_VIEW, useValue: root }; +const root = new GridLayout(); + +let rootViewsCount = 0; +let colors = ["lightgreen", "lightblue", "lightpink"]; +function createRootProvider() { + root.addRow(new ItemSpec(1, "star")); + + const appRootView = new StackLayout(); + GridLayout.setRow(appRootView, rootViewsCount); + root.addChild(appRootView); + appRootView.backgroundColor = new Color(colors[rootViewsCount % colors.length]); + + rootViewsCount++; + return { provide: APP_ROOT_VIEW, useValue: appRootView }; +} + const singlePageHooksLog = new BehaviorSubject([]); const singlePageHooksLogProvider = { provide: HOOKS_LOG, useValue: singlePageHooksLog }; const multiPageHooksLog = new BehaviorSubject([]); @@ -52,108 +73,58 @@ const lazyLoadHooksLog = new BehaviorSubject([]); export const lazyLoadHooksLogProvider = { provide: HOOKS_LOG, useValue: lazyLoadHooksLog }; @NgModule({ - bootstrap: [ - SinglePageMain - ], - declarations: [ - SinglePageMain, - FirstComponent, - SecondComponent, - ], - entryComponents: [ - SinglePageMain, - FirstComponent, - SecondComponent, - ], + bootstrap: [SinglePageMain], + declarations: [SinglePageMain, FirstComponent, SecondComponent], + entryComponents: [SinglePageMain, FirstComponent, SecondComponent], imports: [ NativeScriptModule, NativeScriptFormsModule, NativeScriptRouterModule, NativeScriptRouterModule.forRoot(singlePageRoutes), ], - exports: [ - NativeScriptModule, - NativeScriptFormsModule, - NativeScriptRouterModule, - ], - providers: [ - rootViewProvider, - singlePageHooksLogProvider, - ] + exports: [NativeScriptModule, NativeScriptFormsModule, NativeScriptRouterModule], + providers: [createRootProvider(), singlePageHooksLogProvider], }) -class SinglePageModule { } +class SinglePageModule {} @NgModule({ - bootstrap: [ - MultiPageMain - ], - declarations: [ - MultiPageMain, - FirstComponent, - SecondComponent, - ], - entryComponents: [ - MultiPageMain, - FirstComponent, - SecondComponent, - ], + bootstrap: [MultiPageMain], + declarations: [MultiPageMain, FirstComponent, SecondComponent], + entryComponents: [MultiPageMain, FirstComponent, SecondComponent], imports: [ NativeScriptModule, NativeScriptFormsModule, NativeScriptRouterModule, NativeScriptRouterModule.forRoot(multiPageRoutes), ], - exports: [ - NativeScriptModule, - NativeScriptFormsModule, - NativeScriptRouterModule, - ], - providers: [ - rootViewProvider, - multiPageHooksLogProvider, - ] + exports: [NativeScriptModule, NativeScriptFormsModule, NativeScriptRouterModule], + providers: [createRootProvider(), multiPageHooksLogProvider], }) -class MultiPageModule { } +class MultiPageModule {} @NgModule({ - bootstrap: [ - LazyLoadMain - ], - declarations: [ - LazyLoadMain, - FirstComponent, - ], - entryComponents: [ - LazyLoadMain, - ], + bootstrap: [LazyLoadMain], + declarations: [LazyLoadMain, FirstComponent], + entryComponents: [LazyLoadMain], imports: [ NativeScriptModule, NativeScriptFormsModule, NativeScriptRouterModule, NativeScriptRouterModule.forRoot(lazyLoadRoutes), ], - exports: [ - NativeScriptModule, - NativeScriptFormsModule, - NativeScriptRouterModule, - ], + exports: [NativeScriptModule, NativeScriptFormsModule, NativeScriptRouterModule], providers: [ - rootViewProvider, + createRootProvider(), lazyLoadHooksLogProvider, - { provide: NgModuleFactoryLoader, useClass: NSModuleFactoryLoader }, - ] + ], }) -class LazyLoadModule { } +class LazyLoadModule {} -application.start({ +application.run({ create: (): Page => { - const page = new Page(); - page.content = root; - - let onLoadedHandler = function (args) { - page.off("loaded", onLoadedHandler); + let onLoadedHandler = function(args) { + root.off("loaded", onLoadedHandler); // profiling.stop('application-start'); - console.log("Page loaded"); // profiling.start('ng-bootstrap'); console.log("BOOTSTRAPPING TEST APPS..."); @@ -163,8 +134,8 @@ application.start({ platform.bootstrapModule(LazyLoadModule); }; - page.on("loaded", onLoadedHandler); + root.on("loaded", onLoadedHandler); - return page; - } + return root; + }, }); diff --git a/tests/app/single-page-main.component.ts b/tests/app/single-page-main.component.ts index 6f7a6fefb..4c1743f4f 100644 --- a/tests/app/single-page-main.component.ts +++ b/tests/app/single-page-main.component.ts @@ -7,20 +7,17 @@ import {SecondComponent} from "./second.component"; @Component({ selector: "single-page-main", template: ` - - - - - - - - - - + + + + + + + + ` - }) -export class SinglePageMain { +export class SinglePageMain { constructor( public elementRef: ElementRef, public router: Router, diff --git a/tests/app/snippets/layouts.component.html b/tests/app/snippets/layouts.component.html index 3cc2fbdb3..ec6867a04 100644 --- a/tests/app/snippets/layouts.component.html +++ b/tests/app/snippets/layouts.component.html @@ -176,56 +176,56 @@ - - - - - - diff --git a/tests/app/tests/ns-location-strategy.ts b/tests/app/tests/ns-location-strategy.ts index 13fd898a9..10e24164f 100644 --- a/tests/app/tests/ns-location-strategy.ts +++ b/tests/app/tests/ns-location-strategy.ts @@ -4,6 +4,19 @@ import { NSLocationStrategy, LocationState } from "nativescript-angular/router/n import { Frame, BackstackEntry, NavigationEntry } from "ui/frame"; import { Page } from "ui/page"; import { View } from "ui/core/view"; +import { FrameService } from "nativescript-angular/platform-providers"; + +class FakeFrameService extends FrameService { + private frame: Frame; + constructor(private backCB?: () => void) { + super(); + this.frame = new FakeFrame(backCB); + } + + public getFrame(): Frame { + return this.frame; + } +} class FakeFrame extends View implements Frame { backStack: Array; @@ -11,15 +24,18 @@ class FakeFrame extends View implements Frame { currentEntry: NavigationEntry; animated: boolean; transition: any; + _currentEntry: any; - canGoBack(): boolean { return true; } + canGoBack(): boolean { + return true; + } goBack(to?: BackstackEntry) { if (this.backCB) { this.backCB(); } } - navigate(entry: any) { } + navigate(entry: any) {} constructor(private backCB?: () => void) { super(); @@ -44,10 +60,23 @@ class FakeFrame extends View implements Frame { public _getNavBarVisible(page: Page): boolean { throw new Error("I am a FakeFrame"); } + public isCurrent(entry: BackstackEntry): boolean { + throw new Error("I am a FakeFrame"); + } + setCurrent(entry: BackstackEntry, isBack: boolean): void { + throw new Error("I am a FakeFrame"); + } + _findEntryForTag(fragmentTag: string): BackstackEntry { + throw new Error("I am a FakeFrame"); + } + + _updateBackstack(entry: BackstackEntry, isBack: boolean): void { + throw new Error("I am a FakeFrame"); + } } function initStrategy(back?: () => void): NSLocationStrategy { - const strategy = new NSLocationStrategy(new FakeFrame(back)); + const strategy = new NSLocationStrategy(new FakeFrameService(back)); strategy.pushState(null, null, "/", null); // load initial state return strategy; } @@ -59,11 +88,13 @@ function assertStatesEqual(actual: Array, expected: Array { - it("initial path() value", () => { - const strategy = new NSLocationStrategy(new FakeFrame()); + const strategy = new NSLocationStrategy(new FakeFrameService()); assert.equal(strategy.path(), "/"); }); - it("pushState changes path", () => { const strategy = initStrategy(); @@ -120,7 +149,9 @@ describe("NSLocationStrategy", () => { it("back() calls onPopState", () => { const strategy = initStrategy(); let popCount = 0; - strategy.onPopState(() => { popCount++; }); + strategy.onPopState(() => { + popCount++; + }); strategy.pushState(null, "test", "/test", null); assert.equal(strategy.path(), "/test"); @@ -134,7 +165,9 @@ describe("NSLocationStrategy", () => { it("replaceState() replaces state - doesn't call onPopState", () => { const strategy = initStrategy(); let popCount = 0; - strategy.onPopState(() => { popCount++; }); + strategy.onPopState(() => { + popCount++; + }); strategy.pushState(null, "test", "/test", null); assert.equal(strategy.path(), "/test"); @@ -158,12 +191,15 @@ describe("NSLocationStrategy", () => { assertStatesEqual(strategy._getStates(), expectedStates); }); - it("back() when on page-state calls frame.goBack() if no page navigation in progress", () => { let frameBackCount = 0; - const strategy = initStrategy(() => { frameBackCount++; }); + const strategy = initStrategy(() => { + frameBackCount++; + }); let popCount = 0; - strategy.onPopState(() => { popCount++; }); + strategy.onPopState(() => { + popCount++; + }); simulatePageNavigation(strategy, "/page"); @@ -180,12 +216,15 @@ describe("NSLocationStrategy", () => { assert.equal(strategy._getStates().length, 2); }); - it("back() when on page-state navigates back if page navigation is in progress", () => { let frameBackCount = 0; - const strategy = initStrategy(() => { frameBackCount++; }); + const strategy = initStrategy(() => { + frameBackCount++; + }); let popCount = 0; - strategy.onPopState(() => { popCount++; }); + strategy.onPopState(() => { + popCount++; + }); simulatePageNavigation(strategy, "/page"); @@ -202,7 +241,6 @@ describe("NSLocationStrategy", () => { assert.equal(strategy._getStates().length, 1); }); - it("pushState() with clearHistory clears history", () => { const strategy = initStrategy(); diff --git a/tests/app/tests/renderer-tests.ts b/tests/app/tests/renderer-tests.ts index ebb9091ee..e1df13498 100644 --- a/tests/app/tests/renderer-tests.ts +++ b/tests/app/tests/renderer-tests.ts @@ -5,14 +5,15 @@ import { ProxyViewContainer } from "ui/proxy-view-container"; import { Red } from "color/known-colors"; import { dumpView } from "./test-utils"; import { TestApp } from "./test-app"; -import { LayoutBase } from "ui/layouts/layout-base"; -import { StackLayout } from "ui/layouts/stack-layout"; -import { ContentView } from "ui/content-view"; -import { Button } from "ui/button"; +import { isIOS } from "tns-core-modules/platform"; +import { View, fontInternalProperty, backgroundInternalProperty} from "tns-core-modules/ui/core/view" +import { LayoutBase } from "tns-core-modules/ui/layouts/layout-base"; +import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout"; +import { ContentView } from "tns-core-modules/ui/content-view"; +import { Button } from "tns-core-modules/ui/button"; import { NgView } from "nativescript-angular/element-registry"; import { registerElement } from "nativescript-angular/element-registry"; -import * as button from "tns-core-modules/ui/button"; -import * as view from "tns-core-modules/ui/core/view"; +// import * as view from "tns-core-modules/ui/core/view"; @Component({ template: `` @@ -172,18 +173,18 @@ export class NgIfThenElseComponent { } } -export class ButtonCounter extends button.Button { +export class ButtonCounter extends Button { nativeBackgroundRedraws = 0; backgroundInternalSetNativeCount = 0; fontInternalSetNativeCount = 0; - [view.backgroundInternalProperty.setNative](value) { + [backgroundInternalProperty.setNative](value) { this.backgroundInternalSetNativeCount++; - return super[view.backgroundInternalProperty.setNative](value); + return super[backgroundInternalProperty.setNative](value); } - [view.fontInternalProperty.setNative](value) { + [fontInternalProperty.setNative](value) { this.fontInternalSetNativeCount++; - return super[view.fontInternalProperty.setNative](value); + return super[fontInternalProperty.setNative](value); } _redrawNativeBackground(value: any): void { this.nativeBackgroundRedraws++; @@ -624,12 +625,14 @@ describe("Renderer lifecycle", () => { return testApp.loadComponent(NgControlSettersCount).then((componentRef) => { assert.isTrue(componentRef.instance.isAfterViewInit, "Expected the NgControlSettersCount to have passed its ngAfterViewInit."); componentRef.instance.buttons.map(btn => btn.nativeElement).forEach(btn => { - assert.isTrue(btn.isLoaded, `Expected ${btn.id} to be allready loaded.`); + assert.isTrue(btn.isLoaded, `Expected ${btn.id} to be already loaded.`); assert.isFalse(btn.isLayoutValid, `Expected ${btn.id}'s layout to be invalid.`); assert.equal(btn.backgroundInternalSetNativeCount, 1, `Expected ${btn.id} backgroundInternalSetNativeCount to be called just once.`); assert.equal(btn.fontInternalSetNativeCount, 1, `Expected ${btn.id} fontInternalSetNativeCount to be called just once.`); - assert.equal(btn.nativeBackgroundRedraws, 0, `Expected ${btn.id} nativeBackgroundRedraws to be called after its layout pass.`); + + const expectedBackgroundRedraws = isIOS ? 0 : 1; + assert.equal(btn.nativeBackgroundRedraws, expectedBackgroundRedraws, `Expected ${btn.id} nativeBackgroundRedraws to be called just once`); }); }); }); diff --git a/tests/app/tests/snippets.ts b/tests/app/tests/snippets.ts index 8883e49a5..e0ed3464a 100644 --- a/tests/app/tests/snippets.ts +++ b/tests/app/tests/snippets.ts @@ -20,8 +20,7 @@ import { ListTemplateSelectorTest, } from "../snippets/list-view/template-selector.component"; -import { device, platformNames } from "platform"; -const IS_IOS = (device.os === platformNames.ios); +import { isIOS } from "platform"; describe("Snippets", () => { let testApp: TestApp = null; @@ -50,8 +49,8 @@ describe("Snippets", () => { }); }); - // TODO: Skip list-view test until karma test launcher double navigate bug is fixed - (IS_IOS ? it.skip : it)("Icon-font snippets can be loaded", (done) => { + //TODO: Skip list-view test until karma test launcher double navigate bug is fixed + (isIOS ? it.skip : it)("Icon-font snippets can be loaded", (done) => { testApp.loadComponent(IconFontComponent).then((componentRef) => { const componentInstance = componentRef.instance; assert.instanceOf(componentInstance, IconFontComponent); @@ -79,7 +78,11 @@ describe("Snippets Navigation", () => { after(cleanup); it("router-outlet app", (done) => { - bootstrapTestApp(NavigationApp, [], routes, [NavigationApp, FirstComponent, SecondComponent]).then((app) => { + bootstrapTestApp(NavigationApp, [], routes, [ + NavigationApp, + FirstComponent, + SecondComponent + ]).then((app) => { runningApp = app; return runningApp.done.then(() => { @@ -95,14 +98,13 @@ describe("Snippets Navigation", () => { }); }); - it("page-router-outlet app", (done) => { + //TODO: Skip the page-router-outlet test as it causes a crash in android in the current test-runner setup + (isIOS ? it : it.skip)("page-router-outlet app", (done) => { bootstrapTestApp(PageNavigationApp, [], routes, [ PageNavigationApp, FirstComponent, SecondComponent ]).then((app) => { - - console.log("PageNavigationApp instance: " + app); runningApp = app; return runningApp.done.then(() => { diff --git a/tests/app/tests/style-properties.ts b/tests/app/tests/style-properties.ts index 63f2390d5..3a8fcc20e 100644 --- a/tests/app/tests/style-properties.ts +++ b/tests/app/tests/style-properties.ts @@ -1,18 +1,20 @@ // make sure you import mocha-config before @angular/core -import {assert} from "./test-config"; -import {TextField} from "ui/text-field"; -import {Red, Lime} from "color/known-colors"; +import { assert } from "./test-config"; +import { TextField } from "ui/text-field"; +import { Red, Lime } from "color/known-colors"; import { NativeScriptRendererFactory, NativeScriptRenderer } from "nativescript-angular/renderer"; -import {device} from "platform"; +import { device } from "platform"; import { ViewEncapsulation, RendererType2, Renderer2 } from "@angular/core"; -import {NgView} from "nativescript-angular/view-util"; +import { NgView } from "nativescript-angular/view-util"; +import { StackLayout } from "tns-core-modules/ui/layouts/stack-layout"; describe("Setting style properties", () => { let renderer: NativeScriptRenderer = null; let element: NgView = null; beforeEach(() => { - const rendererFactory = new NativeScriptRendererFactory(null, device, null); + const rootView = new StackLayout(); + const rendererFactory = new NativeScriptRendererFactory(rootView, device, null); renderer = rendererFactory.createRenderer(null, { id: "id", encapsulation: ViewEncapsulation.None, diff --git a/tests/app/tests/test-app.ts b/tests/app/tests/test-app.ts index fd481c67c..6d9726f93 100644 --- a/tests/app/tests/test-app.ts +++ b/tests/app/tests/test-app.ts @@ -7,9 +7,11 @@ import { ViewContainerRef, NgZone, NgModule, } from "@angular/core"; -import { GridLayout } from "ui/layouts/grid-layout"; -import { LayoutBase } from "ui/layouts/layout-base"; -import { topmost } from "ui/frame"; +import { getRootView } from "tns-core-modules/application"; +import { Frame } from "tns-core-modules/ui/frame"; +import { GridLayout } from "tns-core-modules/ui/layouts/grid-layout"; +import { LayoutBase } from "tns-core-modules/ui/layouts/layout-base"; + import { APP_ROOT_VIEW } from "nativescript-angular/platform-providers"; @Component({ @@ -76,7 +78,7 @@ export function bootstrapTestApp( components: any[] = [], directives: any[] = [] ): Promise { - const page = topmost().currentPage; + const page = (getRootView()).currentPage; const rootLayout = page.content; const viewRoot = new GridLayout(); rootLayout.addChild(viewRoot); diff --git a/tests/app/tests/value-accessor-tests.ts b/tests/app/tests/value-accessor-tests.ts index 57b7173ed..eff50e672 100644 --- a/tests/app/tests/value-accessor-tests.ts +++ b/tests/app/tests/value-accessor-tests.ts @@ -72,51 +72,69 @@ class TestTextValueAccessor extends TextValueAccessor { describe("two-way binding via ng-model", () => { it("converts strings to numbers", () => { const accessor = new TestNumberValueAccessor(); + const defaultValue = accessor.view.value; accessor.writeValue(null); - assert.strictEqual(0, accessor.view.value, "default to 0 on empty"); + assert.strictEqual(defaultValue, accessor.view.value, "setting null should keep the default value"); accessor.writeValue("42"); assert.strictEqual(42, accessor.view.value); accessor.writeValue("blah"); assert.notEqual(accessor.view.value, accessor.view.value, "defaults to NaN on parse errors"); + + accessor.writeValue(null); + assert.strictEqual(defaultValue, accessor.view.value, "setting null should reset the value"); }); it("converts strings to bools", () => { const accessor = new TestCheckedValueAccessor(); + const defaultValue = accessor.view.checked; accessor.writeValue(null); - assert.strictEqual(null, accessor.view.checked, "default to null on empty"); + assert.strictEqual(false, accessor.view.checked, "setting null should keep the default value"); accessor.writeValue("true"); assert.strictEqual(true, accessor.view.checked); + accessor.writeValue(null); + assert.strictEqual(defaultValue, accessor.view.checked, "setting null should reset the value"); + assert.throws(() => accessor.writeValue("blah")); }); it("converts strings to dates", () => { - const now = new Date(); const accessor = new TestDateValueAccessor(); - - accessor.writeValue(null); - assert.equal(null, accessor.view.date, "default to null on empty"); + const defaultDate = accessor.view.date; // current date time + + assert.instanceOf(accessor.view.date, Date); + let diff = Math.abs(accessor.view.date.getTime() - defaultDate.getTime()); + assert.isTrue(diff < 1000, "setting null should reset the value"); accessor.writeValue("2010-03-17"); assert.equal(formatDate(new Date(2010, 2, 17)), formatDate(accessor.view.date)); + + accessor.writeValue(null); + assert.instanceOf(accessor.view.date, Date); + diff = Math.abs(accessor.view.date.getTime() - defaultDate.getTime()); + assert.isTrue(diff < 1000, "setting null should reset the value"); }); it("converts strings to int selection", () => { const accessor = new TestSelectedIndexValueAccessor(); - + const defaultValue = accessor.view.selectedIndex; + accessor.writeValue(null); accessor.ngAfterViewInit(); - assert.strictEqual(null, accessor.view.selectedIndex, "default to null on empty"); + assert.strictEqual(defaultValue, accessor.view.selectedIndex, "setting null should keep the default value"); accessor.writeValue("3"); accessor.ngAfterViewInit(); assert.strictEqual(3, accessor.view.selectedIndex); + accessor.writeValue(null); + assert.strictEqual(defaultValue, accessor.view.selectedIndex, "setting null should reset the value"); + accessor.writeValue("blah"); accessor.ngAfterViewInit(); assert.notEqual(accessor.view.selectedIndex, accessor.view.selectedIndex, @@ -126,20 +144,23 @@ describe("two-way binding via ng-model", () => { it("converts strings to times", () => { const accessor = new TestTimeValueAccessor(); - assert.throws(() => accessor.writeValue(null)); assert.throws(() => accessor.writeValue("2010/03/17 12:54")); assert.throws(() => accessor.writeValue("three hours from now")); }); it("converts values to text", () => { const accessor = new TestTextValueAccessor(); + const defaultValue = accessor.view.text; accessor.writeValue(null); - assert.equal(null, accessor.view.text, "defaults to null on empty"); + assert.equal(defaultValue, accessor.view.text, "setting null should keep the default value"); accessor.writeValue("blah"); assert.equal("blah", accessor.view.text); + accessor.writeValue(null); + assert.equal(defaultValue, accessor.view.text, "setting null should reset the value"); + accessor.writeValue({ toString: () => "stringified" }); assert.equal("stringified", accessor.view.text); });