diff --git a/.gitattributes b/.gitattributes
index 90991ebd90c1..e69de29bb2d1 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +0,0 @@
-*.md merge=union
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 8e7742e73822..c8685c864a91 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,6 +30,7 @@ Resource.Designer.cs
bld/
[Bb]in/
[Oo]bj/
+logfile=obj/
# Visual Studio 2015 cache/options directory
.vs/
diff --git a/Doc/ReleaseNotes/_ReleaseNotes.md b/Doc/ReleaseNotes/_ReleaseNotes.md
deleted file mode 100644
index 931b0f0d0ab9..000000000000
--- a/Doc/ReleaseNotes/_ReleaseNotes.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Release notes
-
-## Next version
-
-### Features
-
-### Breaking changes
-
-### Bug fixes
-
- * 129762 - Updated Android SimpleOrientationSensor calculations based on SensorType.Gravity or based on single angle orientation when the device does not have a Gyroscope.
diff --git a/README.md b/README.md
index 975df82101b2..0670a0a08b38 100644
--- a/README.md
+++ b/README.md
@@ -19,6 +19,7 @@ Here's a list of live apps made with the Uno Platform for WebAssembly.
* The [Uno.RoslynQuoter](http://roslynquoter-wasm.platform.uno/), a [Roslyn]() based C# analysis tool ([Source](https://github.com/nventive/Uno.RoslynQuoter))
* The [Uno.BikeSharing360 App](http://bikerider-wasm.platform.uno/), a Xamarin.Forms app running on top of Uno for WebAssembly ([Source](https://github.com/nventive/Uno.BikeSharing360_MobileApps))
* The [Uno.WindowsStateTriggers App](http://winstatetriggers-wasm.platform.uno/), a demo of the [Morten's WindowsStateTriggers](https://github.com/dotMorten/WindowsStateTriggers) ([Source](https://github.com/nventive/Uno.WindowsStateTriggers))
+* The [SQLite + Entity Framework Core App](http://sqliteefcore-wasm.platform.uno), a demo of the combination of [Roslyn](https://github.com/dotnet/roslyn), [Entity Framework Core](https://docs.microsoft.com/en-us/ef/core/), [SQLite](https://github.com/nventive/Uno.SQLitePCLRaw.Wasm) and the Uno Platform to manipulate an in-browser database.
Let us know if you've made your app publicly available, we'll list it here!
@@ -54,7 +55,7 @@ Let us know if you've made your app publicly available, we'll list it here!
* [State Triggers](https://blogs.msdn.microsoft.com/mvpawardprogram/2017/02/07/state-triggers-uwp-apps/)
* [Adaptive Triggers](https://docs.microsoft.com/en-us/uwp/api/Windows.UI.Xaml.AdaptiveTrigger)
* Platform Specific
- * Native controls and properties via [conditional XAML](doc/articles/using-uno-ui.md)
+ * Native controls and properties via [conditional XAML](doc/articles/using-uno-ui.md#supporting-multiple-platforms-in-xaml-files)
* Any of the existing Xamarin iOS/Android libraries available
# Getting Started
diff --git a/build/Uno.UI.WpfHost.nuspec b/build/Uno.UI.WpfHost.nuspec
new file mode 100644
index 000000000000..1d50b9211578
--- /dev/null
+++ b/build/Uno.UI.WpfHost.nuspec
@@ -0,0 +1,40 @@
+
+
+
+ Uno.UI.WpfHost
+ 2.7.1000
+ Uno.UI.WpfHost
+ nventive
+ nventive
+ false
+ https://github.com/nventive/Uno
+ https://nv-assets.azurewebsites.net/logos/uno.png
+ A WPF host for the WebAssembly build on Uno.UI
+ Copyright (C) 2015-2018 nventive inc. - all rights reserved
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/build/Uno.UI.nuspec b/build/Uno.UI.nuspec
index 4ab20b88bd13..b5885df3ed5e 100644
--- a/build/Uno.UI.nuspec
+++ b/build/Uno.UI.nuspec
@@ -20,7 +20,7 @@
-
+
@@ -30,21 +30,21 @@
-
+
-
+
-
+
@@ -109,13 +109,6 @@
-
-
-
-
-
-
-
@@ -130,12 +123,6 @@
-
-
-
-
-
-
@@ -150,13 +137,6 @@
-
-
-
-
-
-
-
@@ -168,12 +148,6 @@
-
-
-
-
-
-
@@ -186,13 +160,6 @@
-
-
-
-
-
-
-
diff --git a/build/Uno.UI.proj b/build/Uno.UI.proj
index 033cec70f351..af12e4d8db5b 100644
--- a/build/Uno.UI.proj
+++ b/build/Uno.UI.proj
@@ -94,9 +94,13 @@
-
-
-
+
+
+
+
+
@@ -129,20 +133,21 @@
-
+
+
diff --git a/Doc/Assets/layouting-ios.png b/doc/Assets/layouting-ios.png
similarity index 100%
rename from Doc/Assets/layouting-ios.png
rename to doc/Assets/layouting-ios.png
diff --git a/Doc/Assets/layouting-ios.pptx b/doc/Assets/layouting-ios.pptx
similarity index 100%
rename from Doc/Assets/layouting-ios.pptx
rename to doc/Assets/layouting-ios.pptx
diff --git a/doc/ReleaseNotes/Release-1.40.md b/doc/ReleaseNotes/Release-1.40.md
new file mode 100644
index 000000000000..280b1a265940
--- /dev/null
+++ b/doc/ReleaseNotes/Release-1.40.md
@@ -0,0 +1,175 @@
+# Uno Platform Release 1.40
+
+This release is the first non-experimental release of the Uno Platform since the initial public version in May 2018. Lot of bug fixes and features have been added since then, and lots more are coming.
+
+A lot of those changes where included to support these libraries : [MVVMLight](https://github.com/nventive/uno.mvvmlight), [ReactiveUI](https://github.com/nventive/Uno.ReactiveUI), [Prism](https://github.com/nventive/Uno.Prism), [Rx.NET](https://github.com/nventive/Uno.Rx.NET), [Windows Community Toolkit](https://github.com/nventive/Uno.WindowsCommunityToolkit), [Xamarin.Forms UWP](https://github.com/nventive/Uno.Xamarin.Forms).
+
+Here are some highlights of this release:
+
+- General improvement in the memory consumption of the `ListView` control
+- Many Wasm rendering and support updates
+ - Invalid images support
+ - Text and images measuring fixes
+ - Add support for AppManifest.displayName
+- Support for the `Pivot` control
+- Support for inline XAML event handlers in `DataTemplate`
+- Support for implicit styles in the `XamlReader`
+- Support for `ThreadPoolTimer`
+- Add support for implicit `bool` to `Visibility` conversion
+- Support for `AutoSuggestBox`
+- SourceLink, Reference Assemblies and deterministic builds are enabled
+- Support for `x:Name` reference in `x:Bind` markup
+- Support for `WriteableBitmap` for all platforms
+- Added support for `Cross-platform Library` template in vsix
+- Added support for `StaticResource` as top level `ResourceDictionary` element
+- Added support for `AutomationPeer`
+- Android status bar height is now included in `Window.Bounds`
+- Add support for `Underline` in `HyperLinkButton`
+- Add support for TextBlock.TextDecorations
+- TextBlock base class is now `FrameworkElement` on iOS, instead of `UILabel`
+- Auto generated list of views implemented in Uno in the documentation
+- Add support for string to `Type` conversion in XAML generator and binding engine
+- Support for Attached Properties localization
+- Added `ItemsControl.OnItemsChanged` support
+- Added support for ListView GroupStyle.HeaderTemplateSelector for iOS/Android
+
+Here's the full change log:
+
+- Fixes for VisualTransition.Storyboard lazy bindings [#12](https://github.com/nventive/Uno/pull/12)
+- ListView fixes [#22](https://github.com/nventive/Uno/pull/22)
+ - Improve Path parser compatibility
+ - Update assets generation documentation
+ - Fix ItemsWrapGrid layout when ItemHeight/ItemWidth are not set
+ - Adjust for invalid AnchorPoint support for iOS (#16)
+ - Fix for ListView initialization order issue
+- Default styles clearing fixes [#23](https://github.com/nventive/Uno/pull/23)
+- Compatibility and stability fixes [#37](https://github.com/nventive/Uno/pull/37)
+ - Wasm SplitView fixes
+ - Enum fast converters
+ - TextBox InputScope fixes
+ - Improved ListViewBase stability
+ - SimpleOrientationSensor fixes
+ - PathMarkupParser: Add support for whitespace following FillRule command
+ - Fix DependencyObjectStore.PopCurrentlySettingProperty
+ - Raised navigation completed after setting CanGoBack/Forward
+ - Fix layouting that sometimes misapplies margin
+ - Selector: Coerce SelectedItem to ensure its value is always valid
+ - Remove legacy panel default constructor restriction
+ - Wasm image support improvements
+ - Add support for forward slash in image source
+ - Add support for CollectionViewSource set directly on ItemsControl.ItemSource
+ - Fix Pane template binding for SplitView
+ - Add support for Object as DependencyProperty owner
+ - Add Wasm support for UIElement.Tapped
+ - Fix iOS UnregisterDoubleTapped stack overflow
+- Compatibility and stability fixes [#43](https://github.com/nventive/Uno/pull/43)
+ - Adjust WASM thickness support for children arrange
+ - Fix support for inline text content using ContentProperty
+ - Fix memory leaks in ScrollViewer
+ - Adjust for missing styles in UWP Styles FeatureConfiguration
+ - Fix for Source Generation race condition on slow build servers
+- Compatibility and stability fixes [#53](https://github.com/nventive/Uno/pull/53)
+ - Adjust for WASM Support for local images [#1](https://github.com/nventive/Uno/issues/1)
+ - Fixes x:Bind support for Wasm
+ - Fix invalid deserialization of ApplicationDataContainer for iOS
+ - Fix error for ApplicationView.Title for WASM
+ - Remove glib conversion errors in WASM
+- UWP API Alignments for Wasm [#70](https://github.com/nventive/Uno/pull/70)
+ - Add support for Application.Start() to provide a proper SynchronizationContext for error management
+ - Fix for ImplicitStyles support in XamlReader
+ - Add support for the Pivot control using the default UWP Xaml style
+ - Adjust body background color after the splash screen removal
+ - Adjust the materialization of Control templates to not be lazy
+- Add support for Xaml file defined event handlers [#71](https://github.com/nventive/Uno/pull/71)
+- API Compatibility Updates [#75](https://github.com/nventive/Uno/pull/75)
+ - Add support for implicit bool to Visibility conversion
+ - Fix default Style constructor does not set the proper property precedence
+ - Add more DependencyObjectStore logging
+ - Align ItemsControl.Items behavior with UWP (#34)
+ - Fix invalid uri parsing when set through BitmapImage.UriSource
+- [WASM] Fix text measure when not connected to DOM [#76](https://github.com/nventive/Uno/pull/76)
+- Pivot, AutoSuggestBox, TextBox, XamlReader updates [#77](https://github.com/nventive/Uno/pull/77)
+ - Added missing TransformGroup ContentProperty
+ - Fixed invalid namespace attribution of attached properties in XamlReader
+ - Fixed BitmapImage.UriSource updates not being applied on Wasm
+ - Add basic implementation of AutoSuggestBox
+ - Fixed focus stealing issues with inactive PivotItem content
+ - Add ThreadPoolTimer support
+ - Fix for iOS popup not appearing
+ - Fix for Wasm textbox not properly updating while not loaded
+- [WASM] Add suport for TextBlock.Padding property [#88](https://github.com/nventive/Uno/pull/88)
+- [WASM] Fixed measuring support with Polyfill for Node.isConnected [#89](https://github.com/nventive/Uno/pull/88), [#91](https://github.com/nventive/Uno/pull/91)
+- Misc fixes [#93](https://github.com/nventive/Uno/pull/93)
+ - Fixed iOS `SimpleOrientationSensor` default queue management
+ - Fixed multiple memory leaks in `ListView`, `ScrollViewer`
+ - Implemented `CacheLength` for Android `ListViewBase`
+ - Fixed for `DependencyObject` properties inheritance race condition
+ - Fix for empty Path reporting an infinite size
+ - Fix Title not appearing in CommandBar
+- Add support for WebAssembly AppManifest.displayName [#94](https://github.com/nventive/Uno/pull/94)
+- Enable SourceLink, Reference Assemblies, Deterministic build [#100](https://github.com/nventive/Uno/pull/100)
+- Binding Engine Alignments [#113](https://github.com/nventive/Uno/pull/113)
+ - Use Portable symbols for Xamarin debugging stability
+ - Enable x:Name reference in x:Bind markup. This requires for a failed BindableMetadata lookup to fall through reflection lookup.
+ - Assume ".Value" binding path on a primitive is equivalent to self, to enable nullable bindings.
+ - Adjust unit tests logging
+ - Enables auto "LogicalChild" treatment to allow for DependencyObjectCollection members to be databound
+ - Enable parent reset for "LogicalChild" assignations
+- Implement the CoreWindow.Dispatcher property [#117](https://github.com/nventive/Uno/pull/117)
+- Misc Fixes [#120](https://github.com/nventive/Uno/pull/120)
+ - Fix for CommandBar back button icon
+ - Improve HyperLinks hit-testing for iOS
+ - Fixed android PaintDrawable opacity
+ - Adjust Unloaded event for ToggleButton
+ - Adjust for brightness support
+ - Adjust touch support for rotated elements
+ - Adjust MinWidth/MinHeight support in Grid
+ - Adjust PasswordBox custom font for during password reveal
+ - ListView, ContentControl memory improvements
+ - Style behavior adjustements
+- Update for android animation reliability [#123](https://github.com/nventive/Uno/pull/123)
+- Add support for WriteableBitmap [#125](https://github.com/nventive/Uno/pull/125)
+- Updated vsix structure [#128](https://github.com/nventive/Uno/pull/128)
+- Multiple enhancements for WCT 4.0 [#131](https://github.com/nventive/Uno/pull/131)
+ - Adds support for `IconElement` fast conversion
+ - Adds stubs for `ToggleSwitchTemplateSettings`, `PackageId`, `UISettings`
+ - Adjust `XamlObjectBuilder` logging
+ - Add implicit conversion for `KeyTime` and `Duration`
+ - Add support for top level `StaticResource` resource dictionary elements
+ - Implement FindFirstParent for net46/netstd2.0
+ - Adds ElementNotAvailableException and ElementNotEnabledException
+ - Fix invalid measure for empty wasm images
+ - Add size/rect checks for measure/arrange wasm
+ - Improve XamlReader error reporting
+- Add support for Cross-platform library template in VSIX [#132](https://github.com/nventive/Uno/pull/132)
+- Add support for AutomationPeer [#141](https://github.com/nventive/Uno/pull/141)
+- Improved support for UWP resources [#149](https://github.com/nventive/Uno/pull/149)
+ - Projects no longer need to define `XamlCodeGenerationFiles` (fixes #144)
+ - Projects no longer need to define `ResourcesDirectory` (fixes #106)
+ - Projects no longer need to initialize `ResourceHelper.ResourcesService` (fixes #142)
+ - `ResourceLoader.GetString` is now supported (fixes #142)
+- Updates rollup [#151](https://github.com/nventive/Uno/pull/151)
+ - Fixed `VisualState` not updated when `TextBox` is focused
+ - Improve `ListView` and `Selector` memory footprint
+ - Adjust GenericStyles application sequence for Android
+ - Add diagnostics methods for `BinderReferenceHolder`
+ - Include android status bar height in `Window.Bounds`
+ - Fixed `Grid` items size when `MinHeight` and `MinHeight` are used
+ - Fixed android race condition during visual tree cleanup
+ - Add support for underline in `HyperLinkButton`
+ - Fixed `ScrollContentPresenter` margin issue
+ - Adjust `MessageDialog` behavior for android
+ - `ContentControl` Data Context is now properly unset
+ - Add `EmailNameOrAddress` InputScope for `TextBox`
+ - Fixed duplicated resw entry support
+ - Fixed `ComboBox` popup touch issue
+ - Add support for TextBlock.TextDecorations
+ - TextBlock base class from UILabel to FrameworkElement
+- Auto-generate list of views implemented in Uno [#152](https://github.com/nventive/Uno/pull/152)
+- Add support for string to `Type` conversion in Xaml generator and Binding engine. [#159](https://github.com/nventive/Uno/pull/159)
+- Add support for attached properties localization [#156](https://github.com/nventive/Uno/pull/156)
+- Added `ItemsControl.OnItemsChanged` support [#175](https://github.com/nventive/Uno/pull/175)
+- Added support for XAML inline collections declaration [#184](https://github.com/nventive/Uno/pull/184)
+- Adjust the sequence of control template materialization [#192](https://github.com/nventive/Uno/pull/192)
+- Support for ListView.ScrollIntoView with leading alignment
+- Added support for ListView GroupStyle.HeaderTemplateSelector
\ No newline at end of file
diff --git a/doc/ReleaseNotes/U2.md b/doc/ReleaseNotes/U2.md
deleted file mode 100644
index 90d0263b9cc9..000000000000
--- a/doc/ReleaseNotes/U2.md
+++ /dev/null
@@ -1,13 +0,0 @@
-## Uno Release U2
-
-### Features
-
- * Implements `ListViewBase.ScrollIntoView(position, ScrollIntoViewAlignment.Leading)` on **Android**.
-
-### Breaking changes
-
- *
-
-### Bugfixes
-
- *
\ No newline at end of file
diff --git a/doc/ReleaseNotes/U3.md b/doc/ReleaseNotes/U3.md
deleted file mode 100644
index 8ec8b5109f1b..000000000000
--- a/doc/ReleaseNotes/U3.md
+++ /dev/null
@@ -1,17 +0,0 @@
-## Uno Release U2
-
-### Features
-
-
-### Breaking changes
-
- *
-
-### Bugfixes
-
- * #116111 Fixed the Xaml parsing on macOS not taking into account escaping accolades
- * #116876 [Android] ItemsWrapGrid now correctly handles items with Stretch dimensions
- * Fixes a bug where two `UIDatePickers` (e.g. `DatePickerSelector` and `TimePickerSelector`) would interefer one with the other if they had different time zones.
- * Fixes a bug where the `CommandBar.Content` will not have a `DataContext`.
- * #116196 Fixed the selection in ListViewBase to reset when the items list becomes null.
- * #116875 [iOS] [Button] Button with ContentPresenter does not trim appropriately
\ No newline at end of file
diff --git a/doc/ReleaseNotes/_ReleaseNotes.md b/doc/ReleaseNotes/_ReleaseNotes.md
new file mode 100644
index 000000000000..d6e972924e23
--- /dev/null
+++ b/doc/ReleaseNotes/_ReleaseNotes.md
@@ -0,0 +1,39 @@
+# Release notes
+
+## Next version
+
+### Features
+*
+
+### Breaking changes
+*
+
+### Bug fixes
+*
+
+## Release 1.41
+
+### Features
+
+* [#154](https://github.com/nventive/Uno/issues/154) Implement the MediaPlayerElement control
+* 135799 Implemented MediaPlayer.Dispose()
+
+### Bug fixes
+
+ * 129762 - Updated Android SimpleOrientationSensor calculations based on SensorType.Gravity or based on single angle orientation when the device does not have a Gyroscope.
+ * 134189 [iOS] The Time Picker flyout placement is not always respected
+ * 134132 [Android] Fix loading of ItemsPresenter
+ * 134104 [iOS] Fixed an issue when back swiping from a page with a collapsed CommandBar
+ * 134026 [iOS] Setting a different DP from TextBox.TextChanging can cause an infinite 'ping pong' of changing Text values
+ * 134415 [iOS] MenuFlyout was not loaded correctly, causing templates containing a MenuFlyout to fail
+ * 133247 [iOS] Image performance improvements
+ * 135192 [iOS] Fixed ImageBrush flash/flickering occurs when transitioning to a new page.
+ * 135112 [Android] Fix crash in UpdateItemsPanelRoot() in the ItemsControl class.
+ * 132014, 134103 [Android] Set the leading edge considering header can push groups out off the screen
+ * 131998 [Android] Window bounds set too late
+ * 131768 [iOS] Improve ListView.ScrollIntoView() when ItemTemplateSelector is set
+ * 135202, 131884 [Android] Content occasionally fails to show because binding throws an exception
+ * 135646 [Android] Binding MediaPlayerElement.Source causes video to go blank
+ * 136093, 136172 [iOS] ComboBox does not display its Popup
+ * 134819, 134828 [iOS] Ensures the back gesture is enabled and disabled properly when the CommandBar is visible, collapsed, visible with a navigation command and collapsed with a navigation command.
+ * 136092 [iOS] ScrollIntoView() throws exception for ungrouped lists
\ No newline at end of file
diff --git a/Doc/Uno-UI-Layouting-iOS.md b/doc/Uno-UI-Layouting-iOS.md
similarity index 100%
rename from Doc/Uno-UI-Layouting-iOS.md
rename to doc/Uno-UI-Layouting-iOS.md
diff --git a/doc/articles/MediaPlayerElement.md b/doc/articles/MediaPlayerElement.md
new file mode 100644
index 000000000000..f565b26dc308
--- /dev/null
+++ b/doc/articles/MediaPlayerElement.md
@@ -0,0 +1,91 @@
+# MediaPlayerElement
+
+See [MediaPlayerElement](https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.mediaplayerelement) on MSDN
+
+## Media formats
+
+| Supported Formats | iOS | Android | Remarks |
+|-------------------------------------------------------|-------|-----------|-----------------------------------|
+| Local/Remote MP3 Support | X | X | |
+| Local/Remote MPEG4 Support | X | X | |
+| HLSv3 Support | X | X | |
+| HLSv4 Support | X | X | |
+| MPEG-Dash Support | - | - | |
+| Smooth Streaming Support | - | - | |
+
+_If you need to set source programmatically (ie, using `_mediaPlayerElement.Source = [source]`), please note that only source created with `MediaSource.CreateFromUri()` are currently supported_
+
+## Features
+
+| Section | Feature | iOS | Android | Remarks |
+|-----------------------|-------------------------------------------------------|-------|-----------|-----------------------------------------------|
+| MediaPlayerElement | AutoPlay | X | X | |
+| | Poster image | X | X | Does not show when playing music |
+| | Enable/Disable MediaTransportControls | X | X | |
+| | Stretch | X | X | Stretch.None behave like Stretch.Fill on iOS |
+| | Pause media when headphones unplugged | X | X | |
+| TransportControls | Transport controls custom style | X | X | |
+| | Play/Pause | X | X | |
+| | Stop | X | X | |
+| | Seek | X | X | |
+| | Volume change | X | X | |
+| | Mute | X | X | |
+| | Show elapsed time | X | X | |
+| | Show remaining time | X | X | |
+| | Show/Hide MediaTransportControls automatically | X | X | |
+| | MediaTransportControls compact mode | X | X | |
+| | Show/Hide MediaTransportControls commands | X | X | |
+| | Enable/Disable MediaTransportControls commands | X | X | |
+| | Skip forwoard | X | X | |
+| | Skip backward | X | X | |
+| | Show buffering progress | X | X | |
+| | Zoom mode | X | X | |
+| | Fullscreen mode | - | - | |
+| | Change playback rate | - | - | |
+| | Player controls on locked screen support | - | - | |
+| | Playlists support | - | - | |
+| | Subtitles support | - | - | |
+| | Languages support | - | - | |
+
+## Requirement
+
+### iOS
+
+Add the folowwing to your info.plist
+
+```xml
+NSAppTransportSecurity
+
+ NSAllowsArbitraryLoads
+
+ NSExceptionMinimumTLSVersion
+ TLSv1.2
+
+```
+
+__Note:__ Don't just copy/paste, but properly setup `NSAppTransportSecurity` as required by your project
+
+### Android
+
+Add the folowwing to your AndroidManifest.xml
+
+```xml
+
+
+
+
+```
+
+## Future improvement
+
+- Playback rate support
+- React to audio focus changes (pause/stop playback or reduce audio volume)
+- Subtitles support
+- Languages support
+- Display poster for audio media
+
+## Known issues
+
+- Volume flyout does not display on iOS (Uno issue)
+- Dynamic width/height not supported when playing audio
+- Sometimes flickers during resizing when using dynamic width/height
\ No newline at end of file
diff --git a/doc/articles/Uno.UI.Toolkit.md b/doc/articles/Uno.UI.Toolkit.md
new file mode 100644
index 000000000000..57675cee46aa
--- /dev/null
+++ b/doc/articles/Uno.UI.Toolkit.md
@@ -0,0 +1,39 @@
+# Uno.UI.Tollkit
+
+Uno.UI.Tollkit is a set of extension methods or behaviors used to enhance UWP and activate device/OS specific features.
+
+Those methods are built to have no effect on platform that does not support the enhanced feature: no need to wrap them into conditional code.
+
+## MenuFlyoutItem - Destructive style
+
+iOS can display `MenuFlyoutItem` to warn user the action will be "destructive". In that case, the button text is display in red.
+
+To set a `MenuFlyoutItem` as destructive, add the toolkit namespace to your XAML
+
+```xml
+xmlns:toolkit="using:Uno.UI.Toolkit"
+```
+
+And declare your `MenuFlyoutItem` as follow
+
+```xml
+
+```
+
+## UICommand - Destructive style
+
+iOS can display `UICommand` to warn user the action will be "destructive". In that case, the button text is display in red.
+
+To set a `UICommand` as destructive, add the toolkit namespace to your code
+
+```csharp
+using Uno.UI.Toolkit;
+```
+
+And declare your `UICommand` as follow
+
+```csharp
+var uic = new UICommand("Destructive action");
+uic.SetDestructive(true);
+```
\ No newline at end of file
diff --git a/doc/articles/faq.md b/doc/articles/faq.md
index 13e47c14217b..56e3010c2687 100644
--- a/doc/articles/faq.md
+++ b/doc/articles/faq.md
@@ -286,3 +286,87 @@ Yes, make sure to use the following project definition:
```
+
+## Does Uno offer a TreeView control?
+
+It's in the UWP API, but [not implemented yet](https://docs.microsoft.com/en-us/windows/uwp/design/controls-and-patterns/tree-view)
+We have an open Github (issue.)[https://github.com/nventive/Uno/issues/3]
+
+## Is there a table of all UWP controls and their features compared to what's offered under Uno?
+
+https://github.com/nventive/Uno/blob/master/doc/articles/supported-features.md
+
+## Is there an Uno template that is based on portable class library?
+
+No, but use the (Cross-Platform library template)[https://marketplace.visualstudio.com/items?itemName=nventivecorp.uno-platform-addin] instead to achieve a similar goal.
+
+## Is there a Visual Studio template for Uno that incorporates the Prism library?
+
+No, but this sample can serve as a base: https://github.com/nventive/Uno.Prism/tree/uno/Sandbox/Windows10/HelloWorld
+
+## I get errors when serializing Json in Uno Wasm
+
+If you are using JSON.NET, you need [this](https://github.com/nventive/Uno.Playground/blob/master/src/Uno.Playground.WASM/LinkerConfig.xml)
+This file is referenced in the .csproj like [that](https://github.com/nventive/Uno.Playground/blob/master/src/Uno.Playground.WASM/Uno.Playground.WASM.csproj#L43)
+
+## Is NavigationView supported in Uno?
+
+It is indeed not implemented at the time, see [nventive/Uno#4](https://github.com/nventive/Uno/issues/4) for now
+
+## Is there any particular reason that Uno uses a shared project? and is it possible to use a netstandard project instead?
+
+The view layer needs to be in a shared project because it has native dependencies.
+For your view models and business logic, it's fine to use a separate netstandard project.
+Shared projects are also used to work around the fact that Visual Studio is not able to selectively compile a single Target Framework when building a cross-targeted library.
+Using a shared project improves the build performance when debugging a single platform.
+
+## Are there any Visual Studio project creation templates for Uno yet?
+
+Yes. Here are the [templates].(https://marketplace.visualstudio.com/items?itemName=nventivecorp.uno-platform-addin)
+
+## How do I add the NuGet package if there's no Packages node for Shared Projects?
+
+Go to 'Manage NuGet packages for solution...'
+Find the ReactiveUI package
+Select all your platform heads (.Wasm, .Android etc) and hit Install
+
+## Is RichEditBox supported in Uno.Platform?
+
+Not yet.
+
+## Is there a way to use local css/js libraries and not those on a CDN?
+
+you can specify a custom HTML template like [this](https://github.com/nventive/Uno.Wasm.Bootstrap#indexhtml-content-override)
+
+## Debugging a published nuget package breaks the Xamarin iOS and Android debugger
+
+This has been fixed starting from Visual Studio 15.9 Preview 3
+Please see this [Developer Community thread.](https://developercommunity.visualstudio.com/content/problem/306764/debugging-a-published-nuget-package-break-the-xama.html)
+
+## Does Uno offer an `AutoSuggestBox`?
+
+[Yes](https://github.com/nventive/Uno/blob/master/src/Uno.UI/UI/Xaml/Controls/AutoSuggestBox/AutoSuggestBox.cs)
+
+## Is there a database that works on all platforms?
+
+Yes, and you can use this (WebAssembly SQLite provider)[https://github.com/nventive/Uno.SQLitePCLRaw.Wasm]
+
+## Are Popups/RichEditbox implemented in Uno?
+
+No. You can use Conditional Xaml to work around it: https://github.com/nventive/Uno/blob/master/doc/articles/using-uno-ui.md#supporting-multiple-platforms-in-xaml-files
+
+## Does Uno support all UWP animations?
+
+We've implemented parts of the supported animations, there are others that are still stubbed.
+
+## Visual Studio is requiring Android API v26 but I want to test on an older device.
+
+The target API does not affect the min API. You just need to have the API day installed in your android sdk manager. The min sdk is specified in the androidmanifest file.
+
+## Is there a workaround for ScrollViewer.ScrollToVerticalOffset method, since it isnt implemented in Uno?
+
+You can use ChangeView instead
+
+## I am having issues running a Wasm project head
+
+Follow the instructions on how to run the WASM head (here)[https://github.com/nventive/Uno.QuickStart#create-an-application-from-the-solution-template]
\ No newline at end of file
diff --git a/doc/articles/map-control-support.md b/doc/articles/map-control-support.md
new file mode 100644
index 000000000000..f9598c09eb9c
--- /dev/null
+++ b/doc/articles/map-control-support.md
@@ -0,0 +1,121 @@
+# MapControl
+
+The `MapControl` is a control which allows you to display maps in your app.
+
+## Architecture
+
+To be able to support multiple map providers, the map control is rendering its content in a `MapPresenter` control in the `Uno.UI.Maps` Nuget package. This separation is also required to avoid
+pulling dependencies in an application that does not need Maps.
+
+The current implementation is using the native UIKit map for iOS, and the Google Play Services map control.
+
+## Sample Xaml
+
+See a more complete sample here:
+
+```xml
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+```
+
+## Platform support
+
+| Feature | Android | iOS | Wasm |
+| ------------------------------------------|:-------:|:---:|:----:|
+| Display a map | X | X | |
+| Display a path | | X | |
+| Customize pushpins with icon | | | |
+| Fully template pushpins | | | |
+| Show user's location on map | | | |
+| Toggle native Locate-Me button visibility | | | |
+| Toggle native Compass button visibility | | | |
+
+## Usage
+
+### 1. Configure your application.
+
+- For **Android**,
+ 1. Add the following to AndroidManifest.xml
+ ```xml
+
+ ```
+ 2. Generate the API key and/or inform your client how to generate it.
+ 1. Go to https://console.developers.google.com
+ 2. Login with a Google account
+ 3. Go to the Credentials section to the top left
+ 4. Click on "Create credentials", then "API key"
+ 5. Go to the Dashboard section in the left-hand side menu
+ 6. Click on the relevant service - for instance, "Google Maps Android API" and click on Enable
+
+ 3. Add the API key to `AssemblyInfo.cs`, this should vary depending on the platform and environment, therefore should be retrieved from ClientConstants:
+ ```csharp
+ [assembly: MetaData("com.google.android.maps.v2.API_KEY", Value = ClientConstants.Maps.GoogleMapApiKey)]
+ ```
+
+ 4. Add the relevant permissions, if you wish to access the location of the user (either coarse or fine location):
+ ```csharp
+ //[assembly: UsesPermission(Android.Manifest.Permission.AccessCoarseLocation)]
+ [assembly: UsesPermission(Android.Manifest.Permission.AccessFineLocation)]
+
+ [assembly: UsesPermission("com.myapp.permission.MAPS_RECEIVE")]
+ [assembly: Permission(Name = "com.myapp.permission.MAPS_RECEIVE", ProtectionLevel = Android.Content.PM.Protection.Signature)]
+ ```
+
+
+# Get API key for map component
+
+In order to use the map component, you will need an API key for Windows and Android. Here are the steps to retrieve it.
+
+## Windows
+
+_For the detailed procedure for Windows, please follow this link: https://msdn.microsoft.com/en-us/library/windows/apps/xaml/mt219694.aspx _
+
++ Go to https://www.bingmapsportal.com
++ Login to your account or register if you don't have one
++ Go to MyAccount -> Keys
++ Enter the following information:
+ - Application name
+ - Application URL (optional)
+ - Key type
+ - Application type
++ Enter the characters you see in the box
++ Hit *Create* and get the key
+
+The key should be added as the value for the parameter _MapServiceToken_ for the MapControl object.
+
+## Android
+
+_For the detailed procedure on Android, please follow this link: https://developers.google.com/maps/documentation/android-api/signup#release-cert _
+
++ Retrieve the application's SHA-1 fingerprint
++ Create a project in the Google Developers Console
++ Go to Credentials -> Add credentials -> API key -> Android key
++ In the dialog box, enter the SHA-1 fingerprint and the app package name
++ Hit *Create* and get the key
+
+The API key should be the value for the property _com.google.android.maps.v2.API_KEY_ in the AndroidManifest.xml file.
\ No newline at end of file
diff --git a/doc/articles/supported-features.md b/doc/articles/supported-features.md
index 1fc779d7801c..e462d346c34a 100644
--- a/doc/articles/supported-features.md
+++ b/doc/articles/supported-features.md
@@ -145,3 +145,4 @@
- UI Priority dispatch
- Windows.Graphics.Display.DisplayInformation orientation
- Windows.Media.SpeechRecognition
+- Windows.Media.Capture.CameraCaptureUI
\ No newline at end of file
diff --git a/doc/articles/toc.yml b/doc/articles/toc.yml
index 58c803415952..52d8a4f565b2 100644
--- a/doc/articles/toc.yml
+++ b/doc/articles/toc.yml
@@ -16,3 +16,7 @@
href: debugging-uno-ui.md
- name: Feature Flags
href: feature-flags.md
+- name: Speech Recognition
+ href: SpeechRecognition.md
+- name: Media Player
+ href: MediaPlayerElement.md
diff --git a/doc/articles/using-uno-ui.md b/doc/articles/using-uno-ui.md
index 744d562c6d8e..bc60e6ca33e2 100644
--- a/doc/articles/using-uno-ui.md
+++ b/doc/articles/using-uno-ui.md
@@ -294,6 +294,14 @@ Uno.UI also generates a nested class named StaticResources in all non-ResourceDi
Uno.UI supports the [authoring of styles](https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.style.aspx).
+## Localization
+
+Localization is done through the `resw` files in the current project. Resources are then used using `x:Uid`.
+
+See [Localize strings in your UI](https://docs.microsoft.com/en-us/windows/uwp/app-resources/localize-strings-ui-manifest).
+
+Note that the default language can be defined using the `DefaultLanguage` property, using an IETF Language Tag (e.g. `en` or `fr-FR`).
+
## Supported Uno.UI Controls
### Grid
diff --git a/doc/articles/working-with-commandbar.md b/doc/articles/working-with-commandbar.md
index b1bb0f5f41fe..bf7798e059ab 100644
--- a/doc/articles/working-with-commandbar.md
+++ b/doc/articles/working-with-commandbar.md
@@ -269,7 +269,10 @@ Unlike the `PrimaryCommands` or `SecondaryCommands`, which appear to the right o
This is typically used for burger menus.
-Setting `NavigationCommand` on pages with a back button will replace it (and disable the back gesture on **iOS**).
+On **iOS**, the back gesture can be enabled or disabled using this property.
+
+- When a `CommandBar` (visible or collapsed) is in the visual tree, the back gesture is **enabled**.
+- When a `CommandBar` has a `NavigationCommand`, the back gesture is **disabled**.
On **Android**, only icons are supported (`AppBarButton.Icon`). This is due to a platform limitation, which can be explained by the fact that `CommandBar.Content` is left-aligned.
@@ -295,6 +298,12 @@ To ensure everything works properly, you must follow a few rules:
* The `CommandBar` must be accessible as soon as the page is being navigated to (i.e., don't put it inside a `DataTemplate` or an `AsyncValuePresenter`).
* There can only be one `CommandBar` per page.
+## Extensibility
+
+The `CommandBar` it automatically managed by the `Frame` control, however you can still use the "native" mode of the `CommandBar` with your own navigation mechanisim.
+
+On **iOS** a `CommandBarHelper` is available for this purpose, you only have to invoke each of the provided method in your own `UIViewController` implementation.
+
# AppBarButton
The `AppBarButton` in **Uno** is designed to be used the same way you would use the `AppBarButton` on **UWP**. In most cases, you should refer to the [official `CommandBar` documentation](https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.controls.appbarbutton).
@@ -875,4 +884,4 @@ Can’t superpose views over a CommandBar.
Can’t animate/translate the CommandBar (i.e., when hiding/showing it based on scroll offset).
Can’t put your CommandBar inside a ScrollViewer and make it scroll.
Can’t put your CommandBar inside templates (i.e., AVP).
-Can’t cancel a back navigation using BackRequestedEventArgs.Handled.
\ No newline at end of file
+Can’t cancel a back navigation using BackRequestedEventArgs.Handled.
diff --git a/doc/articles/working-with-uno-wpf-host.md b/doc/articles/working-with-uno-wpf-host.md
new file mode 100644
index 000000000000..f2048e93464f
--- /dev/null
+++ b/doc/articles/working-with-uno-wpf-host.md
@@ -0,0 +1,38 @@
+# The Uno.UI WebAssembly WPF Host
+
+The Uno Platform provides the ability to run UWP and .NET code through the Mono runtime. While WebAssembly makes it very easy to deploy on the Web, it currently is, as of October 2018, not very easy to debug a application running in this context.
+
+In order to ease the debugging of such an application, the Uno Platform provides the [Uno.UI.WpfHost package](https://www.nuget.org/packages/Uno.UI.WpfHost) to allow running the Uno Platform inside of a WPF application, using a Chromium WebView.
+
+This mode is possible by replacing the WebAssembly runtime by the Desktop .NET Framework, and have it communicate with the WebView via Javascript `eval()` calls on the WebView control. This enables easier troubleshooting of the .NET code, as all the C# code is running in a VisualStudio supported scenario, where C# edit and continue and all the debugger features are available.
+
+## Using the Uno.UI.WpfHost package
+
+- Create an Uno Platform app using the [Visual Studio extension](https://marketplace.visualstudio.com/items?itemName=nventivecorp.uno-platform-addin#overview) named `MyApp`
+- Add a WPF application head
+- Reference the [Uno.UI.WpfHost package](https://www.nuget.org/packages/Uno.UI.WpfHost)
+- In the new WPF head, reference the `MyApp.Wasm` project
+- The constructor of the MainWindow, add the following code:
+```csharp
+UnoHostView.Init(() => MyApp.Wasm.Program.Main(new string[0]), $@"..\..\..\..\MyApp.Wasm\bin\{configuration}\netstandard2.0\dist");
+```
+
+- In the `MainWindow.xaml` file:
+
+```xml
+
+
+
+
+
+```
+
+Running the application will then execute the Wasm head code inside of the WPF application, allowing for the debugging of the C# code.
\ No newline at end of file
diff --git a/doc/blog/201809-UnoUnderTheHoodDependencyObjectGeneration.md b/doc/blog/201809-UnoUnderTheHoodDependencyObjectGeneration.md
new file mode 100644
index 000000000000..afb538a191ce
--- /dev/null
+++ b/doc/blog/201809-UnoUnderTheHoodDependencyObjectGeneration.md
@@ -0,0 +1,154 @@
+# Talkin' 'bout my generation: How the Uno Platform generates code, part 2
+
+[Previously](https://medium.com/@unoplatform/talkin-bout-my-generation-how-the-uno-platform-generates-code-part-1-under-the-hood-7664d83c4f90) we looked at how the [Uno Platform](https://platform.uno/) turns XAML mark-up files into C# code. In this article, I'll talk about another way Uno uses code generation, allowing us to make native Android and iOS views conform to UWP's API, and tackle the thorny problem of [multiple inheritance](https://en.wikipedia.org/wiki/Multiple_inheritance).
+
+## Wanting it all
+Part of the power of Uno on Android and iOS is the ability to easily mix UWP view types with purely native views. This is possible because, in Uno, all views inherit from the native base view type: [View](https://developer.android.com/reference/android/view/View) on Android, [UIView](https://developer.apple.com/documentation/uikit/uiview) on iOS.
+
+
+
+But as I alluded to in an earlier article, this poses a challenge for reproducing UWP's inheritance hierarchy. UIElement is the primitive view type in UWP, but it in turn derives from the DependencyObject class. `DependencyObject` is the base class for anything that has `DependencyProperties`, that is, anything that supports databinding. That includes all views, as well as some non-view framework types like [Transforms](https://docs.microsoft.com/en-us/windows/uwp/design/layout/transforms) and [Brushes](https://docs.microsoft.com/en-us/windows/uwp/design/style/brushes).
+
+
+
+We want to inherit from `ViewGroup` or `UIView`. We also want to inherit from `DependencyObject.` C# doesn't permit multiple inheritance, so what do we do? Since we can't change the iOS or Android frameworks, we opted instead within Uno to make `DependencyObject` an [interface](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/interfaces/index). That allows an Uno `FrameworkElement` to be a `UIView` and at the same time to be a `DependencyObject`. But that alone isn't enough.
+
+
+What if you have code like this in your app?
+
+```` csharp
+ public class MyBindableObject : DependencyObject
+
+ {
+
+ public string MyProperty
+
+ {
+
+ get { return (string)GetValue(MyPropertyProperty); }
+
+ set { SetValue(MyPropertyProperty, value); }
+
+ }
+
+
+
+ // Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
+
+ public static readonly DependencyProperty MyPropertyProperty =
+
+ DependencyProperty.Register("MyProperty", typeof(string), typeof(MyBindableObject), new PropertyMetadata(default(string)));
+
+ }
+````
+
+
+We're inheriting from `DependencyObject` and defining a `DependencyProperty` using the standard syntax, which uses the `DependencyObject.GetValue` and `DependencyObject.SetValue` methods. On UWP these are defined in the base class, but if `DependencyObject` is an interface then there _is_ no base class. In fact if it's just an interface then the code won't compile, because the interface hasn't been implemented.
+
+Luckily `DependencyObject` isn't _just_ an interface in Uno, and the code above will compile as-is on Android and iOS, just as it does on UWP. Code generation makes it happen. Here's some programmer art to illustrate the point. The detailed explanation is below.
+
+![UWP inheritance](Assets/DependencyObjectGeneration/DependencyObjectGenerator_UWP.png)
+*On UWP, `UIElement` inherits from the `DependencyObject` class.*
+![Multiple inheritance](Assets/DependencyObjectGeneration/DependencyObjectGenerator_nope.png)
+*Multiple inheritance - not an option.*
+![Multiple inheritance](Assets/DependencyObjectGeneration/DependencyObjectGenerator_Uno.png)
+*In Uno, `DependencyObject` is an interface, with the implementation automagically supplied by code generation.*
+
+We face a weaker form of this problem - wanting to have two base types - in other cases is well. In a few places in the framework we inherit from a more derived native view type. For example, `ScrollContentPresenter` inherits from the native scroll view on Android and iOS. But we also want `ScrollContentPresenter` to expose the methods and properties of `FrameworkElement`.
+
+We successfully addressed both of these problems by using code generation to implement mixins in C#.
+
+## Mixing things up
+Most statically-typed languages don't permit multiple base classes on account of the added complexity it brings, a.k.a. the ['diamond problem'](https://en.wikipedia.org/wiki/Multiple_inheritance#The_diamond_problem). (C++ is a notable exception.) In dynamically-typed languages, however, it's quite common to bolt on extra functionality to a class in a reusable way with [mixins](https://en.wikipedia.org/wiki/Mixin).
+
+C#, as a statically-typed language, doesn't support mixins as a first-class language feature. Code generation allows us to simulate it, though. Uno uses code generation to add mixins in (at least) two different ways.
+
+I'll start with the simpler approach: using 'T4' templates. To quote Microsoft's documentation:
+> In Visual Studio, a T4 text template is a mixture of text blocks and control logic that can generate a text file. The control logic is written as fragments of program code in Visual C# or Visual Basic. In Visual Studio 2015 Update 2 and later, you can use C# version 6.0 features in T4 templates directives. The generated file can be text of any kind, such as a web page, or a resource file, or program source code in any language.
+
+*Source:* https://docs.microsoft.com/en-us/visualstudio/modeling/code-generation-and-t4-text-templates?view=vs-2017
+
+T4 templates ('.tt files') have been around for quite a while. They're essentially a mix of static text (which is C# code, in our case) and conditional logic. Here's a snippet:
+
+```` csharp
+namespace <#= mixin.NamespaceName #>
+{
+ public partial class <#= mixin.ClassName #> : IFrameworkElement
+ {
+ #if !<#= mixin.IsFrameworkElement #>
+ ///
+ /// Gets the parent of this FrameworkElement in the object tree.
+ ///
+ public DependencyObject Parent => ((IDependencyObjectStoreProvider)this).Store.Parent as DependencyObject;
+#endif
+
+#if <#= mixin.HasAttachedToWindow #>
+ partial void OnAttachedToWindowPartial()
+ {
+ OnLoading();
+ OnLoaded();
+ }
+�
+````
+
+That's from the [template](https://github.com/nventive/Uno/blob/be4f4e938a861d5802c228efc314c1f3ea314027/src/Uno.UI/UI/Xaml/IFrameworkElementImplementation.iOS.tt#L30-L46) which adds `IFrameworkElement` functionality in Uno. It implements properties like `Width`/`Height`, `Opacity`, `Style`, etc. At compile time, the template runs and creates a [partial class](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods) with those members for `ScrollContentPresenter` and several other classes (including `FrameworkElement` itself).
+
+The T4 approach is well-tested and works well in this scenario. It has a couple of limitations though:
+
+1. It requires manual set-up: each class that wants to use the mixin has to be explicitly registered.
+2. It requires manual flags to make sure that the generated code doesn't 'step on' the authored code, eg by generating a `Foo()` method when the authored code already defines `Foo()`.
+3. It doesn't support external code. You can't use the mixin above in your app (short of copy-pasting the templates into the app).
+
+For that reason, in order to have a mixin to implement `DependencyObject`'s features, we went with something a little more complex and a little more magical.
+
+## DependencyObjectGenerator - Making the magic happen
+The release of [Roslyn](https://github.com/dotnet/roslyn), aka the '.NET Compiler Platform', was a boon to code generation. With Roslyn, Microsoft open-sourced the C# compiler, but they also exposed a powerful API for code analysis. With Roslyn it's easy to access all the syntactic and semantic information that the compiler possesses.
+
+To leverage this power for code generation, we created the [Uno.SourceGeneration](https://github.com/nventive/Uno.SourceGeneration) package. Like the Uno Platform, it's free and open source. It creates a build task and allows you to easily add generated code based on Roslyn's analysis of your solution. This might be partial class definitions which augment existing types, or it might be entirely new classes.
+
+In Uno, this used by the [DependencyObjectGenerator](https://github.com/nventive/Uno/blob/master/src/SourceGenerators/Uno.UI.SourceGenerators/DependencyObject/DependencyObjectGenerator.cs) class. This generator looks for every class in the solution that implements the `DependencyObject` interface, like our `MyBindableObject` example above. For each such class, it automatically generates the methods and properties of `DependencyObject`.
+
+Since the generator has a full set of semantic information from Roslyn, it can do this in a smart way. For instance, if it detects that the class is a view type, it adds methods to update binding information when the view is loaded or unloaded.
+
+Here's a [small snippet](https://github.com/nventive/Uno/blob/74ba91756c446107e7394e0423527de273154f5d/src/SourceGenerators/Uno.UI.SourceGenerators/DependencyObject/DependencyObjectGenerator.cs#L218-L250) of code from `DependencyObjectGenerator`:
+
+```` csharp
+ private void WriteAndroidAttachedToWindow(INamedTypeSymbol typeSymbol, IndentedStringBuilder builder)
+ {
+ var isAndroidView = typeSymbol.Is(_androidViewSymbol);
+ var isAndroidActivity = typeSymbol.Is(_androidActivitySymbol);
+ var isAndroidFragment = typeSymbol.Is(_androidFragmentSymbol);
+ var isUnoViewGroup = typeSymbol.Is(_unoViewgroupSymbol);
+ var implementsIFrameworkElement = typeSymbol.Interfaces.Any(t => t == _iFrameworkElementSymbol);
+ var hasOverridesAttachedToWindowAndroid = isAndroidView &&
+ typeSymbol
+ .GetMethods()
+ .Where(m => IsNotDependencyObjectGeneratorSourceFile(m))
+ .None(m => m.Name == "OnAttachedToWindow");
+
+ if (isAndroidView || isAndroidActivity || isAndroidFragment)
+ {
+ if (!isAndroidActivity && !isAndroidFragment)
+ {
+ WriteRegisterLoadActions(typeSymbol, builder);
+ }
+
+ builder.AppendLine($@"
+#if {hasOverridesAttachedToWindowAndroid} //Is Android view (that doesn't already override OnAttachedToWindow)
+#if {isUnoViewGroup} //Is UnoViewGroup
+ // Both methods below are implementation of abstract methods
+ // which are called from onAttachedToWindow in Java.
+ protected override void OnNativeLoaded()
+ {{
+ _loadActions.ForEach(a => a.Item1());
+ BinderAttachedToWindow();
+ }}
+````
+
+In this method we have an [INamedTypeSymbol](https://docs.microsoft.com/en-us/dotnet/api/microsoft.codeanalysis.inamedtypesymbol?view=roslyn-dotnet), an object from Roslyn that encapsulates information about a type. We've already determined that `typeSymbol` implements `DependencyObject`; here we check if it's an Android `View` and, if so override the loaded method. You can notice that we're also checking that the type doesn't _already_ override the same method, so we don't accidentally generate code that clashes with authored code and causes a compiler error. All this goes on under the hood without user intervention, whenever your app compiles.
+
+The end result is that `DependencyObject` can be used almost exactly the same way with Uno as with UWP, even though it's an interface and not a class! There are edge cases: some generic constraints won't work the same way, for example. But in general it works remarkably well.
+
+ ---
+
+That's all for now. Let us know what other 'under the hood' aspects of Uno you'd like to hear more about!
diff --git a/doc/blog/201809-UnoUnderTheHoodXamlGeneration.md b/doc/blog/201809-UnoUnderTheHoodXamlGeneration.md
new file mode 100644
index 000000000000..bffd90766ea3
--- /dev/null
+++ b/doc/blog/201809-UnoUnderTheHoodXamlGeneration.md
@@ -0,0 +1,85 @@
+# Talkin' 'bout my generation: How the Uno Platform generates code, part 1
+
+In [previous](https://medium.com/@unoplatform/under-the-hood-an-introduction-to-uno-platform-6064a765d6a) [articles](https://hackernoon.com/pushing-the-right-buttons-how-uno-implements-views-under-the-hood-a5e93ea86688) we've covered how the [Uno Platform](https://platform.uno/) takes a visual tree defined in the [XAML](https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/xaml-overview) markup language and creates it on iOS, Android, and WebAssembly. In this article I want to dive into a key intermediate step: how the XAML is parsed and mapped to generated C# code. In an upcoming part 2, we'll look at a few other ways in which Uno leverages code generation to make the wheels turn.
+
+## Parsing XAML
+
+XAML stands for eXtensible Application Markup Language. It's an XML-based syntax. Although it can be used to describe [pretty much anything](https://docs.microsoft.com/en-us/dotnet/framework/windows-workflow-foundation/serializing-workflows-and-activities-to-and-from-xaml), it's geared toward describing the structure of an application. It was first used in [Windows Presentation Foundation](https://en.wikipedia.org/wiki/Windows_Presentation_Foundation), and since then has been used (with minor syntactic differences) in a number of contexts, including Silverlight (RIP), WinRT, Xamarin Forms, and the Universal Windows Platform.
+
+XAML hits a sweet spot: it's human readable, expressive, and sufficiently structured to support design tools like [Blend](https://docs.microsoft.com/en-us/visualstudio/designers/creating-a-ui-by-using-blend-for-visual-studio?view=vs-2017) and [XAML Designer](https://docs.microsoft.com/en-us/visualstudio/designers/creating-a-ui-by-using-xaml-designer-in-visual-studio?view=vs-2017). One nice feature is that it can be seamlessly intermingled with C# via [code-behind](https://docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/code-behind-and-xaml-in-wpf) files.
+
+To tap into that power, Uno needs to be able to read a XAML file and convert it into compileable C# code.
+
+The first step is to parse the file into a Xaml object tree, using the [System.Xaml](https://docs.microsoft.com/en-us/dotnet/api/system.xaml?view=netframework-4.7.2) namespace. Next, the Xaml object tree is processed into a C# class definition. The bulk of the heavy lifting is done in the mammoth [XamlFileGenerator](https://github.com/nventive/Uno/blob/master/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs) class. We lean on the [Microsoft.CodeAnalysis API](https://github.com/dotnet/roslyn) here (aka 'Roslyn') to match types used in XAML to types defined in the app assembly or its dependencies. The output is saved to a generated file.
+
+All this happens behind the scenes whenever you build an Uno head.
+
+## The end result
+
+Let's look at a concrete example. This is part of the markup we put in `MainPage.xaml` in a previous article:
+
+```` xml
+
+
+
+
+````
+
+The generated output can be found in the 'obj' folder under the project head.
+
+![Xaml Code Generation Location](Assets/xaml-code-generation-location.png)
+
+*The code file generated from MainPage.xaml.*
+
+This is a part of the generated code, showing the output for the XAML snippet above:
+
+```` csharp
+ public sealed partial class MainPage : Windows.UI.Xaml.Controls.Page
+ {
+ private void InitializeComponent()
+ {
+ var nameScope = new global::Windows.UI.Xaml.NameScope();
+ NameScope.SetNameScope(this, nameScope);
+ // Source ..\..\..\..\..\..\UnoExtTestbed.Shared\MainPage.xaml (Line 1:2)
+ Content = new global::Windows.UI.Xaml.Controls.StackPanel
+ {
+ // Source ..\..\..\..\..\..\UnoExtTestbed.Shared\MainPage.xaml (Line 8:3)
+ Children =
+ {
+ new global::Windows.UI.Xaml.Controls.TextBlock
+ {
+ Name = "ClickTextBlock",
+ Text = "Button wasn't clicked yet",
+ // Source ..\..\..\..\..\..\UnoExtTestbed.Shared\MainPage.xaml (Line 9:4)
+ }
+ .MainPage_05a03e67d6a6581089c5d12899278d61_XamlApply((MainPage_05a03e67d6a6581089c5d12899278d61XamlApplyExtensions.XamlApplyHandler0)(c0 =>
+ {
+ nameScope.RegisterName("ClickTextBlock", c0);
+ this.ClickTextBlock = c0;
+ }
+ ))
+ ,
+ new global::Windows.UI.Xaml.Controls.Button
+ {
+ Content = @"Click me",
+ // Source ..\..\..\..\..\..\UnoExtTestbed.Shared\MainPage.xaml (Line 11:4)
+ }
+ .MainPage_05a03e67d6a6581089c5d12899278d61_XamlApply((MainPage_05a03e67d6a6581089c5d12899278d61XamlApplyExtensions.XamlApplyHandler1)(c1 =>
+ {
+ c1.Click += Button_Click;
+ }
+ ))
+ ,
+ }
+ }
+````
+
+What a mouthful! Bear in mind that generated code tends to be optimized for machine readability, rather than for human readability. For example, the explicit casts to `XamlApplyHandler` were added when we found that the compiler was having to do a lot of computationally-expensive type inference. That one change **doubled** the compilation speed for large XAML files.
+
+In the normal course of Uno development you don't need to look at code generated from XAML or even know that it's there, though occasionally it's useful to take a peek when debugging.
+
+You can see that something called `Button_Click` is subscribed to the Button's Click event. Recall that `Button_Click` is defined in [the code-behind](https://medium.com/@unoplatform/pushing-the-right-buttons-how-uno-implements-views-under-the-hood-a5e93ea86688#the-number-goes-up) in `MainPage.xaml.cs`. As far as the compiler is concerned, both the authored and generated files are just [partial definitions](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/partial-classes-and-methods) of the same class.
+
+One last fun fact: when building on MacOS using [Visual Studio for Mac](https://visualstudio.microsoft.com/vs/mac/) (which Uno tentatively supports in preview), Uno uses an internal port in place of the System.Xaml namespace which isn't available on Mac. The same code backs Uno's support for runtime Xaml interpretation via [Windows.UI.Xaml.Markup.XamlReader](https://docs.microsoft.com/en-us/uwp/api/windows.ui.xaml.markup.xamlreader). That in turn is used in the [interactive mode](https://github.com/nventive/Uno.Playground/blob/master/src/Uno.Playground.Shared/Samples/Playground.xaml) of the [Uno Gallery app](https://github.com/nventive/Uno.Playground) and [Uno.Playground website](https://playground.platform.uno/), which allows you to edit snippets of XAML and see the results in realtime. Check it out!
diff --git a/doc/blog/201809-uno-wasm-intro-part-01.md b/doc/blog/201809-uno-wasm-intro-part-01.md
new file mode 100644
index 000000000000..9dfe6932433e
--- /dev/null
+++ b/doc/blog/201809-uno-wasm-intro-part-01.md
@@ -0,0 +1,73 @@
+# Introduction to WebAssembly for the Uno Platform (Part 1)
+
+WebAssembly, or Wasm for short, is a hot topic these days and for good reasons. It has lots of promise, and for the Uno Platform it promises to open up the Web to other languages and frameworks.
+
+## What is WebAssembly ?
+
+[WebAssembly](https://webassembly.org/) is a low-level byte code for the web, meant to be used as a compilation target for any language, much like ARM or x86. It has been built over the past few years by a W3C group, composed of various people from mostly browser, framework and hardware vendors. They have the simple concrete goal of being able to [securely run arbitrary binary code with near native performance](https://webassembly.org/docs/high-level-goals/).
+
+It's currently supported by all major browsers, making it a viable target **today**.
+
+WebAssembly is agnostic in its definition. Even though its name contains "Web", it is designed as a generic byte code. That's what allows for projects like [Ethereum](https://github.com/ewasm/design), [Life](https://medium.com/perlin-network/life-a-secure-blazing-fast-cross-platform-webassembly-vm-in-go-ea3b31fa6e09), [Nebulet](https://github.com/nebulet/nebulet) or [WebAssembly for .NET](https://github.com/RyanLamansky/dotnet-webassembly) to run without any browser in sight. As [Jay Phelps often mentions](https://twitter.com/_jayphelps/status/1034663875839504384), WebAssembly is neither Web nor Assembly, and can be adapted to many scenarios. It has the potential to ultimately be a true universal binary format, for any kind of programming.
+
+Other good resources can be found in [Matteo Basso's Awesome Wasm](https://github.com/mbasso/awesome-wasm) curated list.
+
+## What does WebAssembly look like ?
+
+WebAssembly being a binary format, it's not human readable, but it has a textual representation that makes it easier to reason with.
+
+[WebAssembly Studio](http://webassembly.studio/) is a good way have a peek inside the generated WebAssembly, where building this C code :
+
+![C Code](Assets/wasm-intro-c-code.png)
+
+becomes this WebAssembly literal code:
+
+![Wasm Code](Assets/wasm-intro-wasm-code.png)
+
+It's not particularly easy to read, as would any similar assembler code, but it gives an idea on how a stack based virtual machine language works.
+
+WebAssembly is a target that most developers will never have to interact with directly, in the same way that most developers never have to interact with x86_64 or ARM64 directly. It will mostly remain a build target, an element in a drop down list next to x86 and ARM64.
+
+Consuming a WebAssembly module is generally composed of a `.wasm` file and a JS _glue_ file, as can be found in the default `main.js` sample of [WebAssembly Studio](http://webassembly.studio/). The JS file is present to use the [WebAssembly.instantiate](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/instantiate) method to load WebAssembly code.
+
+## Why WebAssembly ?
+
+WebAssembly is mainly trying to solve the issues that makes it difficult to optimize performance for large applications, provide access to binary-producing languages and improve the security of running the resulting code.
+
+WebAssembly modules are defined as self-contained units of byte code. It's possible to use [streaming compilation](https://webassembly.github.io/spec/web-api/index.html#streaming-modules) to concurrently process the byte code as it is being downloaded, unlike Javascript where the source file needs to be fully parsed to make sense.
+
+It also provides a way for any language to have a compilation back-end (such as LLVM and [Emscripten](http://emscripten.org/)) to target the Web. That opens a path for C, C++, Rust, [.NET based languages via Mono](https://github.com/mono/mono/tree/master/sdks/wasm), Java, Go, and many other languages to finally reach the web. It provides choices for developers targeting the Web, whether they need full type safety or not, to reuse that complex C++ library that is proving very difficult to port to Javascript. Such portability also enables runtimes and frameworks to follow, such as [QT-Wasm](https://wiki.qt.io/Qt_for_WebAssembly), and Mono and a very large part of the .NET ecosystem.
+
+Security-wise, WebAssembly is very different from previous attempts to run arbitrary binary code in the browser, such as Flash, Java applets, VBA, Silverlight, ActiveX, ... which all had (and continue to have) security and portability issues. For instance, security features include the inability to execute arbitrary memory locations. While this makes optionally JIT'ed languages (such as .NET based languages) a difficult target, it promises a [higher security](https://i.blackhat.com/us-18/Thu-August-9/us-18-Lukasiewicz-WebAssembly-A-New-World-of-Native_Exploits-On-The-Web-wp.pdf) execution environment than its similar add-in based predecessors.
+
+## WebAssembly and .NET
+
+Microsoft has been working on a WebAssembly [port of the Mono runtime for a while now](https://www.mono-project.com/news/2017/08/09/hello-webassembly/), and [progress has been steady](https://www.mono-project.com/news/2018/01/16/mono-static-webassembly-compilation/) since the beginning of 2018. The runtime is looking as stable as it is on iOS and Android using the [Uno Platform](https://github.com/nventive/Uno) as a point of reference, which is quite the achievement.
+
+There's also the .NET Core Runtime (CoreRT) team who are working [on a WebAssembly port of the .NET Native engine](https://github.com/dotnet/corert/blob/master/Documentation/how-to-build-WebAssembly.md), and significant progress is being made there as well.
+
+The security aspect of WebAssembly, with the [inability to execute data segments of memory](https://webassembly.org/docs/modules/#function-index-space), makes for a difficult time running IL code. Commonly, Just-In-Time (JIT) compilation is used to emit code using the underlying platform's instructions in data memory segments, then the CPU executes that data as code. The security constraint in WebAssembly is similar to the constraints found in iOS and watchOS, which do not allow such a compilation technique. The Mono team already worked under those constraints, and WebAssembly support requires the same kind of treatment to get around this limitation.
+
+The obvious answer to this is the use of _Ahead-of-Time Compilation_ (AOT), employing the same technique used for iOS and watchOS. [Due to technical considerations](https://gitter.im/aspnet/Blazor?at=5b1ab670dd54362753f8a168) such as the integration of [Emscripten](https://kripken.github.io/emscripten-site/index.html) and its `libc` implementation over Javascript, AOT is not yet available. While [AOT integration is currently being worked on](https://github.com/mono/mono/issues/10222) by Microsoft, the current path for running .NET code in a WebAssembly environment is through the revived Mono interpreter.
+
+The Mono interpreter is similar to a piece of code that to one that has been around for a long while ([mint](https://www.mono-project.com/news/2017/11/13/mono-interpreter/)), used in the early days of Mono when the JIT engine (mini) wasn't yet available. Its role is to take IL instructions one-by-one and execute them on top of a natively compiled runtime. It allows for IL code to instantly run in the proper environment, at the expense of execution performance.
+
+While this makes for a good kick start solution, such an implementation contains a [_giant switch_](https://github.com/mono/mono/blob/7c19f9d443136cd76bd50bde3e13c4b43c98000f/mono/mini/interp/interp.c#L2686) for each and every available opcode in the IL specification. This is [giving a hard time](https://bugs.chromium.org/p/v8/issues/detail?id=7838) to browsers when going through this hot execution path. It is also not really playing nice with CPU data caches, such as devices with i5 CPU or below with limited L2 cache size.
+
+This situation is fortunately only temporary. When Mono's AOT will be available, the code will instantly be a lot faster, even though by how much remains to be seen. The size aspect of the generated WASM binary is also an unknown variable, and it can also be difficult to extrapolate from other similar looking AOT target CPU architectures.
+
+The interpreter mode will stay in Mono as a mixed execution mode. This will allow for [scenarios of dynamic code generation using Roslyn](https://github.com/jeromelaban/Wasm.Samples/blob/master/RoslynTests/RoslynTests/Program.cs) to be viable in a non-JIT friendly environment, and enable pieces of the BCL such as [Expression compilation](https://docs.microsoft.com/en-us/dotnet/api/system.linq.expressions.expression-1.compile?redirectedfrom=MSDN&view=netframework-4.7.2#System_Linq_Expressions_Expression_1_Compile) to be functional.
+
+## Bootstrapping the mono-wasm SDK
+
+The current challenge when using the mono-wasm SDK is its barrier to entry. There are still lots of things to fiddle around with and it's not integrated in any way to Visual Studio or VS Code.
+
+Based on the work from [Frank A. Krueger on OOui](https://github.com/praeclarum/Ooui), we built [Uno.Wasm.Bootstrap](https://github.com/nventive/Uno.Wasm.Bootstrap), a simple NuGet package with no ties to any framework (not even the Uno Platform), other than mono-wasm. This allows the user to take a simple .NET Standard 2.0 library, and run it in the browser, using `Console.WriteLine` to write text to the browser's debugging console. Anything else more advanced that interacts with the browser needs to go through the Javascript evaluation API.
+
+We expect this package to change significantly in the near future. This includes the addition of new Mono features (such as the AOT and debugger support), Nuget integration, VS integration, etc...
+
+Head over to the [Uno.Wasm.Bootstrap readme](https://github.com/nventive/Uno.Wasm.Bootstrap#how-to-use-the-package) to create your own app and experiment with C# in the browser in minutes. See those two [examples for additional scenarios](https://github.com/jeromelaban/Wasm.Samples) using Json.NET and Roslyn.
+
+## Up next...
+
+In the second part of this article, we'll touch on more advanced topics about the integration of Mono in WebAssembly and upcoming features.
diff --git a/doc/blog/Assets/DependencyObjectGeneration/DependencyObjectGenerator_UWP.png b/doc/blog/Assets/DependencyObjectGeneration/DependencyObjectGenerator_UWP.png
new file mode 100644
index 000000000000..46c2145a5160
Binary files /dev/null and b/doc/blog/Assets/DependencyObjectGeneration/DependencyObjectGenerator_UWP.png differ
diff --git a/doc/blog/Assets/DependencyObjectGeneration/DependencyObjectGenerator_Uno.png b/doc/blog/Assets/DependencyObjectGeneration/DependencyObjectGenerator_Uno.png
new file mode 100644
index 000000000000..02db40e59f41
Binary files /dev/null and b/doc/blog/Assets/DependencyObjectGeneration/DependencyObjectGenerator_Uno.png differ
diff --git a/doc/blog/Assets/DependencyObjectGeneration/DependencyObjectGenerator_nope.png b/doc/blog/Assets/DependencyObjectGeneration/DependencyObjectGenerator_nope.png
new file mode 100644
index 000000000000..90cf62567c9f
Binary files /dev/null and b/doc/blog/Assets/DependencyObjectGeneration/DependencyObjectGenerator_nope.png differ
diff --git a/doc/blog/Assets/wasm-intro-c-code.png b/doc/blog/Assets/wasm-intro-c-code.png
new file mode 100644
index 000000000000..caa001bfd539
Binary files /dev/null and b/doc/blog/Assets/wasm-intro-c-code.png differ
diff --git a/doc/blog/Assets/wasm-intro-wasm-code.png b/doc/blog/Assets/wasm-intro-wasm-code.png
new file mode 100644
index 000000000000..3d5c2e69ccd8
Binary files /dev/null and b/doc/blog/Assets/wasm-intro-wasm-code.png differ
diff --git a/doc/blog/Assets/xaml-code-generation-location.png b/doc/blog/Assets/xaml-code-generation-location.png
new file mode 100644
index 000000000000..f0fd783ce937
Binary files /dev/null and b/doc/blog/Assets/xaml-code-generation-location.png differ
diff --git a/gitversion.yml b/gitversion.yml
index 5f3591da09c2..59b3345ea092 100644
--- a/gitversion.yml
+++ b/gitversion.yml
@@ -1,6 +1,6 @@
assembly-versioning-scheme: MajorMinorPatch
mode: ContinuousDeployment
-next-version: 1.40.0
+next-version: 1.41.1
continuous-delivery-fallback-tag: ""
branches:
master:
diff --git a/src/SamplesApp/SamplesApp.Droid/Assets/AboutAssets.txt b/src/SamplesApp/SamplesApp.Droid/Assets/AboutAssets.txt
new file mode 100644
index 000000000000..ee398862952b
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Droid/Assets/AboutAssets.txt
@@ -0,0 +1,19 @@
+Any raw assets you want to be deployed with your application can be placed in
+this directory (and child directories) and given a Build Action of "AndroidAsset".
+
+These files will be deployed with you package and will be accessible using Android's
+AssetManager, like this:
+
+public class ReadAsset : Activity
+{
+ protected override void OnCreate (Bundle bundle)
+ {
+ base.OnCreate (bundle);
+
+ InputStream input = Assets.Open ("my_asset.txt");
+ }
+}
+
+Additionally, some Android functions will automatically load asset files:
+
+Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf");
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.Droid/Main.cs b/src/SamplesApp/SamplesApp.Droid/Main.cs
new file mode 100644
index 000000000000..4252c9fb6dca
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Droid/Main.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Android.App;
+using Android.Content;
+using Android.OS;
+using Android.Runtime;
+using Android.Views;
+using Android.Widget;
+using Com.Nostra13.Universalimageloader.Core;
+using Windows.UI.Xaml.Media;
+
+namespace SamplesApp.Droid
+{
+ [global::Android.App.ApplicationAttribute(
+ Label = "@string/ApplicationName",
+ LargeHeap = true,
+ HardwareAccelerated = true,
+ Theme = "@style/AppTheme"
+ )]
+ public class Application : Windows.UI.Xaml.NativeApplication
+ {
+ public Application(IntPtr javaReference, JniHandleOwnership transfer)
+ : base(new App(), javaReference, transfer)
+ {
+ ConfigureUniversalImageLoader();
+ }
+
+ private void ConfigureUniversalImageLoader()
+ {
+ // Create global configuration and initialize ImageLoader with this config
+ ImageLoaderConfiguration config = new ImageLoaderConfiguration
+ .Builder(Context)
+ .Build();
+
+ ImageLoader.Instance.Init(config);
+
+ ImageSource.DefaultImageLoader = ImageLoader.Instance.LoadImageAsync;
+ }
+ }
+}
diff --git a/src/SamplesApp/SamplesApp.Droid/MainActivity.cs b/src/SamplesApp/SamplesApp.Droid/MainActivity.cs
new file mode 100644
index 000000000000..e694b53cb3c7
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Droid/MainActivity.cs
@@ -0,0 +1,18 @@
+using Android.App;
+using Android.Widget;
+using Android.OS;
+using Android.Content.PM;
+using Android.Views;
+
+namespace SamplesApp.Droid
+{
+ [Activity(
+ MainLauncher = true,
+ ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.ScreenSize,
+ WindowSoftInputMode = SoftInput.AdjustPan | SoftInput.StateHidden
+ )]
+ public class MainActivity : Windows.UI.Xaml.ApplicationActivity
+ {
+ }
+}
+
diff --git a/src/SamplesApp/SamplesApp.Droid/Properties/AndroidManifest.xml b/src/SamplesApp/SamplesApp.Droid/Properties/AndroidManifest.xml
new file mode 100644
index 000000000000..af9e8c260fa0
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Droid/Properties/AndroidManifest.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.Droid/Properties/AssemblyInfo.cs b/src/SamplesApp/SamplesApp.Droid/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000000..d1561776b4ae
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Droid/Properties/AssemblyInfo.cs
@@ -0,0 +1,30 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Android.App;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("UnoQuickStart.Droid")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("UnoQuickStart.Droid")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+[assembly: ComVisible(false)]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/SamplesApp/SamplesApp.Droid/Resources/AboutResources.txt b/src/SamplesApp/SamplesApp.Droid/Resources/AboutResources.txt
new file mode 100644
index 000000000000..c2bca974c48c
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Droid/Resources/AboutResources.txt
@@ -0,0 +1,44 @@
+Images, layout descriptions, binary blobs and string dictionaries can be included
+in your application as resource files. Various Android APIs are designed to
+operate on the resource IDs instead of dealing with images, strings or binary blobs
+directly.
+
+For example, a sample Android app that contains a user interface layout (main.axml),
+an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png)
+would keep its resources in the "Resources" directory of the application:
+
+Resources/
+ drawable/
+ icon.png
+
+ layout/
+ main.axml
+
+ values/
+ strings.xml
+
+In order to get the build system to recognize Android resources, set the build action to
+"AndroidResource". The native Android APIs do not operate directly with filenames, but
+instead operate on resource IDs. When you compile an Android application that uses resources,
+the build system will package the resources for distribution and generate a class called "R"
+(this is an Android convention) that contains the tokens for each one of the resources
+included. For example, for the above Resources layout, this is what the R class would expose:
+
+public class R {
+ public class drawable {
+ public const int icon = 0x123;
+ }
+
+ public class layout {
+ public const int main = 0x456;
+ }
+
+ public class strings {
+ public const int first_string = 0xabc;
+ public const int second_string = 0xbcd;
+ }
+}
+
+You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main
+to reference the layout/main.axml file, or R.strings.first_string to reference the first
+string in the dictionary file values/strings.xml.
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.Droid/Resources/drawable/Icon.png b/src/SamplesApp/SamplesApp.Droid/Resources/drawable/Icon.png
new file mode 100644
index 000000000000..8074c4c571b8
Binary files /dev/null and b/src/SamplesApp/SamplesApp.Droid/Resources/drawable/Icon.png differ
diff --git a/src/SamplesApp/SamplesApp.Droid/Resources/values/Strings.xml b/src/SamplesApp/SamplesApp.Droid/Resources/values/Strings.xml
new file mode 100644
index 000000000000..d4c27901644d
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Droid/Resources/values/Strings.xml
@@ -0,0 +1,5 @@
+
+
+ Hello World, Click Me!
+ UnoQuickStart.Droid
+
diff --git a/src/SamplesApp/SamplesApp.Droid/Resources/values/Styles.xml b/src/SamplesApp/SamplesApp.Droid/Resources/values/Styles.xml
new file mode 100644
index 000000000000..d668a8e04037
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Droid/Resources/values/Styles.xml
@@ -0,0 +1,12 @@
+
+
+
+
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.Droid/SamplesApp.Droid.csproj b/src/SamplesApp/SamplesApp.Droid/SamplesApp.Droid.csproj
new file mode 100644
index 000000000000..fa5cfe1f756d
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Droid/SamplesApp.Droid.csproj
@@ -0,0 +1,112 @@
+
+
+
+ Debug
+ AnyCPU
+ 8.0.30703
+ 2.0
+ {3FDF0F2D-CC11-49BE-8634-F81638D595C6}
+ {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Library
+ Properties
+ SamplesApp.Droid
+ SamplesApp.Droid
+ 512
+ true
+ Resources\Resource.Designer.cs
+ Off
+ False
+ v8.0
+ Properties\AndroidManifest.xml
+ True
+ ..\SamplesApp.Shared\Strings
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ True
+ None
+
+
+ pdbonly
+ true
+ true
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+ False
+ SdkOnly
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.27.0
+ NU1701
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\SourceGenerators\Uno.UI.SourceGenerators\bin\$(Configuration)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/Uno.UI.Wasm.Shell/App.xaml b/src/SamplesApp/SamplesApp.Shared/App.xaml
similarity index 71%
rename from src/Uno.UI.Wasm.Shell/App.xaml
rename to src/SamplesApp/SamplesApp.Shared/App.xaml
index 194d9e50bac3..ccdf81283c00 100644
--- a/src/Uno.UI.Wasm.Shell/App.xaml
+++ b/src/SamplesApp/SamplesApp.Shared/App.xaml
@@ -1,8 +1,8 @@
diff --git a/src/SamplesApp/SamplesApp.Shared/App.xaml.cs b/src/SamplesApp/SamplesApp.Shared/App.xaml.cs
new file mode 100644
index 000000000000..cee70d495991
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Shared/App.xaml.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.ApplicationModel;
+using Windows.ApplicationModel.Activation;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+
+namespace SamplesApp
+{
+ ///
+ /// Provides application-specific behavior to supplement the default Application class.
+ ///
+ sealed partial class App : Application
+ {
+ ///
+ /// Initializes the singleton application object. This is the first line of authored code
+ /// executed, and as such is the logical equivalent of main() or WinMain().
+ ///
+ public App()
+ {
+ this.InitializeComponent();
+ this.Suspending += OnSuspending;
+ }
+
+ ///
+ /// Invoked when the application is launched normally by the end user. Other entry points
+ /// will be used such as when the application is launched to open a specific file.
+ ///
+ /// Details about the launch request and process.
+ protected override void OnLaunched(LaunchActivatedEventArgs e)
+ {
+#if DEBUG
+ if (System.Diagnostics.Debugger.IsAttached)
+ {
+ // this.DebugSettings.EnableFrameRateCounter = true;
+ }
+#endif
+ Frame rootFrame = Windows.UI.Xaml.Window.Current.Content as Frame;
+
+ // Do not repeat app initialization when the Window already has content,
+ // just ensure that the window is active
+ if (rootFrame == null)
+ {
+ // Create a Frame to act as the navigation context and navigate to the first page
+ rootFrame = new Frame();
+
+ rootFrame.NavigationFailed += OnNavigationFailed;
+
+ if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
+ {
+ //TODO: Load state from previously suspended application
+ }
+
+ // Place the frame in the current Window
+ Windows.UI.Xaml.Window.Current.Content = rootFrame;
+ }
+
+ if (e.PrelaunchActivated == false)
+ {
+ if (rootFrame.Content == null)
+ {
+ // When the navigation stack isn't restored navigate to the first page,
+ // configuring the new page by passing required information as a navigation
+ // parameter
+ rootFrame.Navigate(typeof(MainPage), e.Arguments);
+ }
+ // Ensure the current window is active
+ Windows.UI.Xaml.Window.Current.Activate();
+ }
+ }
+
+ ///
+ /// Invoked when Navigation to a certain page fails
+ ///
+ /// The Frame which failed navigation
+ /// Details about the navigation failure
+ void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
+ {
+ throw new Exception("Failed to load Page " + e.SourcePageType.FullName);
+ }
+
+ ///
+ /// Invoked when application execution is being suspended. Application state is saved
+ /// without knowing whether the application will be terminated or resumed with the contents
+ /// of memory still intact.
+ ///
+ /// The source of the suspend request.
+ /// Details about the suspend request.
+ private void OnSuspending(object sender, SuspendingEventArgs e)
+ {
+ var deferral = e.SuspendingOperation.GetDeferral();
+ //TODO: Save application state and stop any background activity
+ deferral.Complete();
+ }
+ }
+}
diff --git a/src/SamplesApp/SamplesApp.Shared/Assets/lockscreenlogo.scale-200.png b/src/SamplesApp/SamplesApp.Shared/Assets/lockscreenlogo.scale-200.png
new file mode 100644
index 000000000000..735f57adb5df
Binary files /dev/null and b/src/SamplesApp/SamplesApp.Shared/Assets/lockscreenlogo.scale-200.png differ
diff --git a/src/SamplesApp/SamplesApp.Shared/Assets/splashscreen.scale-200.png b/src/SamplesApp/SamplesApp.Shared/Assets/splashscreen.scale-200.png
new file mode 100644
index 000000000000..023e7f1feda7
Binary files /dev/null and b/src/SamplesApp/SamplesApp.Shared/Assets/splashscreen.scale-200.png differ
diff --git a/src/SamplesApp/SamplesApp.Shared/Assets/square150x150logo.scale-200.png b/src/SamplesApp/SamplesApp.Shared/Assets/square150x150logo.scale-200.png
new file mode 100644
index 000000000000..af49fec1a548
Binary files /dev/null and b/src/SamplesApp/SamplesApp.Shared/Assets/square150x150logo.scale-200.png differ
diff --git a/src/SamplesApp/SamplesApp.Shared/Assets/square44x44logo.scale-200.png b/src/SamplesApp/SamplesApp.Shared/Assets/square44x44logo.scale-200.png
new file mode 100644
index 000000000000..ce342a2ec8a6
Binary files /dev/null and b/src/SamplesApp/SamplesApp.Shared/Assets/square44x44logo.scale-200.png differ
diff --git a/src/SamplesApp/SamplesApp.Shared/Assets/square44x44logo.targetsize-24_altform-unplated.png b/src/SamplesApp/SamplesApp.Shared/Assets/square44x44logo.targetsize-24_altform-unplated.png
new file mode 100644
index 000000000000..f6c02ce97e0a
Binary files /dev/null and b/src/SamplesApp/SamplesApp.Shared/Assets/square44x44logo.targetsize-24_altform-unplated.png differ
diff --git a/src/SamplesApp/SamplesApp.Shared/Assets/storelogo.png b/src/SamplesApp/SamplesApp.Shared/Assets/storelogo.png
new file mode 100644
index 000000000000..7385b56c0e4d
Binary files /dev/null and b/src/SamplesApp/SamplesApp.Shared/Assets/storelogo.png differ
diff --git a/src/SamplesApp/SamplesApp.Shared/Assets/wide310x150logo.scale-200.png b/src/SamplesApp/SamplesApp.Shared/Assets/wide310x150logo.scale-200.png
new file mode 100644
index 000000000000..288995b397fd
Binary files /dev/null and b/src/SamplesApp/SamplesApp.Shared/Assets/wide310x150logo.scale-200.png differ
diff --git a/src/SamplesApp/SamplesApp.Shared/MainPage.xaml b/src/SamplesApp/SamplesApp.Shared/MainPage.xaml
new file mode 100644
index 000000000000..95b38998f501
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Shared/MainPage.xaml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/SamplesApp/SamplesApp.Shared/MainPage.xaml.cs b/src/SamplesApp/SamplesApp.Shared/MainPage.xaml.cs
new file mode 100644
index 000000000000..24d7590de59d
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Shared/MainPage.xaml.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.InteropServices.WindowsRuntime;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+using Windows.UI.Xaml.Controls.Primitives;
+using Windows.UI.Xaml.Data;
+using Windows.UI.Xaml.Input;
+using Windows.UI.Xaml.Media;
+using Windows.UI.Xaml.Navigation;
+
+// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
+
+namespace SamplesApp
+{
+ ///
+ /// An empty page that can be used on its own or navigated to within a Frame.
+ ///
+ public sealed partial class MainPage : Page
+ {
+ public MainPage()
+ {
+ this.InitializeComponent();
+ }
+ }
+}
diff --git a/src/SamplesApp/SamplesApp.Shared/SamplesApp.Shared.projitems b/src/SamplesApp/SamplesApp.Shared/SamplesApp.Shared.projitems
new file mode 100644
index 000000000000..a14bc536a752
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Shared/SamplesApp.Shared.projitems
@@ -0,0 +1,43 @@
+
+
+
+ $(MSBuildAllProjects);$(MSBuildThisFileFullPath)
+ true
+ 6279c845-92f8-4333-ab99-3d213163593c
+
+
+ SamplesApp.Shared
+
+
+
+ Designer
+ MSBuild:Compile
+
+
+
+
+ App.xaml
+
+
+ MainPage.xaml
+
+
+
+
+ Designer
+ MSBuild:Compile
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.Shared/SamplesApp.Shared.shproj b/src/SamplesApp/SamplesApp.Shared/SamplesApp.Shared.shproj
new file mode 100644
index 000000000000..19dad59b2c5c
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Shared/SamplesApp.Shared.shproj
@@ -0,0 +1,13 @@
+
+
+
+ 6279c845-92f8-4333-ab99-3d213163593c
+ 14.0
+
+
+
+
+
+
+
+
diff --git a/src/SamplesApp/SamplesApp.Shared/Strings/en/Resources.resw b/src/SamplesApp/SamplesApp.Shared/Strings/en/Resources.resw
new file mode 100644
index 000000000000..a78bac371884
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Shared/Strings/en/Resources.resw
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ SamplesApp
+
+
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.UWP/Package.appxmanifest b/src/SamplesApp/SamplesApp.UWP/Package.appxmanifest
new file mode 100644
index 000000000000..af0ec6e66da1
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.UWP/Package.appxmanifest
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+ SamplesApp
+ SamplesApp
+ Assets\StoreLogo.png
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.UWP/Properties/AssemblyInfo.cs b/src/SamplesApp/SamplesApp.UWP/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000000..1e69d08e594c
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.UWP/Properties/AssemblyInfo.cs
@@ -0,0 +1,29 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("UnoQuickStart")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("UnoQuickStart")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
+[assembly: ComVisible(false)]
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.UWP/Properties/Default.rd.xml b/src/SamplesApp/SamplesApp.UWP/Properties/Default.rd.xml
new file mode 100644
index 000000000000..80a960ce32fc
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.UWP/Properties/Default.rd.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.UWP/SamplesApp.UWP.csproj b/src/SamplesApp/SamplesApp.UWP/SamplesApp.UWP.csproj
new file mode 100644
index 000000000000..1b9df3d356d4
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.UWP/SamplesApp.UWP.csproj
@@ -0,0 +1,122 @@
+
+
+
+
+
+ 6.1.7
+
+
+
+ Debug
+ x86
+ {6C25BEB3-E332-48D3-B4DE-20A0B71935CD}
+ AppContainerExe
+ Properties
+ SamplesApp
+ SamplesApp
+ en-US
+ UAP
+ 10.0.16299.0
+ 10.0.16299.0
+ 14
+ 512
+ {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ SamplesApp.Uwp_TemporaryKey.pfx
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ x86
+ false
+ prompt
+ true
+
+
+ bin\x86\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ x86
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\ARM\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ ARM
+ false
+ prompt
+ true
+
+
+ bin\ARM\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ ARM
+ false
+ prompt
+ true
+ true
+
+
+ true
+ bin\x64\Debug\
+ DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP
+ ;2008
+ full
+ x64
+ false
+ prompt
+ true
+
+
+ bin\x64\Release\
+ TRACE;NETFX_CORE;WINDOWS_UWP
+ true
+ ;2008
+ pdbonly
+ x64
+ false
+ prompt
+ true
+ true
+
+
+
+
+
+
+
+
+
+ Designer
+
+
+
+
+
+
+
+
+ 14.0
+
+
+
+
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.WPF/App.config b/src/SamplesApp/SamplesApp.WPF/App.config
new file mode 100644
index 000000000000..016d28fcc6ff
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.WPF/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.WPF/App.xaml b/src/SamplesApp/SamplesApp.WPF/App.xaml
new file mode 100644
index 000000000000..168316bb3a02
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.WPF/App.xaml
@@ -0,0 +1,25 @@
+
+
+
+
+
+
diff --git a/src/SamplesApp/SamplesApp.WPF/App.xaml.cs b/src/SamplesApp/SamplesApp.WPF/App.xaml.cs
new file mode 100644
index 000000000000..c2df56f9fee4
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.WPF/App.xaml.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Configuration;
+using System.Data;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Windows;
+
+namespace SamplesApp.WPF
+{
+ ///
+ /// Interaction logic for App.xaml
+ ///
+ public partial class App : Application
+ {
+ }
+}
diff --git a/src/SamplesApp/SamplesApp.WPF/MainWindow.xaml b/src/SamplesApp/SamplesApp.WPF/MainWindow.xaml
new file mode 100644
index 000000000000..f518196ac027
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.WPF/MainWindow.xaml
@@ -0,0 +1,13 @@
+
+
+
+
+
diff --git a/src/SamplesApp/SamplesApp.WPF/MainWindow.xaml.cs b/src/SamplesApp/SamplesApp.WPF/MainWindow.xaml.cs
new file mode 100644
index 000000000000..a5e7bb7e0d77
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.WPF/MainWindow.xaml.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Uno.UI.WpfHost;
+
+namespace SamplesApp.WPF
+{
+ ///
+ /// Interaction logic for MainWindow.xaml
+ ///
+ public partial class MainWindow : Window
+ {
+ public MainWindow()
+ {
+#if DEBUG
+ var configuration = "Debug";
+#else
+ var configuration = "Release";
+#endif
+
+ UnoHostView.Init(() => SamplesApp.Wasm.Program.Main(new string[0]), $@"..\..\..\..\SamplesApp.Wasm\bin\{configuration}\netstandard2.0\dist");
+
+ InitializeComponent();
+ }
+ }
+}
diff --git a/src/SamplesApp/SamplesApp.WPF/Properties/AssemblyInfo.cs b/src/SamplesApp/SamplesApp.WPF/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000000..fcd66d147594
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.WPF/Properties/AssemblyInfo.cs
@@ -0,0 +1,55 @@
+using System.Reflection;
+using System.Resources;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Windows;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("SamplesApp.WPF")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("SamplesApp.WPF")]
+[assembly: AssemblyCopyright("Copyright © 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+//In order to begin building localizable applications, set
+//CultureYouAreCodingWith in your .csproj file
+//inside a . For example, if you are using US english
+//in your source files, set the to en-US. Then uncomment
+//the NeutralResourceLanguage attribute below. Update the "en-US" in
+//the line below to match the UICulture setting in the project file.
+
+//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
+
+
+[assembly: ThemeInfo(
+ ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
+ //(used if a resource is not found in the page,
+ // or application resource dictionaries)
+ ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
+ //(used if a resource is not found in the page,
+ // app, or any theme specific resource dictionaries)
+)]
+
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/SamplesApp/SamplesApp.WPF/Properties/Resources.Designer.cs b/src/SamplesApp/SamplesApp.WPF/Properties/Resources.Designer.cs
new file mode 100644
index 000000000000..6b8931d2b6d4
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.WPF/Properties/Resources.Designer.cs
@@ -0,0 +1,71 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace SamplesApp.WPF.Properties
+{
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources
+ {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources()
+ {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager
+ {
+ get
+ {
+ if ((resourceMan == null))
+ {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SamplesApp.WPF.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture
+ {
+ get
+ {
+ return resourceCulture;
+ }
+ set
+ {
+ resourceCulture = value;
+ }
+ }
+ }
+}
diff --git a/src/SamplesApp/SamplesApp.WPF/Properties/Resources.resx b/src/SamplesApp/SamplesApp.WPF/Properties/Resources.resx
new file mode 100644
index 000000000000..af7dbebbacef
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.WPF/Properties/Resources.resx
@@ -0,0 +1,117 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.WPF/Properties/Settings.Designer.cs b/src/SamplesApp/SamplesApp.WPF/Properties/Settings.Designer.cs
new file mode 100644
index 000000000000..d7fa2d356865
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.WPF/Properties/Settings.Designer.cs
@@ -0,0 +1,30 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace SamplesApp.WPF.Properties
+{
+
+
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
+ internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
+ {
+
+ private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
+
+ public static Settings Default
+ {
+ get
+ {
+ return defaultInstance;
+ }
+ }
+ }
+}
diff --git a/src/SamplesApp/SamplesApp.WPF/Properties/Settings.settings b/src/SamplesApp/SamplesApp.WPF/Properties/Settings.settings
new file mode 100644
index 000000000000..033d7a5e9e22
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.WPF/Properties/Settings.settings
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.WPF/SamplesApp.WPF.csproj b/src/SamplesApp/SamplesApp.WPF/SamplesApp.WPF.csproj
new file mode 100644
index 000000000000..4c8f8179c557
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.WPF/SamplesApp.WPF.csproj
@@ -0,0 +1,159 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {2622209D-C306-4ECF-8005-88132EFF943E}
+ WinExe
+ SamplesApp.WPF
+ SamplesApp.WPF
+ v4.7
+ 512
+ {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ 4
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ true
+ bin\x86\Debug\
+ DEBUG;TRACE
+ ;1998
+ full
+ x86
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+
+
+ true
+ bin\x86\Release\
+ TRACE
+ true
+ ;1998
+ pdbonly
+ x86
+ prompt
+ MinimumRecommendedRules.ruleset
+ true
+
+
+
+ ..\SamplesApp.Wasm\bin\$(Configuration)\netstandard2.0\SamplesApp.Wasm.dll
+
+
+
+
+
+
+
+
+
+
+ 4.0
+
+
+ ..\..\Uno.UI\bin\$(Configuration)\netstandard2.0\Uno.dll
+
+
+ ..\..\Uno.UI\bin\$(Configuration)\netstandard2.0\Uno.Foundation.dll
+
+
+ ..\..\Uno.UI\bin\$(Configuration)\netstandard2.0\Uno.UI.dll
+
+
+ ..\..\Uno.UI\bin\$(Configuration)\netstandard2.0\Uno.Xaml.dll
+
+
+
+
+
+
+
+ 3.3396.1786
+
+
+ 3.3396.1786
+
+
+ 67.0.0
+
+
+ 67.0.0
+
+
+ 4.1.0
+
+
+
+
+ MSBuild:Compile
+ Designer
+
+
+ MSBuild:Compile
+ Designer
+
+
+ App.xaml
+ Code
+
+
+ MainWindow.xaml
+ Code
+
+
+
+
+ Code
+
+
+ True
+ True
+ Resources.resx
+
+
+ True
+ Settings.settings
+ True
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+ SettingsSingleFileGenerator
+ Settings.Designer.cs
+
+
+
+
+
+
+
+ {2257a641-9fe7-4f96-9674-b5c61815194a}
+ Uno.UI.WpfHost
+
+
+
+
diff --git a/src/SamplesApp/SamplesApp.Wasm/Fonts/winjs-symbols.woff2 b/src/SamplesApp/SamplesApp.Wasm/Fonts/winjs-symbols.woff2
new file mode 100644
index 000000000000..615c0a4c1b57
Binary files /dev/null and b/src/SamplesApp/SamplesApp.Wasm/Fonts/winjs-symbols.woff2 differ
diff --git a/src/SamplesApp/SamplesApp.Wasm/LinkerConfig.xml b/src/SamplesApp/SamplesApp.Wasm/LinkerConfig.xml
new file mode 100644
index 000000000000..09deb3746b4a
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Wasm/LinkerConfig.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/src/SamplesApp/SamplesApp.Wasm/Program.cs b/src/SamplesApp/SamplesApp.Wasm/Program.cs
new file mode 100644
index 000000000000..047898bbfe69
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Wasm/Program.cs
@@ -0,0 +1,15 @@
+using System;
+using Windows.UI.Xaml;
+
+namespace SamplesApp.Wasm
+{
+ public class Program
+ {
+ private static App _app;
+
+ public static void Main(string[] args)
+ {
+ Windows.UI.Xaml.Application.Start(_ => _app = new App());
+ }
+ }
+}
diff --git a/src/SamplesApp/SamplesApp.Wasm/SamplesApp.Wasm.csproj b/src/SamplesApp/SamplesApp.Wasm/SamplesApp.Wasm.csproj
new file mode 100644
index 000000000000..c6777e4b0e73
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Wasm/SamplesApp.Wasm.csproj
@@ -0,0 +1,56 @@
+
+
+
+ Exe
+ netstandard2.0
+ true
+ $(DefineConstants);__WASM__
+ NU1701
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.27.0
+ NU1701
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\SourceGenerators\Uno.UI.SourceGenerators\bin\$(Configuration)
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.Wasm/WasmCSS/Fonts.css b/src/SamplesApp/SamplesApp.Wasm/WasmCSS/Fonts.css
new file mode 100644
index 000000000000..00e838eccfa1
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Wasm/WasmCSS/Fonts.css
@@ -0,0 +1,4 @@
+@font-face {
+ font-family: "Symbols";
+ src: url("Fonts/winjs-symbols.woff2") format('woff');
+}
diff --git a/src/SamplesApp/SamplesApp.Wasm/WasmScripts/AppManifest.js b/src/SamplesApp/SamplesApp.Wasm/WasmScripts/AppManifest.js
new file mode 100644
index 000000000000..a82c02bcb629
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.Wasm/WasmScripts/AppManifest.js
@@ -0,0 +1,7 @@
+var UnoAppManifest = {
+
+ splashScreenImage: "Assets/SplashScreen.scale-200.png",
+ splashScreenColor: "#00f",
+ displayName: "SamplesApp"
+
+}
diff --git a/src/SamplesApp/SamplesApp.iOS/Entitlements.plist b/src/SamplesApp/SamplesApp.iOS/Entitlements.plist
new file mode 100644
index 000000000000..24c3103683fa
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.iOS/Entitlements.plist
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/src/SamplesApp/SamplesApp.iOS/Info.plist b/src/SamplesApp/SamplesApp.iOS/Info.plist
new file mode 100644
index 000000000000..ac07a45b86c3
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.iOS/Info.plist
@@ -0,0 +1,42 @@
+
+
+
+
+ CFBundleDisplayName
+ UnoQuickStart.iOS
+ CFBundleIdentifier
+ com.companyname.SamplesApp
+ CFBundleShortVersionString
+ 1.0
+ CFBundleVersion
+ 1.0
+ LSRequiresIPhoneOS
+
+ MinimumOSVersion
+
+ UIDeviceFamily
+
+ 1
+ 2
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIRequiredDeviceCapabilities
+
+ armv7
+
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+
+
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.iOS/Main.cs b/src/SamplesApp/SamplesApp.iOS/Main.cs
new file mode 100644
index 000000000000..a5d77d30c358
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.iOS/Main.cs
@@ -0,0 +1,15 @@
+using UIKit;
+
+namespace SamplesApp.iOS
+{
+ public class Application
+ {
+ // This is the main entry point of the application.
+ static void Main(string[] args)
+ {
+ // if you want to use a different Application Delegate class from "AppDelegate"
+ // you can specify it here.
+ UIApplication.Main(args, null, typeof(App));
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/SamplesApp/SamplesApp.iOS/Properties/AssemblyInfo.cs b/src/SamplesApp/SamplesApp.iOS/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000000..eceb25c0e9dd
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.iOS/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("UnoQuickStart.iOS")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("UnoQuickStart.iOS")]
+[assembly: AssemblyCopyright("Copyright © 2016")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("166de4ca-8f11-4ef9-bcf8-3e7834988e7d")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/src/SamplesApp/SamplesApp.iOS/SamplesApp.iOS.csproj b/src/SamplesApp/SamplesApp.iOS/SamplesApp.iOS.csproj
new file mode 100644
index 000000000000..052dff3774bf
--- /dev/null
+++ b/src/SamplesApp/SamplesApp.iOS/SamplesApp.iOS.csproj
@@ -0,0 +1,124 @@
+
+
+
+ Debug
+ iPhoneSimulator
+ {B71AE380-558C-4D6C-81D8-9C043B50262C}
+ {FEACFBD2-3405-455C-9665-78FE426C6842};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
+ Exe
+ SamplesApp
+ Resources
+ SamplesApp
+
+
+ ..\SamplesApp.Shared\Strings
+
+
+ true
+ full
+ false
+ bin\iPhoneSimulator\Debug
+ DEBUG
+ prompt
+ 4
+ false
+ x86_64
+ None
+ true
+
+
+ none
+ true
+ bin\iPhoneSimulator\Release
+ prompt
+ 4
+ None
+ x86_64
+ false
+
+
+ true
+ full
+ false
+ bin\iPhone\Debug
+ DEBUG
+ prompt
+ 4
+ false
+ ARM64
+ Entitlements.plist
+ iPhone Developer
+ true
+
+
+ none
+ true
+ bin\iPhone\Release
+ prompt
+ 4
+ Entitlements.plist
+ ARM64
+ false
+ iPhone Developer
+
+
+ none
+ True
+ bin\iPhone\Ad-Hoc
+ prompt
+ 4
+ False
+ ARM64
+ Entitlements.plist
+ True
+ Automatic:AdHoc
+ iPhone Distribution
+
+
+ none
+ True
+ bin\iPhone\AppStore
+ prompt
+ 4
+ False
+ ARM64
+ Entitlements.plist
+ Automatic:AppStore
+ iPhone Distribution
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 1.27.0
+ NU1701
+
+
+
+
+
+
+
+
+
+
+
+ ..\..\SourceGenerators\Uno.UI.SourceGenerators\bin\$(Configuration)
+
+
+
+
+
+
+
diff --git a/src/SolutionTemplate/UnoLibraryTemplate/CrossTargetedLibrary.csproj b/src/SolutionTemplate/UnoLibraryTemplate/CrossTargetedLibrary.csproj
index 03ea2e80a450..536ca74e235e 100644
--- a/src/SolutionTemplate/UnoLibraryTemplate/CrossTargetedLibrary.csproj
+++ b/src/SolutionTemplate/UnoLibraryTemplate/CrossTargetedLibrary.csproj
@@ -12,7 +12,7 @@
-
+
diff --git a/src/SolutionTemplate/UnoSolutionTemplate.VISX/UnoSolutionTemplate.VISX.csproj b/src/SolutionTemplate/UnoSolutionTemplate.VISX/UnoSolutionTemplate.VISX.csproj
index f9ac40087384..1f423de0b84d 100644
--- a/src/SolutionTemplate/UnoSolutionTemplate.VISX/UnoSolutionTemplate.VISX.csproj
+++ b/src/SolutionTemplate/UnoSolutionTemplate.VISX/UnoSolutionTemplate.VISX.csproj
@@ -67,6 +67,9 @@
Designer
+
+ Always
+
diff --git a/src/SolutionTemplate/UnoSolutionTemplate.VISX/winjs-symbols.ttf b/src/SolutionTemplate/UnoSolutionTemplate.VISX/winjs-symbols.ttf
new file mode 100644
index 000000000000..f502611c3b6a
Binary files /dev/null and b/src/SolutionTemplate/UnoSolutionTemplate.VISX/winjs-symbols.ttf differ
diff --git a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Droid/Android.vstemplate b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Droid/Android.vstemplate
index cc30bf8844af..356aba963717 100644
--- a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Droid/Android.vstemplate
+++ b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Droid/Android.vstemplate
@@ -21,6 +21,9 @@
Main.cs
AboutAssets.txt
+
+ winjs-symbols.ttf
+
AndroidManifest.xml
@@ -38,4 +41,4 @@
-
\ No newline at end of file
+
diff --git a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Droid/Assets/Fonts/winjs-symbols.ttf b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Droid/Assets/Fonts/winjs-symbols.ttf
new file mode 100644
index 000000000000..f502611c3b6a
Binary files /dev/null and b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Droid/Assets/Fonts/winjs-symbols.ttf differ
diff --git a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Droid/UnoQuickStart.Droid.csproj b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Droid/UnoQuickStart.Droid.csproj
index 797742212baa..5ebdd5751528 100644
--- a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Droid/UnoQuickStart.Droid.csproj
+++ b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Droid/UnoQuickStart.Droid.csproj
@@ -54,8 +54,8 @@
-
-
+
+
@@ -63,6 +63,7 @@
+
@@ -77,7 +78,7 @@
-
+
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
diff --git a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Wasm/UnoQuickStart.Wasm.csproj b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Wasm/UnoQuickStart.Wasm.csproj
index e9e53b9e8a9a..6a6b81a880df 100644
--- a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Wasm/UnoQuickStart.Wasm.csproj
+++ b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Wasm/UnoQuickStart.Wasm.csproj
@@ -27,7 +27,7 @@
This item group is required by the project templace because of the
new SDK-Style project, otherwise some files are not aded automatically.
- You can safely this ItemGroup completely.
+ You can safely remove this ItemGroup completely.
-->
@@ -35,8 +35,8 @@
-
-
+
+
diff --git a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Wasm/Wasm.vstemplate b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Wasm/Wasm.vstemplate
index 1c7f348d23d1..efd65627e44f 100644
--- a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Wasm/Wasm.vstemplate
+++ b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.Wasm/Wasm.vstemplate
@@ -18,7 +18,7 @@
Program.cs
- LinkerConfig.xml
+ LinkerConfig.xml
winjs-symbols.woff2
diff --git a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/Info.plist b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/Info.plist
index c295957614bd..f9c48f2bd9a8 100644
--- a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/Info.plist
+++ b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/Info.plist
@@ -38,5 +38,9 @@
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
+ UIAppFonts
+
+ Fonts/winjs-symbols.ttf
+
-
\ No newline at end of file
+
diff --git a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/Resources/Fonts/winjs-symbols.ttf b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/Resources/Fonts/winjs-symbols.ttf
new file mode 100644
index 000000000000..f502611c3b6a
Binary files /dev/null and b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/Resources/Fonts/winjs-symbols.ttf differ
diff --git a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/UnoQuickStart.iOS.csproj b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/UnoQuickStart.iOS.csproj
index fdb605fcf88e..5eeaefdd012f 100644
--- a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/UnoQuickStart.iOS.csproj
+++ b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/UnoQuickStart.iOS.csproj
@@ -99,7 +99,10 @@
-
+
+
+
+
diff --git a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/iOS.vstemplate b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/iOS.vstemplate
index c3775c4f1fd2..1dbc7dc96a8b 100644
--- a/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/iOS.vstemplate
+++ b/src/SolutionTemplate/UnoSolutionTemplate/UnoQuickStart.iOS/iOS.vstemplate
@@ -25,7 +25,10 @@
Default-568h@2x.png
+
+ winjs-symbols.ttf
+
-
\ No newline at end of file
+
diff --git a/src/SolutionTemplate/UnoSolutionTemplate/UnoSolutionTemplate.csproj b/src/SolutionTemplate/UnoSolutionTemplate/UnoSolutionTemplate.csproj
index 02a7e3903d91..04635b99c048 100644
--- a/src/SolutionTemplate/UnoSolutionTemplate/UnoSolutionTemplate.csproj
+++ b/src/SolutionTemplate/UnoSolutionTemplate/UnoSolutionTemplate.csproj
@@ -75,6 +75,12 @@
+
+ Always
+
+
+ Always
+
Designer
@@ -104,7 +110,9 @@
-
+
+ Designer
+
@@ -114,7 +122,9 @@
-
+
+ Designer
+
Designer
@@ -174,4 +184,4 @@
-->
-
\ No newline at end of file
+
diff --git a/src/SourceGenerators/System.Xaml.Tests.MS/XmlFiles/Generic.Native.xaml b/src/SourceGenerators/System.Xaml.Tests.MS/XmlFiles/Generic.Native.xaml
index f6df5f807683..85f57093f507 100644
--- a/src/SourceGenerators/System.Xaml.Tests.MS/XmlFiles/Generic.Native.xaml
+++ b/src/SourceGenerators/System.Xaml.Tests.MS/XmlFiles/Generic.Native.xaml
@@ -161,7 +161,7 @@
-
+
diff --git a/src/SourceGenerators/System.Xaml.Tests/Test/XmlFiles/Generic.Native.xaml b/src/SourceGenerators/System.Xaml.Tests/Test/XmlFiles/Generic.Native.xaml
index b011d76cfde1..8b5cf62935de 100644
--- a/src/SourceGenerators/System.Xaml.Tests/Test/XmlFiles/Generic.Native.xaml
+++ b/src/SourceGenerators/System.Xaml.Tests/Test/XmlFiles/Generic.Native.xaml
@@ -161,7 +161,7 @@
-
+
diff --git a/src/SourceGenerators/System.Xaml/Uno.Xaml.csproj b/src/SourceGenerators/System.Xaml/Uno.Xaml.csproj
index aa970166b42b..f304d7c1151d 100644
--- a/src/SourceGenerators/System.Xaml/Uno.Xaml.csproj
+++ b/src/SourceGenerators/System.Xaml/Uno.Xaml.csproj
@@ -6,7 +6,7 @@
True
obj\$(TargetFramework)\Resources\Resource.Designer.cs
- true
+ false
true
bin\$(Configuration)\$(TargetFramework)\
$(BaseIntermediateOutputPath)$(Configuration)\$(TargetFramework)\
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/DependencyObject/DependencyObjectGenerator.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/DependencyObject/DependencyObjectGenerator.cs
index 049f6fe0a2b0..46d7b5283c24 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators/DependencyObject/DependencyObjectGenerator.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators/DependencyObject/DependencyObjectGenerator.cs
@@ -6,6 +6,7 @@
using Microsoft.CodeAnalysis;
using Uno.Extensions;
using Uno.SourceGeneration;
+using Uno.UI.SourceGenerators.Helpers;
using Uno.UI.SourceGenerators.XamlGenerator;
namespace Uno.UI.SourceGenerators.DependencyObject
@@ -123,7 +124,7 @@ private void ProcessType(INamedTypeSymbol typeSymbol)
}
}
- _context.AddCompilationUnit(typeSymbol.GetFullName(), builder.ToString());
+ _context.AddCompilationUnit(HashBuilder.BuildIDFromSymbol(typeSymbol), builder.ToString());
}
}
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/Helpers/HashBuilder.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/Helpers/HashBuilder.cs
new file mode 100644
index 000000000000..773a196baf29
--- /dev/null
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators/Helpers/HashBuilder.cs
@@ -0,0 +1,44 @@
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Security.Cryptography;
+using System.Text;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis;
+
+namespace Uno.UI.SourceGenerators.Helpers
+{
+ internal class HashBuilder
+ {
+ ///
+ /// Build a stable ID from the provided symbol
+ ///
+ public static string BuildIDFromSymbol(ITypeSymbol typeSymbol)
+ => typeSymbol.GetFullName() + "_" + Build(typeSymbol.MetadataName + typeSymbol.ContainingAssembly.MetadataName);
+
+ public static string Build(string input)
+ {
+ using (var md5Hash = MD5.Create())
+ {
+ // Convert the input string to a byte array and compute the hash.
+ var data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
+
+ // Create a new Stringbuilder to collect the bytes
+ // and create a string.
+ var sBuilder = new StringBuilder();
+
+ // Loop through each byte of the hashed data
+ // and format each one as a hexadecimal string.
+ for (int i = 0; i < data.Length; i++)
+ {
+ sBuilder.Append(data[i].ToString("x2", CultureInfo.InvariantCulture));
+ }
+
+ // Return the hexadecimal string.
+ return sBuilder.ToString();
+ }
+ }
+ }
+}
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/NativeCtor/NativeCtorsGenerator.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/NativeCtor/NativeCtorsGenerator.cs
index b1f299bbfbd9..2e39aef8bd52 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators/NativeCtor/NativeCtorsGenerator.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators/NativeCtor/NativeCtorsGenerator.cs
@@ -5,6 +5,7 @@
using System.Text;
using System.Threading.Tasks;
using Uno.SourceGeneration;
+using Uno.UI.SourceGenerators.Helpers;
namespace Uno.UI.SourceGenerators.NativeCtor
{
@@ -129,7 +130,7 @@ private void ProcessType(INamedTypeSymbol typeSymbol)
if (nativeCtor == null)
{
_context.AddCompilationUnit(
- $"{(_fileIndex++).ToString("000")}_{typeSymbol.ToString()}",
+ HashBuilder.BuildIDFromSymbol(typeSymbol),
string.Format(
BaseClassFormat,
typeSymbol.ContainingNamespace,
@@ -152,7 +153,7 @@ private void ProcessType(INamedTypeSymbol typeSymbol)
if (nativeCtor == null)
{
_context.AddCompilationUnit(
- typeSymbol.GetFullName(),
+ HashBuilder.BuildIDFromSymbol(typeSymbol),
string.Format(
BaseClassFormat,
typeSymbol.ContainingNamespace,
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/Uno.UI.SourceGenerators.csproj b/src/SourceGenerators/Uno.UI.SourceGenerators/Uno.UI.SourceGenerators.csproj
index 50304b8f1fb2..df3671ec6623 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators/Uno.UI.SourceGenerators.csproj
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators/Uno.UI.SourceGenerators.csproj
@@ -51,10 +51,10 @@
1.24.0
- 1.26.0
+ 1.27.0
- 1.26.0
+ 1.27.0
@@ -92,6 +92,7 @@
+
@@ -144,8 +145,8 @@
-
-
+
+
-
+
\ No newline at end of file
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlCodeGeneration.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlCodeGeneration.cs
index d6f49bcd206c..ec8d01bb3309 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlCodeGeneration.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlCodeGeneration.cs
@@ -18,6 +18,7 @@ internal class XamlCodeGeneration
{
private string[] _xamlSourceFiles;
private string _targetPath;
+ private readonly string _defaultLanguage;
private bool _isWasm;
private string _defaultNamespace;
private string[] _assemblySearchPaths;
@@ -100,6 +101,8 @@ public XamlCodeGeneration(Compilation sourceCompilation, ProjectInstance msbProj
msbProject.GetProperty("IntermediateOutputPath").EvaluatedValue
);
+ _defaultLanguage = msbProject.GetProperty("DefaultLanguage")?.EvaluatedValue;
+
_analyzerSuppressions = msbProject
.GetItems("XamlGeneratorAnalyzerSuppressions")
.Select(i => i.EvaluatedInclude)
@@ -158,6 +161,7 @@ public KeyValuePair[] Generate()
resourceKeys: resourceKeys,
isUiAutomationMappingEnabled: _isUiAutomationMappingEnabled,
uiAutomationMappings: _uiAutomationMappings,
+ defaultLanguage: _defaultLanguage,
isWasm: _isWasm
)
.GenerateFile()
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileDefinition.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileDefinition.cs
index 4aaf4834d73d..9ae6b6e3d485 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileDefinition.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileDefinition.cs
@@ -6,6 +6,7 @@
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
+using Uno.UI.SourceGenerators.Helpers;
using Uno.UI.SourceGenerators.XamlGenerator.XamlRedirection;
namespace Uno.UI.SourceGenerators.XamlGenerator
@@ -18,7 +19,7 @@ public XamlFileDefinition(string file)
Objects = new List();
FilePath = file;
- UniqueID = SanitizedFileName + "_" + GetMd5Hash(FilePath);
+ UniqueID = SanitizedFileName + "_" + HashBuilder.Build(FilePath);
}
private string SanitizedFileName => Path
@@ -32,28 +33,5 @@ public XamlFileDefinition(string file)
public string FilePath { get; private set; }
public string UniqueID { get; }
-
- static string GetMd5Hash(string input)
- {
- using (MD5 md5Hash = MD5.Create())
- {
- // Convert the input string to a byte array and compute the hash.
- var data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
-
- // Create a new Stringbuilder to collect the bytes
- // and create a string.
- var sBuilder = new StringBuilder();
-
- // Loop through each byte of the hashed data
- // and format each one as a hexadecimal string.
- for (int i = 0; i < data.Length; i++)
- {
- sBuilder.Append(data[i].ToString("x2", CultureInfo.InvariantCulture));
- }
-
- // Return the hexadecimal string.
- return sBuilder.ToString();
- }
- }
}
}
diff --git a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs
index 9a2e1a600970..f564981d43a2 100644
--- a/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs
+++ b/src/SourceGenerators/Uno.UI.SourceGenerators/XamlGenerator/XamlFileGenerator.cs
@@ -62,7 +62,8 @@ internal class XamlFileGenerator
private XamlGlobalStaticResourcesMap _globalStaticResourcesMap;
private readonly bool _isUiAutomationMappingEnabled;
private readonly Dictionary _uiAutomationMappings;
- private readonly string _relativePath;
+ private readonly string _defaultLanguage;
+ private readonly string _relativePath;
private List _xamlAppliedTypes = new List();
@@ -100,6 +101,7 @@ public XamlFileGenerator(
XamlGlobalStaticResourcesMap globalStaticResourcesMap,
bool isUiAutomationMappingEnabled,
Dictionary uiAutomationMappings,
+ string defaultLanguage,
bool isWasm
)
{
@@ -115,8 +117,9 @@ bool isWasm
_globalStaticResourcesMap = globalStaticResourcesMap;
_isUiAutomationMappingEnabled = isUiAutomationMappingEnabled;
_uiAutomationMappings = uiAutomationMappings;
+ _defaultLanguage = defaultLanguage.HasValue() ? defaultLanguage : "en";
- _findType = Funcs.Create(SourceFindType).AsLockedMemoized();
+ _findType = Funcs.Create(SourceFindType).AsLockedMemoized();
_findPropertyTypeByXamlMember = Funcs.Create(SourceFindPropertyType).AsLockedMemoized();
_findEventType = Funcs.Create(SourceFindEventType).AsLockedMemoized();
_findPropertyTypeByName = Funcs.Create(SourceFindPropertyType).AsLockedMemoized();
@@ -344,8 +347,10 @@ private void BuildXamlApplyBlocks(IndentedStringBuilder writer)
private void BuildApplicationInitializerBody(IndentedStringBuilder writer, XamlObjectDefinition topLevelControl)
{
writer.AppendLineInvariant($"global::Windows.UI.Xaml.GenericStyles.Initialize();");
- writer.AppendLineInvariant($"global::Windows.UI.Xaml.ResourceDictionary.DefaultResolver = global::{_defaultNamespace}.GlobalStaticResources.FindResource;");
- writer.AppendLineInvariant($"global::{_defaultNamespace}.GlobalStaticResources.Initialize();");
+ writer.AppendLineInvariant($"global::Windows.UI.Xaml.ResourceDictionary.DefaultResolver = global::{_defaultNamespace}.GlobalStaticResources.FindResource;");
+ writer.AppendLineInvariant($"global::Windows.ApplicationModel.Resources.ResourceLoader.AddLookupAssembly(GetType().Assembly);");
+ writer.AppendLineInvariant($"global::Windows.ApplicationModel.Resources.ResourceLoader.DefaultLanguage = \"{_defaultLanguage}\";");
+ writer.AppendLineInvariant($"global::{_defaultNamespace}.GlobalStaticResources.Initialize();");
writer.AppendLineInvariant($"global::Uno.UI.DataBinding.BindableMetadata.Provider = new global::{_defaultNamespace}.BindableMetadataProvider();");
writer.AppendLineInvariant($"#if __ANDROID__");
@@ -2575,7 +2580,10 @@ private string BuildLiteralValue(INamedTypeSymbol propertyType, string memberVal
case "Windows.UI.Xaml.Controls.IconElement":
return "new Windows.UI.Xaml.Controls.SymbolIcon { Symbol = Windows.UI.Xaml.Controls.Symbol." + memberValue + "}";
- }
+
+ case "Windows.Media.Playback.IMediaPlaybackSource":
+ return "Windows.Media.Core.MediaSource.CreateFromUri(new Uri(\"" + memberValue + "\"))";
+ }
var isEnum = propertyType
.TypeKind == TypeKind.Enum;
diff --git a/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets b/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets
index ef498783df14..1d8ede4e4141 100644
--- a/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets
+++ b/src/SourceGenerators/Uno.UI.Tasks/Content/Uno.UI.Tasks.targets
@@ -34,6 +34,7 @@
+
diff --git a/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/ResourcesGenerationTask.cs b/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/ResourcesGenerationTask.cs
index 911505dec2a1..f39cc25e02a5 100644
--- a/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/ResourcesGenerationTask.cs
+++ b/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/ResourcesGenerationTask.cs
@@ -85,6 +85,10 @@ public override bool Execute()
{
return GenerateiOSResources(language, sourceLastWriteTime, resources, comment);
}
+ else if (TargetPlatform == "wasm")
+ {
+ return GenerateUnoPRIResources(language, sourceLastWriteTime, resources, comment);
+ }
return null;
})
@@ -101,6 +105,36 @@ public override bool Execute()
return false;
}
+ private ITaskItem GenerateUnoPRIResources(string language, DateTime sourceLastWriteTime, Dictionary resources, string comment)
+ {
+ var logicalTargetPath = Path.Combine($"{language}", "resources.upri");
+ var actualTargetPath = Path.Combine(OutputPath, logicalTargetPath);
+
+ Directory.CreateDirectory(Path.GetDirectoryName(actualTargetPath));
+
+ var targetLastWriteTime = new FileInfo(actualTargetPath).LastWriteTimeUtc;
+
+ if (sourceLastWriteTime > targetLastWriteTime)
+ {
+ this.Log().Info("Writing resources to {0}".InvariantCultureFormat(actualTargetPath));
+
+ UnoPRIResourcesWriter.Write(language, resources, actualTargetPath, comment);
+ }
+ else
+ {
+ this.Log().Info($"Skipping unmodified file {actualTargetPath}");
+ }
+
+ return new TaskItem
+ (
+ actualTargetPath,
+ new Dictionary()
+ {
+ { "LogicalName", logicalTargetPath.Replace(Path.DirectorySeparatorChar, '.') }
+ }
+ );
+ }
+
private ITaskItem GenerateiOSResources(string language, DateTime sourceLastWriteTime, Dictionary resources, string comment)
{
var logicalTargetPath = Path.Combine($"{language}.lproj", "Localizable.strings"); // this path is required by Xamarin
diff --git a/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/UnoPRIResourcesWriter.cs b/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/UnoPRIResourcesWriter.cs
new file mode 100644
index 000000000000..4e3a099c9bb2
--- /dev/null
+++ b/src/SourceGenerators/Uno.UI.Tasks/ResourcesGenerator/UnoPRIResourcesWriter.cs
@@ -0,0 +1,33 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Text;
+
+namespace Uno.UI.Tasks.ResourcesGenerator
+{
+ internal class UnoPRIResourcesWriter
+ {
+ internal static void Write(string language, Dictionary resources, string actualTargetPath, string comment)
+ {
+ using (var file = File.OpenWrite(actualTargetPath))
+ {
+ using (var writer = new BinaryWriter(file, Encoding.UTF8))
+ {
+ // "Magic" sequence to ensure we'll be reading a proper
+ // resource file at runtime
+ writer.Write(new byte[] { 0x75, 0x6E, 0x6F });
+ writer.Write(1); // version
+
+ writer.Write(language);
+ writer.Write(resources.Count);
+
+ foreach (var pair in resources)
+ {
+ writer.Write(pair.Key);
+ writer.Write(pair.Value);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/SourceGenerators/Uno.UI.Tasks/Uno.UI.Tasks.csproj b/src/SourceGenerators/Uno.UI.Tasks/Uno.UI.Tasks.csproj
index 9a01a6f4e39d..3b4a2428c7c0 100644
--- a/src/SourceGenerators/Uno.UI.Tasks/Uno.UI.Tasks.csproj
+++ b/src/SourceGenerators/Uno.UI.Tasks/Uno.UI.Tasks.csproj
@@ -58,7 +58,7 @@
1.24.0
- 1.26.0
+ 1.27.0
@@ -86,6 +86,7 @@
+
@@ -109,4 +110,4 @@ rem copy /Y "$(TargetDir)\*.*" "C:\s\temp\Universal Windows app samples\XAML use
-->
-
+
\ No newline at end of file
diff --git a/src/SourceGenerators/XamlGenerationTests.Core/XamlGenerationTests.Core.csproj b/src/SourceGenerators/XamlGenerationTests.Core/XamlGenerationTests.Core.csproj
index 4f9e947804af..3ab63c906f76 100644
--- a/src/SourceGenerators/XamlGenerationTests.Core/XamlGenerationTests.Core.csproj
+++ b/src/SourceGenerators/XamlGenerationTests.Core/XamlGenerationTests.Core.csproj
@@ -14,7 +14,7 @@
- 1.26.0
+ 1.27.0
Runtime
diff --git a/src/SourceGenerators/XamlGenerationTests/XamlGenerationTests.csproj b/src/SourceGenerators/XamlGenerationTests/XamlGenerationTests.csproj
index 739ad39cd3a7..d83d662b60fa 100644
--- a/src/SourceGenerators/XamlGenerationTests/XamlGenerationTests.csproj
+++ b/src/SourceGenerators/XamlGenerationTests/XamlGenerationTests.csproj
@@ -14,7 +14,7 @@
- 1.26.0
+ 1.27.0
Runtime
diff --git a/src/Uno.CrossTargetting.props b/src/Uno.CrossTargetting.props
index 6ede77d93726..4e06de3c68fc 100644
--- a/src/Uno.CrossTargetting.props
+++ b/src/Uno.CrossTargetting.props
@@ -106,7 +106,7 @@
-
+
diff --git a/src/Uno.Foundation/Uno.Foundation.csproj b/src/Uno.Foundation/Uno.Foundation.csproj
index c5dfdb6c4943..04de2f8ae632 100644
--- a/src/Uno.Foundation/Uno.Foundation.csproj
+++ b/src/Uno.Foundation/Uno.Foundation.csproj
@@ -10,14 +10,14 @@
$(NoWarn);NU1701
true
- true
+ false
true
- 1.26.0
+ 1.27.0
Runtime
diff --git a/src/Uno.UI.BindingHelper.Android/Uno.UI.BindingHelper.Android.csproj b/src/Uno.UI.BindingHelper.Android/Uno.UI.BindingHelper.Android.csproj
index bc56ee90e696..a23492d349c1 100644
--- a/src/Uno.UI.BindingHelper.Android/Uno.UI.BindingHelper.Android.csproj
+++ b/src/Uno.UI.BindingHelper.Android/Uno.UI.BindingHelper.Android.csproj
@@ -7,7 +7,7 @@
True
obj\$(TargetFramework)\Resources\Resource.Designer.cs
- true
+ false
true
diff --git a/src/Uno.UI.Maps/GoogleMapView.Android.cs b/src/Uno.UI.Maps/GoogleMapView.Android.cs
new file mode 100644
index 000000000000..3ac2649a3ac1
--- /dev/null
+++ b/src/Uno.UI.Maps/GoogleMapView.Android.cs
@@ -0,0 +1,83 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+using Android.App;
+using Android.Content;
+using Android.Gms.Maps;
+using Android.OS;
+using Android.Runtime;
+using Android.Util;
+using Android.Views;
+using Android.Widget;
+using Size = System.Drawing.Size;
+
+namespace Windows.UI.Xaml.Controls.Maps.Presenter
+{
+ public class GoogleMapView : MapView
+ {
+ private Size _lastAvailableSize;
+ private Size _lastLayoutedSize;
+
+ public event EventHandler TouchOccurred;
+
+ public GoogleMapView(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer)
+ {
+ }
+
+ public GoogleMapView(Android.Content.Context context, GoogleMapOptions options) : base(context, options)
+ {
+ }
+
+ public GoogleMapView(Android.Content.Context context, IAttributeSet attrs, int defStyle) : base(context, attrs, defStyle)
+ {
+ }
+
+ public GoogleMapView(Android.Content.Context context, IAttributeSet attrs) : base(context, attrs)
+ {
+ }
+
+ public GoogleMapView(Android.Content.Context context) : base(context)
+ {
+ }
+
+ protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
+ {
+ _lastAvailableSize = new Size(MeasureSpec.GetSize(widthMeasureSpec), MeasureSpec.GetSize(heightMeasureSpec));
+
+ base.OnMeasure(widthMeasureSpec, heightMeasureSpec);
+ }
+
+ protected override void OnLayout(bool changed, int left, int top, int right, int bottom)
+ {
+ _lastLayoutedSize = new Size(right - left, bottom - top);
+
+ // Measures the map to its layouted size so that it fills its bounds
+ OnMeasure(
+ MeasureSpec.MakeMeasureSpec(_lastLayoutedSize.Width, MeasureSpecMode.AtMost),
+ MeasureSpec.MakeMeasureSpec(_lastLayoutedSize.Height, MeasureSpecMode.AtMost)
+ );
+
+ base.OnLayout(changed, left, top, right, bottom);
+ }
+
+ public override void RequestLayout()
+ {
+ // MapView contains a TextView (Google Trademark text)
+ // that calls requestLayout continuously when GoogleMap.MyLocationEnabled is true.
+ // We don't want to propagate the request to the Map's parents when the
+ // size of the map is exactly the same as before.
+ if (_lastAvailableSize != _lastLayoutedSize)
+ {
+ base.RequestLayout();
+ }
+ }
+
+ public override bool DispatchTouchEvent(MotionEvent e)
+ {
+ TouchOccurred?.Invoke(this, e);
+ return base.DispatchTouchEvent(e);
+ }
+ }
+}
diff --git a/src/Uno.UI.Maps/MapHelper.iOS.cs b/src/Uno.UI.Maps/MapHelper.iOS.cs
new file mode 100644
index 000000000000..df2033be6fb8
--- /dev/null
+++ b/src/Uno.UI.Maps/MapHelper.iOS.cs
@@ -0,0 +1,101 @@
+using System;
+using CoreGraphics;
+using CoreLocation;
+using MapKit;
+using Windows.Devices.Geolocation;
+
+namespace Windows.UI.Xaml.Controls.Maps
+{
+ internal static class MapHelper
+ {
+ public const double MercatorRadius = MercatorOffset / Math.PI;
+
+ // Half of the earth circumference in pixels at zoom level 21.
+ public const double MercatorOffset = 268435456;
+
+ internal static MKCoordinateRegion CreateRegion(Geopoint centerCoordinate, double zoomLevel, CGSize size)
+ {
+ // convert center coordiate to pixel space
+ double centerPixelX = LongitudeToPixelSpaceX(centerCoordinate.Position.Longitude);
+ double centerPixelY = LatitudeToPixelSpaceY(centerCoordinate.Position.Latitude);
+
+ // determine the scale value from the zoom level
+ var zoomExponent = 21 - zoomLevel;
+ double zoomScale = Math.Pow(2, zoomExponent);
+
+ // scale the map’s size in pixel space
+ var mapSizeInPixels = size;
+ double scaledMapWidth = mapSizeInPixels.Width * zoomScale;
+ double scaledMapHeight = mapSizeInPixels.Height * zoomScale;
+
+ // figure out the position of the top-left pixel
+ double topLeftPixelX = centerPixelX - (scaledMapWidth / 2);
+ double topLeftPixelY = centerPixelY - (scaledMapHeight / 2);
+
+ // find delta between left and right longitudes
+ var minLng = PixelSpaceXToLongitude(topLeftPixelX);
+ var maxLng = PixelSpaceXToLongitude(topLeftPixelX + scaledMapWidth);
+ var longitudeDelta = maxLng - minLng;
+
+ // find delta between top and bottom latitudes
+ var minLat = PixelSpaceYToLatitude(topLeftPixelY);
+ var maxLat = PixelSpaceYToLatitude(topLeftPixelY + scaledMapHeight);
+ var latitudeDelta = -1 * (maxLat - minLat);
+
+ // create and return the lat/lng span
+ var span = new MKCoordinateSpan(latitudeDelta, longitudeDelta);
+ var region = new MKCoordinateRegion(centerCoordinate.ToLocation(), span);
+
+ return region;
+ }
+
+ internal static double PixelSpaceXToLongitude(double pixelX)
+ {
+ return ((Math.Round(pixelX) - MercatorOffset) / MercatorRadius) * 180.0 / Math.PI;
+ }
+
+ internal static double PixelSpaceYToLatitude(double pixelY)
+ {
+ return (Math.PI / 2.0 - 2.0 * Math.Atan(Math.Exp((Math.Round(pixelY) - MercatorOffset) / MercatorRadius))) * 180.0 / Math.PI;
+ }
+
+ internal static double LongitudeToPixelSpaceX(double longitude)
+ {
+ return Math.Round(MercatorOffset + MercatorRadius * longitude * Math.PI / 180.0);
+ }
+
+ internal static double LatitudeToPixelSpaceY(double latitude)
+ {
+ if (latitude == 90.0)
+ {
+ return 0;
+ }
+ else if (latitude == -90.0)
+ {
+ return MercatorOffset * 2;
+ }
+ else
+ {
+ return Math.Round(MercatorOffset - MercatorRadius * Math.Log((1 + Math.Sin(latitude * Math.PI / 180.0)) / (1 - Math.Sin(latitude * Math.PI / 180.0))) / 2.0);
+ }
+ }
+
+ }
+
+ internal static class GeopointExtensions
+ {
+ public static CLLocationCoordinate2D ToLocation(this Geopoint c)
+ {
+ return new CLLocationCoordinate2D(c.Position.Latitude, c.Position.Longitude);
+ }
+ public static CLLocationCoordinate2D ToLocation(this BasicGeoposition c)
+ {
+ return new CLLocationCoordinate2D(c.Latitude, c.Longitude);
+ }
+
+ public static Geopoint ToGeopoint(this CLLocationCoordinate2D l)
+ {
+ return new Geopoint(new BasicGeoposition { Latitude = l.Latitude, Longitude = l.Longitude });
+ }
+ }
+}
diff --git a/src/Uno.UI.Maps/MapPresenter.Android.cs b/src/Uno.UI.Maps/MapPresenter.Android.cs
new file mode 100644
index 000000000000..071ab6df43ef
--- /dev/null
+++ b/src/Uno.UI.Maps/MapPresenter.Android.cs
@@ -0,0 +1,266 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Drawing;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+using Android.App;
+using Android.Gms.Maps;
+using Android.Gms.Maps.Model;
+using Android.Views;
+using Uno.Extensions;
+using Uno.Logging;
+using Uno.UI;
+using Windows.Devices.Geolocation;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.Foundation.Metadata;
+using Windows.UI.Xaml.Markup;
+
+namespace Windows.UI.Xaml.Controls.Maps.Presenter
+{
+ public sealed partial class MapPresenter : Control
+ {
+ private Grid _mapGrid, _layerGrid;
+
+ private MapReadyCallback _callback;
+ private GoogleMapView _internalMapView;
+ private GoogleMap _map;
+ private Thickness _padding;
+ private MapLifeCycleCallBacks _callbacks;
+ private Android.App.Application _application;
+ private MapControl _owner;
+
+ public MapPresenter()
+ {
+ _internalMapView = new GoogleMapView(ContextHelper.Current, new GoogleMapOptions());
+
+ MapsInitializer.Initialize(ContextHelper.Current);
+
+ _internalMapView.GetMapAsync(_callback = new MapReadyCallback(OnMapReady));
+
+ _internalMapView.OnCreate(null); // This otherwise the map does not appear
+
+ }
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ _owner = TemplatedParent as MapControl;
+
+ _owner.RegisterPropertyChangedCallback(MapControl.CenterProperty, (s, e) => OnCenterChanged());
+ _owner.RegisterPropertyChangedCallback(MapControl.ZoomLevelProperty, (s, e) => OnCenterChanged());
+
+ _mapGrid = GetTemplateChild("MapGrid") as Grid;
+ _layerGrid = GetTemplateChild("LayerGrid") as Grid;
+
+ if (_mapGrid == null)
+ {
+ throw new InvalidOperationException("Unable to find [MapGrid] template part");
+ }
+
+ if (_layerGrid == null)
+ {
+ throw new InvalidOperationException("Unable to find [LayerGrid] template part");
+ }
+
+ _map.MyLocationEnabled = false;
+ _mapGrid.Children.Add(_internalMapView);
+ }
+
+ private void OnMapReady(GoogleMap map)
+ {
+ _map = map;
+
+ _padding = Thickness.Empty;
+
+ if (this.Log().IsEnabled(Microsoft.Extensions.Logging.LogLevel.Debug))
+ {
+ this.Log().Debug("GoogleMap instance is ready");
+ }
+ }
+
+ private void OnCenterChanged()
+ {
+ var builder = new CameraPosition.Builder(_map.CameraPosition)
+ .Target(_owner.Center.ToLatLng());
+
+ builder.Zoom((float)_owner.ZoomLevel);
+
+ var cameraUpdate = CameraUpdateFactory.NewCameraPosition(builder.Build());
+ _map.AnimateCamera(cameraUpdate);
+ }
+
+ protected override void OnLoaded()
+ {
+ _internalMapView.OnResume(); // This otherwise the map stay empty
+
+ HandleActivityLifeCycle();
+
+ _internalMapView.TouchOccurred += MapTouchOccurred;
+
+ base.OnLoaded();
+ }
+
+ protected override void OnUnloaded()
+ {
+ // These line is required for the control to
+ // stop actively monitoring the user's location.
+ _internalMapView.OnPause();
+
+ _application.UnregisterActivityLifecycleCallbacks(_callbacks);
+
+ if (_internalMapView != null)
+ {
+ _internalMapView.TouchOccurred -= MapTouchOccurred;
+ }
+
+ base.OnUnloaded();
+ }
+
+ private void MapTouchOccurred(object sender, MotionEvent e)
+ {
+
+ }
+
+ ///
+ /// Register to the LifeCycleCallbacks and properly call the OnResume and OnPause methods when needed.
+ /// This will release the GPS while the application is in the background
+ ///
+ private void HandleActivityLifeCycle()
+ {
+ _callbacks = new MapLifeCycleCallBacks(onPause: _internalMapView.OnPause, onResume: _internalMapView.OnResume);
+
+ _application = Context.ApplicationContext as Android.App.Application;
+ if (_application != null)
+ {
+ _application.RegisterActivityLifecycleCallbacks(_callbacks);
+ }
+ else
+ {
+ this.Log().Error("ApplicationContext is invalid, could not RegisterActivityLifecycleCallbacks to release GPS when application is paused.");
+ }
+ }
+
+ private class MapLifeCycleCallBacks : Java.Lang.Object, global::Android.App.Application.IActivityLifecycleCallbacks
+ {
+ private readonly Action _onPause;
+ private readonly Action _onResume;
+
+ public MapLifeCycleCallBacks(Action onPause, Action onResume)
+ {
+ _onResume = onResume;
+ _onPause = onPause;
+ }
+
+ public void OnActivityResumed(Activity activity)
+ {
+ _onResume();
+ }
+
+ public void OnActivityPaused(Activity activity)
+ {
+ _onPause();
+ }
+
+ public void OnActivityCreated(Activity activity, global::Android.OS.Bundle savedInstanceState)
+ {
+ }
+
+ public void OnActivityDestroyed(Activity activity)
+ {
+ }
+
+ public void OnActivitySaveInstanceState(Activity activity, global::Android.OS.Bundle outState)
+ {
+ }
+
+ public void OnActivityStarted(Activity activity)
+ {
+ }
+
+ public void OnActivityStopped(Activity activity)
+ {
+ }
+ }
+
+ private class MapReadyCallback : Java.Lang.Object, IOnMapReadyCallback
+ {
+ private readonly Action _mapAvailable;
+
+ public MapReadyCallback(Action mapAvailable)
+ {
+ _mapAvailable = mapAvailable;
+ }
+
+ public void OnMapReady(GoogleMap googleMap)
+ {
+ _mapAvailable(googleMap);
+ }
+ }
+
+ private class MapCancellableCallback : Java.Lang.Object, GoogleMap.ICancelableCallback
+ {
+ private readonly TaskCompletionSource _source = new TaskCompletionSource();
+ private readonly IDisposable _cancelSubscription;
+
+ public MapCancellableCallback(CancellationToken ct)
+ {
+ _cancelSubscription = ct.Register(() => _source.TrySetCanceled());
+ }
+
+ void GoogleMap.ICancelableCallback.OnCancel()
+ {
+ _source.TrySetCanceled();
+ }
+
+ void GoogleMap.ICancelableCallback.OnFinish()
+ {
+ _source.TrySetResult(true);
+ }
+
+ public TaskAwaiter GetAwaiter()
+ {
+ return _source.Task.GetAwaiter();
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ _cancelSubscription.Dispose();
+
+ base.Dispose(disposing);
+ }
+ }
+ }
+
+ static partial class CoordinateExtensions
+ {
+ public static LatLng ToLatLng(this Geopoint c)
+ {
+ return new LatLng(c.Position.Latitude, c.Position.Longitude);
+ }
+
+ public static Geoposition ToGeoposition(LatLng l)
+ {
+ return new Geoposition(
+ new Geocoordinate(
+ latitude: l.Latitude,
+ longitude: l.Longitude,
+ point: new Geopoint(
+ new BasicGeoposition {
+ Latitude = l.Latitude,
+ Longitude = l.Longitude
+ }
+ ),
+ accuracy: 0,
+ timestamp: DateTime.Now
+ )
+ );
+ }
+ }
+}
diff --git a/src/Uno.UI.Maps/MapPresenter.iOS.cs b/src/Uno.UI.Maps/MapPresenter.iOS.cs
new file mode 100644
index 000000000000..f2ca68f21b4b
--- /dev/null
+++ b/src/Uno.UI.Maps/MapPresenter.iOS.cs
@@ -0,0 +1,332 @@
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using CoreLocation;
+using Foundation;
+using MapKit;
+using UIKit;
+using Uno.Disposables;
+using Uno.Extensions;
+using Windows.Devices.Geolocation;
+using Windows.Foundation;
+using Windows.Foundation.Collections;
+using Windows.Foundation.Metadata;
+using Windows.UI.Xaml.Markup;
+using AnnotationAlias = MapKit.IMKAnnotation;
+using OverlayAlias = MapKit.IMKOverlay;
+
+namespace Windows.UI.Xaml.Controls.Maps.Presenters
+{
+ public sealed partial class MapPresenter : Control
+ {
+ private Grid _mapGrid, _layerGrid;
+
+ private MKMapView _internalMapView;
+ private readonly Dictionary _overlayRenderers = new Dictionary();
+ private readonly SerialDisposable _elementsDisposable = new SerialDisposable();
+ private readonly Dictionary _elements = new Dictionary();
+ private bool _changingCenter;
+
+ private MapControl _owner;
+
+ protected override void OnApplyTemplate()
+ {
+ base.OnApplyTemplate();
+
+ _owner = TemplatedParent as MapControl;
+
+ _owner.RegisterPropertyChangedCallback(MapControl.CenterProperty, OnCenterChanged);
+ _owner.RegisterPropertyChangedCallback(MapControl.ZoomLevelProperty, OnZoomLevelChanged);
+ (_owner.Children as DependencyObjectCollection).VectorChanged += OnChildrenCollectionChanged;
+
+ _mapGrid = GetTemplateChild("MapGrid") as Grid;
+ _layerGrid = GetTemplateChild("LayerGrid") as Grid;
+
+ if (_mapGrid == null)
+ {
+ throw new InvalidOperationException("Unable to find [MapGrid] template part");
+ }
+
+ if (_layerGrid == null)
+ {
+ throw new InvalidOperationException("Unable to find [LayerGrid] template part");
+ }
+
+ _internalMapView = new MKMapView();
+
+ _mapGrid.Children.Add(_internalMapView);
+ _internalMapView.ShowsUserLocation = false;
+
+ _internalMapView.RegionChanged += OnRegionChanged;
+
+ OnChildrenCollectionChanged(this, null);
+
+ SetUpOverlayRenderer();
+
+ _internalMapView.GetViewForAnnotation = OnGetViewForAnnotation;
+ }
+
+
+ private void OnRegionChanged(object sender, MKMapViewChangeEventArgs e)
+ {
+ if (!_changingCenter)
+ {
+ _changingCenter = true;
+
+ try
+ {
+ _owner.Center = _internalMapView.Region.Center.ToGeopoint();
+ UpdateZoomLevel();
+ }
+ finally
+ {
+ _changingCenter = false;
+ }
+ }
+ }
+
+ private double Log2(double value) => (Math.Log(value) / Math.Log(2));
+
+ private void UpdateZoomLevel()
+ {
+ _owner.ZoomLevel = 21 - Log2(_internalMapView.Region.Span.LongitudeDelta *
+ MapHelper.MercatorRadius * Math.PI / (180.0 * _internalMapView.Bounds.Size.Width));
+ }
+
+ private void OnCenterChanged(DependencyObject sender, DependencyProperty dp)
+ {
+ if (!_changingCenter)
+ {
+ _changingCenter = true;
+
+ try
+ {
+ if (_owner is IUnoMapControl unoMap)
+ {
+ unoMap.RaiseCenterChanged(this, null);
+ }
+
+ RefreshPosition();
+ }
+ finally
+ {
+ _changingCenter = false;
+ }
+ }
+ }
+
+ private void OnZoomLevelChanged(DependencyObject sender, DependencyProperty dp)
+ {
+ if (!_changingCenter)
+ {
+ _changingCenter = true;
+
+ try
+ {
+ if (_owner is IUnoMapControl unoMap)
+ {
+ unoMap.RaiseZoomLevelChanged(this, null);
+ }
+
+ RefreshPosition();
+ }
+ finally
+ {
+ _changingCenter = false;
+ }
+ }
+ }
+
+ private void OnChildrenCollectionChanged(object sender, IVectorChangedEventArgs e)
+ {
+ if (_internalMapView != null)
+ {
+ var mapItemsControl = _owner.Children.OfType();
+ var allItems = mapItemsControl.SelectMany(c => c.Items.OfType()).ToArray();
+
+ var removed = _elements.Keys.Except().ToArray();
+
+ foreach (var child in allItems)
+ {
+ MapControlAnnotation annotation;
+
+ if (!_elements.TryGetValue(child, out annotation))
+ {
+ _internalMapView.AddAnnotation(new MapControlAnnotation(child));
+ }
+ }
+
+ if (removed.Length != 0)
+ {
+ _internalMapView.RemoveAnnotations(removed.Select(d => _elements[d]).ToArray());
+ }
+ }
+ }
+
+ private void RefreshPosition()
+ {
+ var region = MapHelper.CreateRegion(_owner.Center, _owner.ZoomLevel, Bounds.Size);
+
+ _internalMapView.SetRegion(region, true);
+ }
+
+ private void OnMapElementsChanged(DependencyPropertyChangedEventArgs e)
+ {
+ UpdateMapPolygons();
+ }
+
+ private void OnMapElementsCollectionChanged(NotifyCollectionChangedEventArgs args)
+ {
+ UpdateMapPolygons();
+ }
+
+ private void SetUpOverlayRenderer()
+ {
+ // We do not support GetViewForOverlay.
+ _internalMapView.OverlayRenderer = OnGetOverlayRenderer;
+ }
+
+ private MKOverlayRenderer OnGetOverlayRenderer(MKMapView mapView, IMKOverlay overlay)
+ {
+ return _overlayRenderers.GetValueOrDefault(overlay);
+ }
+
+ private MKAnnotationView OnGetViewForAnnotation(MKMapView mapView, AnnotationAlias annotation)
+ {
+ if (annotation is MapControlAnnotation mapAnnotation)
+ {
+ var annotationView = mapView.DequeueReusableAnnotation(MapControlAnnotation.AnnotationId);
+
+ if (annotationView == null)
+ {
+ annotationView = new MKAnnotationView(mapAnnotation, MapControlAnnotation.AnnotationId);
+ annotationView.Add(mapAnnotation.Content);
+ }
+
+ if (mapAnnotation.Content is FrameworkElement element)
+ {
+ element.Measure(new Size((float)Bounds.Width, (float)Bounds.Height));
+ var size = element.DesiredSize;
+ element.Arrange(new Rect(0, 0, size.Width, size.Height));
+
+ // Set the frame size, or the pin will not be selectable.
+ annotationView.Frame = new CoreGraphics.CGRect(0, 0, size.Width, size.Height);
+ mapAnnotation.Content.Frame = new CoreGraphics.CGRect(0, 0, size.Width, size.Height);
+ }
+
+ return annotationView;
+ }
+
+ return null;
+ }
+
+ private void UpdateMapPolygons()
+ {
+ if (_internalMapView != null)
+ {
+ _internalMapView.RemoveOverlays(_overlayRenderers.Keys.ToArray());
+
+ _overlayRenderers.Values.DisposeAll();
+ _overlayRenderers.Clear();
+
+ _elementsDisposable.Disposable = new CompositeDisposable(
+ _owner.MapElements
+ .Select(e => e.RegisterDisposablePropertyChangedCallback((wr, p, args) => UpdateMapPolygons()))
+ );
+
+ foreach (var polygon in _owner.MapElements)
+ {
+ if (polygon is MapPolyline)
+ {
+ AddPolyline(polygon as MapPolyline);
+ }
+ }
+ }
+ }
+
+ private void AddPolyline(MapPolyline polyline)
+ {
+ var coordinates = polyline
+ .Path
+ .Positions
+ .Select(point => point.ToLocation())
+ .ToArray();
+
+ var strokeColor = (UIColor)polyline.StrokeColor;
+
+ if (strokeColor == null)
+ {
+ throw new KeyNotFoundException("Stroke color key not found in resources.");
+ }
+
+ var overlay = MKPolyline.FromCoordinates(coordinates);
+ var renderer = new MKPolylineRenderer(overlay)
+ {
+ StrokeColor = strokeColor,
+ LineWidth = (nfloat)polyline.StrokeThickness
+ };
+
+ if (polyline.StrokeThickness != 0 && polyline.StrokeDashed)
+ {
+ renderer.LineDashPattern = new NSNumber[]
+ {
+ polyline.StrokeThickness,
+ 4
+ };
+ }
+
+ _overlayRenderers.Add(overlay, renderer);
+ _internalMapView.AddOverlay(overlay);
+ }
+
+ private class MapControlAnnotation : MKAnnotation
+ {
+ public const string AnnotationId = "Uno.Pushpin";
+ private CLLocationCoordinate2D _coordinate;
+
+ public MapControlAnnotation(UIElement child)
+ {
+ Content = child;
+
+ Content.RegisterDisposablePropertyChangedCallback(MapControl.LocationProperty, OnCoordinateChanged);
+ }
+
+ private void OnCoordinateChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs args)
+ {
+ WillChangeValue("coordinate");
+ _coordinate = GetAttachedLocation();
+ DidChangeValue("coordinate");
+ }
+
+ public override void SetCoordinate(CLLocationCoordinate2D value)
+ {
+ _coordinate = value;
+ MapControl.SetLocation(Content, _coordinate.ToGeopoint());
+ }
+
+ public override string Title
+ {
+ get
+ {
+ return "Test";
+ }
+ }
+
+ public override CLLocationCoordinate2D Coordinate
+ {
+ get { return _coordinate; }
+ }
+
+ private CLLocationCoordinate2D GetAttachedLocation()
+ {
+ return MapControl.GetLocation(Content)?.ToLocation() ?? new CLLocationCoordinate2D();
+ }
+
+ public UIElement Content { get; set; }
+ }
+ }
+}
diff --git a/src/Uno.UI.Maps/Uno.UI.Maps.csproj b/src/Uno.UI.Maps/Uno.UI.Maps.csproj
new file mode 100644
index 000000000000..72ef2d073d04
--- /dev/null
+++ b/src/Uno.UI.Maps/Uno.UI.Maps.csproj
@@ -0,0 +1,80 @@
+
+
+ MonoAndroid80;xamarinios10
+ MonoAndroid80;xamarinios10
+
+
+
+ $(NoWarn);NU1701
+
+ false
+ true
+
+
+
+
+
+
+
+ false
+
+
+
+
+
+ 1.27.0
+
+
+ 1.24.0
+
+
+ 1.24.0
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ..\SourceGenerators\Uno.UI.SourceGenerators\bin\$(Configuration)
+ true
+
+
+
+
+
+
+
+ <_OverrideTargetFramework>$(TargetFramework)
+ <_TargetNugetFolder>$(USERPROFILE)\.nuget\packages\Uno.UI\$(UnoNugetOverrideVersion)\lib\$(_OverrideTargetFramework)
+
+
+ <_OutputFiles Include="$(TargetDir)*.*" />
+
+
+
+
+
+
+
+
+
+
+
+ MSBuild:Compile
+
+
+
+
+
+ MSBuild:Compile
+
+
+
+
diff --git a/src/Uno.UI.Maps/themes/Generic.xaml b/src/Uno.UI.Maps/themes/Generic.xaml
new file mode 100644
index 000000000000..5cc90c63aebe
--- /dev/null
+++ b/src/Uno.UI.Maps/themes/Generic.xaml
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
diff --git a/src/Uno.UI.Tests.Performance/Uno.UI.Tests.Performance.csproj b/src/Uno.UI.Tests.Performance/Uno.UI.Tests.Performance.csproj
index 52fd9e612f7e..27ec32edc1cf 100644
--- a/src/Uno.UI.Tests.Performance/Uno.UI.Tests.Performance.csproj
+++ b/src/Uno.UI.Tests.Performance/Uno.UI.Tests.Performance.csproj
@@ -45,7 +45,7 @@
1.3.1
- 1.26.0
+ 1.27.0
1.24.0
diff --git a/src/Uno.UI.Tests/BinderTests/Given_Binder.cs b/src/Uno.UI.Tests/BinderTests/Given_Binder.cs
index e457834cfa20..b391a47773c6 100644
--- a/src/Uno.UI.Tests/BinderTests/Given_Binder.cs
+++ b/src/Uno.UI.Tests/BinderTests/Given_Binder.cs
@@ -20,6 +20,7 @@
using Windows.UI.Xaml.Media;
using Uno.Conversion;
using Microsoft.Extensions.Logging;
+using Windows.UI.Xaml.Controls;
namespace Uno.UI.Tests.BinderTests
{
@@ -640,6 +641,39 @@ public void When_PrivateProperty_And_Binding()
Assert.IsNull(SUT.Tag);
}
+ [TestMethod]
+ //TODO: Amend this test when Uno correctly supports reentrantly modifying DPs.
+ public void When_Reentrant_Set()
+ {
+ var sut = new TextBox();
+
+ sut.TextChanged += (o, e) =>
+ {
+ sut.Text = "Bob";
+ };
+
+ sut.Text = "Alice";
+
+ Assert.AreEqual("Alice", sut.Text);
+ }
+
+ [TestMethod]
+ //TODO: Amend this test when Uno correctly supports reentrantly modifying DPs.
+ public void When_Reentrant_Set_With_Additional_Set()
+ {
+ var sut = new TextBox();
+
+ sut.TextChanged += (o, e) =>
+ {
+ sut.SetValue(Grid.RowProperty, 0);
+ sut.Text = "Bob";
+ };
+
+ sut.Text = "Alice";
+
+ Assert.AreEqual("Alice", sut.Text);
+ }
+
public partial class BaseTarget : DependencyObject
{
private List
- 1.26.0
+ 1.27.0
1.24.0
@@ -73,6 +73,9 @@
Resources\%(RecursiveDir)%(FileName)%(Extension)
+
+
+
@@ -121,6 +124,12 @@
+
+
+
+
+
+
diff --git a/src/Uno.UI.Tests/XamlReaderTests/When_Binding_Converter.xamltest b/src/Uno.UI.Tests/XamlReaderTests/When_Binding_Converter.xamltest
index 37700398a44e..305b04aa6fec 100644
--- a/src/Uno.UI.Tests/XamlReaderTests/When_Binding_Converter.xamltest
+++ b/src/Uno.UI.Tests/XamlReaderTests/When_Binding_Converter.xamltest
@@ -1,6 +1,6 @@
diff --git a/src/Uno.UI.Toolkit/MenuFlyoutItemExtensions.cs b/src/Uno.UI.Toolkit/MenuFlyoutItemExtensions.cs
new file mode 100644
index 000000000000..7bac7407f376
--- /dev/null
+++ b/src/Uno.UI.Toolkit/MenuFlyoutItemExtensions.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.UI.Xaml;
+using Windows.UI.Xaml.Controls;
+
+namespace Uno.UI.Toolkit
+{
+#if __IOS__
+ [Foundation.PreserveAttribute(AllMembers = true)]
+#elif __ANDROID__
+ [Android.Runtime.PreserveAttribute(AllMembers = true)]
+#endif
+ public static class MenuFlyoutItemExtensions
+ {
+ #region IsDestructive
+
+ public static DependencyProperty IsDestructiveProperty { get; } =
+ DependencyProperty.RegisterAttached(
+ "IsDestructive",
+ typeof(bool),
+ typeof(MenuFlyoutItemExtensions),
+ new PropertyMetadata(false)
+ );
+
+ public static void SetIsDestructive(this MenuFlyoutItem menuFlyoutItem, bool isDestructive)
+ {
+ menuFlyoutItem.SetValue(IsDestructiveProperty, isDestructive);
+ }
+
+ public static bool GetIsDestructive(this MenuFlyoutItem menuFlyoutItem)
+ {
+ return (bool)menuFlyoutItem.GetValue(IsDestructiveProperty);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/Uno.UI.Toolkit/UICommandExtensions.cs b/src/Uno.UI.Toolkit/UICommandExtensions.cs
new file mode 100644
index 000000000000..3e6c29f03b77
--- /dev/null
+++ b/src/Uno.UI.Toolkit/UICommandExtensions.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Windows.UI.Popups;
+
+namespace Uno.UI.Toolkit
+{
+ public static class UICommandExtensions
+ {
+ public static void SetDestructive(this UICommand command, bool isDestructive)
+ {
+#if __IOS__
+ if (command == null)
+ {
+ return;
+ }
+
+ command.IsDestructive = isDestructive;
+#endif
+ }
+ }
+}
diff --git a/src/Uno.UI.Toolkit/Uno.UI.Toolkit.csproj b/src/Uno.UI.Toolkit/Uno.UI.Toolkit.csproj
index 0ef0a5b6773e..f9566a0f2446 100644
--- a/src/Uno.UI.Toolkit/Uno.UI.Toolkit.csproj
+++ b/src/Uno.UI.Toolkit/Uno.UI.Toolkit.csproj
@@ -10,7 +10,7 @@
$(AssemblyName) ($(TargetFramework))
en-US
- true
+ false
true
@@ -19,7 +19,7 @@
- 1.26.0
+ 1.27.0
1.24.0
@@ -131,7 +131,7 @@
-
-
+
+
diff --git a/src/Uno.UI.Wasm.Shell/App.xaml.cs b/src/Uno.UI.Wasm.Shell/App.xaml.cs
deleted file mode 100644
index d03c572621f5..000000000000
--- a/src/Uno.UI.Wasm.Shell/App.xaml.cs
+++ /dev/null
@@ -1,110 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Runtime.InteropServices.WindowsRuntime;
-using Windows.ApplicationModel;
-using Windows.ApplicationModel.Activation;
-using Windows.Foundation;
-using Windows.Foundation.Collections;
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Controls;
-using Windows.UI.Xaml.Controls.Primitives;
-using Windows.UI.Xaml.Data;
-using Windows.UI.Xaml.Input;
-using Windows.UI.Xaml.Media;
-using Windows.UI.Xaml.Navigation;
-using Uno.Extensions;
-using Uno.Logging;
-
-namespace Uno.UI.Wasm.App
-{
- ///
- /// Provides application-specific behavior to supplement the default Application class.
- ///
- sealed partial class App : Application
- {
- ///
- /// Initializes the singleton application object. This is the first line of authored code
- /// executed, and as such is the logical equivalent of main() or WinMain().
- ///
- public App() : base()
- {
- this.InitializeComponent();
- this.Suspending += OnSuspending;
- }
-
- ///
- /// Invoked when the application is launched normally by the end user. Other entry points
- /// will be used such as when the application is launched to open a specific file.
- ///
- /// Details about the launch request and process.
- protected override async void OnLaunched(LaunchActivatedEventArgs e)
- {
-#if DEBUG
- if (System.Diagnostics.Debugger.IsAttached)
- {
- // this.DebugSettings.EnableFrameRateCounter = true;
- }
-#endif
-
- Frame rootFrame = Windows.UI.Xaml.Window.Current.Content as Frame;
-
- // Do not repeat app initialization when the Window already has content,
- // just ensure that the window is active
- if (rootFrame == null)
- {
- // Create a Frame to act as the navigation context and navigate to the first page
- rootFrame = new Frame();
-
- rootFrame.NavigationFailed += OnNavigationFailed;
-
- if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
- {
- //TODO: Load state from previously suspended application
- }
-
- // Place the frame in the current Window
- Windows.UI.Xaml.Window.Current.Content = rootFrame;
-
- }
-
- if (e.PrelaunchActivated == false)
- {
- if (rootFrame.Content == null)
- {
- // When the navigation stack isn't restored navigate to the first page,
- // configuring the new page by passing required information as a navigation
- // parameter
- rootFrame.Navigate(typeof(MainPage), e.Arguments);
- }
- // Ensure the current window is active
- Windows.UI.Xaml.Window.Current.Activate();
- }
- }
-
- ///
- /// Invoked when Navigation to a certain page fails
- ///
- /// The Frame which failed navigation
- /// Details about the navigation failure
- void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
- {
- throw new Exception("Failed to load Page " + e.SourcePageType.FullName, e.Exception);
- }
-
- ///
- /// Invoked when application execution is being suspended. Application state is saved
- /// without knowing whether the application will be terminated or resumed with the contents
- /// of memory still intact.
- ///
- /// The source of the suspend request.
- /// Details about the suspend request.
- private void OnSuspending(object sender, SuspendingEventArgs e)
- {
- var deferral = e.SuspendingOperation.GetDeferral();
- //TODO: Save application state and stop any background activity
- deferral.Complete();
- }
- }
-}
diff --git a/src/Uno.UI.Wasm.Shell/MainPage.xaml b/src/Uno.UI.Wasm.Shell/MainPage.xaml
deleted file mode 100644
index a7572b9eb630..000000000000
--- a/src/Uno.UI.Wasm.Shell/MainPage.xaml
+++ /dev/null
@@ -1,129 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
-
-
-
-
-
-
- 1234
-
-
-
- 90-x
-
-
- Spanless Text
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/Uno.UI.Wasm.Shell/MainPage.xaml.cs b/src/Uno.UI.Wasm.Shell/MainPage.xaml.cs
deleted file mode 100644
index c95c01e868e8..000000000000
--- a/src/Uno.UI.Wasm.Shell/MainPage.xaml.cs
+++ /dev/null
@@ -1,106 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Runtime.InteropServices.WindowsRuntime;
-using Windows.Foundation;
-using Windows.Foundation.Collections;
-using Windows.UI.Popups;
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Controls;
-using Windows.UI.Xaml.Controls.Primitives;
-using Windows.UI.Xaml.Data;
-using Windows.UI.Xaml.Input;
-using Windows.UI.Xaml.Media;
-using Windows.UI.Xaml.Media.Animation;
-using Windows.UI.Xaml.Navigation;
-
-// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409
-
-namespace Uno.UI.Wasm.App
-{
- ///
- /// An empty page that can be used on its own or navigated to within a Frame.
- ///
- public sealed partial class MainPage : Page
- {
- public MainPage()
- {
- this.InitializeComponent();
-
- DataContext = new MainPageViewModel();
- }
-
- private void Button_Click(object sender, RoutedEventArgs e)
- {
- new MessageDialog("Button clicked!").ShowAsync();
- }
-
- private Storyboard _storyboard;
- private bool _storyboardIsRunning;
- private void StartAnimation(object sender, TappedRoutedEventArgs e)
- {
- if (_storyboard == null)
- {
- var animation = new DoubleAnimation
- {
- From = 0,
- To = 360,
- RepeatBehavior = RepeatBehavior.Forever,
- AutoReverse = true,
- Duration = new Duration(TimeSpan.FromSeconds(10)),
- EnableDependentAnimation = true
- };
- Storyboard.SetTarget(animation, _transform);
- Storyboard.SetTargetProperty(animation, nameof(_transform.Angle));
-
- _storyboard = new Storyboard
- {
- Children = { animation }
- };
-
- _storyboardIsRunning = true;
- _storyboard.Begin();
- }
- else if (_storyboardIsRunning)
- {
- _storyboardIsRunning = false;
- _storyboard.Pause();
- }
- else
- {
- _storyboardIsRunning = true;
- _storyboard.Resume();
- }
- }
- }
-
- [Bindable]
- public class MainPageViewModel
- {
- public MainPageViewModel()
- {
- Items = Enumerable.Range(0, 3).Select(i =>
- new Item
- {
- Title = $"Title {i}",
- Subtitle = $"Subtitle {i}",
- Image = "http://lorempixel.com/100/100/",
- }
- )
- .ToArray();
- }
-
- public Item[] Items { get; set; }
- }
-
- [Bindable]
- public class Item
- {
- public string Subtitle { get; set; }
- public string Title { get; set; }
- public string Image { get; set; }
-
- public override string ToString() => Title;
- }
-}
diff --git a/src/Uno.UI.Wasm.Shell/Program.cs b/src/Uno.UI.Wasm.Shell/Program.cs
deleted file mode 100644
index 90791438ab09..000000000000
--- a/src/Uno.UI.Wasm.Shell/Program.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using System;
-using System.IO;
-using Windows.ApplicationModel.Activation;
-using Windows.UI.Xaml;
-using Windows.UI.Xaml.Controls;
-using Windows.UI.Xaml.Shapes;
-using Microsoft.Extensions.Logging;
-using Uno.Extensions;
-using Uno.Foundation;
-using Uno.Logging;
-using Windows.UI.Popups;
-using System.Reflection;
-
-namespace Uno.UI.Wasm.Shell
-{
- class Program
- {
- private static App.App _app;
-
- static void Main(string[] args)
- {
- ConfigureFilters(LogExtensionPoint.AmbientLoggerFactory);
-
- Application.Start(_ => new App.App());
- }
-
- static void ConfigureFilters(ILoggerFactory factory)
- {
- factory
- .WithFilter(new FilterLoggerSettings
- {
- { "Uno", LogLevel.Warning },
- { "Windows", LogLevel.Warning },
- { "SampleControl.Presentation", LogLevel.Debug },
-
- // Generic Xaml events
- // { "Windows.UI.Xaml", LogLevel.Debug },
-
- // { "Uno.UI.Controls.AsyncValuePresenter", LogLevel.Debug },
- // { "Uno.UI.Controls.IfDataContext", LogLevel.Debug },
-
- // Layouter specific messages
- // { "Windows.UI.Xaml.Controls", LogLevel.Debug },
- //{ "Windows.UI.Xaml.Controls.Layouter", LogLevel.Debug },
- //{ "Windows.UI.Xaml.Controls.Panel", LogLevel.Debug },
-
- // Binding related messages
- // { "Windows.UI.Xaml.Data", LogLevel.Debug },
- // { "Windows.UI.Xaml.Data", LogLevel.Debug },
-
- // Binder memory references tracking
- // { "ReferenceHolder", LogLevel.Debug },
- }
- )
- .AddConsole(LogLevel.Debug);
- }
- }
-}
diff --git a/src/Uno.UI.Wasm.Shell/Properties/launchSettings.json b/src/Uno.UI.Wasm.Shell/Properties/launchSettings.json
deleted file mode 100644
index 36edc0a41b42..000000000000
--- a/src/Uno.UI.Wasm.Shell/Properties/launchSettings.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "profiles": {
- "Uno.UI.Wasm.Shell": {
- "commandName": "Executable",
- "executablePath": "C:\\Windows\\System32\\whoami.exe"
- }
- }
-}
\ No newline at end of file
diff --git a/src/Uno.UI.Wasm.Shell/Runtime.cs b/src/Uno.UI.Wasm.Shell/Runtime.cs
deleted file mode 100644
index b6d3a6120e3f..000000000000
--- a/src/Uno.UI.Wasm.Shell/Runtime.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace WebAssembly
-{
- internal sealed class Runtime
- {
- [System.Runtime.CompilerServices.MethodImplAttribute((System.Runtime.CompilerServices.MethodImplOptions)4096)]
- static extern string InvokeJS(string str, out int exceptional_result);
-
- public static string InvokeJS(string str)
- {
- return InvokeJS(str, out var _);
- }
- }
-}
diff --git a/src/Uno.UI.Wasm.Shell/Uno.UI.Wasm.Shell.csproj b/src/Uno.UI.Wasm.Shell/Uno.UI.Wasm.Shell.csproj
deleted file mode 100644
index 66f99ff1c098..000000000000
--- a/src/Uno.UI.Wasm.Shell/Uno.UI.Wasm.Shell.csproj
+++ /dev/null
@@ -1,55 +0,0 @@
-
-
-
- Exe
- netstandard2.0
- $(DefineConstants);__WASM__
- true
-
-
-
-
-
-
-
-
- 1.26.0
- NU1701
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- ..\SourceGenerators\Uno.UI.SourceGenerators\bin\$(Configuration)
-
-
-
- $(DefineConstants);TRACE;DEBUG
-
-
-
-
-
diff --git a/src/Uno.UI.Wasm/Uno.UI.Wasm.csproj b/src/Uno.UI.Wasm/Uno.UI.Wasm.csproj
index 55b1c10a3810..854e4d6325b0 100644
--- a/src/Uno.UI.Wasm/Uno.UI.Wasm.csproj
+++ b/src/Uno.UI.Wasm/Uno.UI.Wasm.csproj
@@ -6,7 +6,7 @@
$(NoWarn);NU1701
- true
+ false
true
@@ -21,7 +21,7 @@
-
+
@@ -54,8 +54,8 @@
-
-
+
+
diff --git a/src/Uno.UI.Wasm/WasmScripts/Uno.UI.d.ts b/src/Uno.UI.Wasm/WasmScripts/Uno.UI.d.ts
index bfbaf37f22bb..25690eadc5bd 100644
--- a/src/Uno.UI.Wasm/WasmScripts/Uno.UI.d.ts
+++ b/src/Uno.UI.Wasm/WasmScripts/Uno.UI.d.ts
@@ -50,6 +50,13 @@ declare namespace Uno.UI {
private containerElementId;
private loadingElementId;
static current: WindowManager;
+ private static _isHosted;
+ /**
+ * Defines if the WindowManager is running in hosted mode, and should skip the
+ * initialization of WebAssembly, use this mode in conjuction with the Uno.UI.WpfHost
+ * to improve debuggability.
+ */
+ static readonly isHosted: boolean;
private static readonly unoRootClassName;
private static readonly unoUnarrangedClassName;
/**
@@ -57,7 +64,7 @@ declare namespace Uno.UI {
* @param containerElementId The ID of the container element for the Xaml UI
* @param loadingElementId The ID of the loading element to remove once ready
*/
- static init(containerElementId?: string, loadingElementId?: string): string;
+ static init(localStoragePath: string, isHosted: boolean, containerElementId?: string, loadingElementId?: string): string;
private containerElement;
private rootContent;
private allActiveElementsById;
@@ -65,6 +72,19 @@ declare namespace Uno.UI {
private static resizeMethod;
private static dispatchEventMethod;
private constructor();
+ /**
+ * Setup the storage persistence
+ *
+ * */
+ static setupStorage(localStoragePath: string): void;
+ /**
+ * Determine if IndexDB is available, some browsers and modes disable it.
+ * */
+ static isIndexDBAvailable(): boolean;
+ /**
+ * Synchronize the IDBFS memory cache back to IndexDB
+ * */
+ static synchronizeFileSystem(): void;
/**
* Creates the UWP-compatible splash screen
*
@@ -246,22 +266,16 @@ declare module Uno.UI.Interop {
}
}
declare module Uno.UI.Interop {
- interface IWebAssemblyApp {
- main_module: Interop.IMonoAssemblyHandle;
- main_class: Interop.IMonoClassHandle;
+ interface IUnoDispatch {
+ resize(size: string): void;
+ dispatch(htmlIdStr: string, eventNameStr: string, eventPayloadStr: string): string;
+ managedObjectDispatch(handle: string, method: string, parameters: string): string;
}
}
declare module Uno.UI.Interop {
- interface IWebAssemblyModule {
- getValue(ptr: number, format: string): number;
- HEAPU8: Uint8Array;
- HEAP8: Int8Array;
- HEAP16: Int16Array;
- HEAPU16: Uint16Array;
- HEAP32: Int32Array;
- HEAPU32: Uint32Array;
- HEAPF32: Float32Array;
- HEAPF64: Float64Array;
+ interface IWebAssemblyApp {
+ main_module: Interop.IMonoAssemblyHandle;
+ main_class: Interop.IMonoClassHandle;
}
}
declare namespace Uno.Foundation.Interop {
@@ -285,4 +299,4 @@ declare namespace Uno.UI.Interop {
declare const MonoRuntime: Uno.UI.Interop.IMonoRuntime;
declare const WebAssemblyApp: Uno.UI.Interop.IWebAssemblyApp;
declare const UnoAppManifest: Uno.UI.IAppManifest;
-declare const Module: Uno.UI.Interop.IWebAssemblyModule;
+declare const UnoDispatch: Uno.UI.Interop.IUnoDispatch;
diff --git a/src/Uno.UI.Wasm/WasmScripts/Uno.UI.js b/src/Uno.UI.Wasm/WasmScripts/Uno.UI.js
index d51c971be066..7c44e7e14f0b 100644
--- a/src/Uno.UI.Wasm/WasmScripts/Uno.UI.js
+++ b/src/Uno.UI.Wasm/WasmScripts/Uno.UI.js
@@ -143,21 +143,79 @@ var Uno;
this.allActiveElementsById = {};
this.initDom();
}
+ /**
+ * Defines if the WindowManager is running in hosted mode, and should skip the
+ * initialization of WebAssembly, use this mode in conjuction with the Uno.UI.WpfHost
+ * to improve debuggability.
+ */
+ static get isHosted() {
+ return WindowManager._isHosted;
+ }
/**
* Initialize the WindowManager
* @param containerElementId The ID of the container element for the Xaml UI
* @param loadingElementId The ID of the loading element to remove once ready
*/
- static init(containerElementId = "uno-body", loadingElementId = "uno-loading") {
+ static init(localStoragePath, isHosted, containerElementId = "uno-body", loadingElementId = "uno-loading") {
if (WindowManager.assembly) {
throw "Already initialized";
}
+ WindowManager._isHosted = isHosted;
WindowManager.initMethods();
UI.HtmlDom.initPolyfills();
+ WindowManager.setupStorage(localStoragePath);
this.current = new WindowManager(containerElementId, loadingElementId);
this.current.init();
return "ok";
}
+ /**
+ * Setup the storage persistence
+ *
+ * */
+ static setupStorage(localStoragePath) {
+ if (WindowManager.isHosted) {
+ console.debug("Hosted Mode: skipping IndexDB initialization");
+ }
+ else {
+ if (WindowManager.isIndexDBAvailable()) {
+ FS.mkdir(localStoragePath);
+ FS.mount(IDBFS, {}, localStoragePath);
+ FS.syncfs(true, err => {
+ if (err) {
+ console.error(`Error synchronizing filsystem from IndexDB: ${err}`);
+ }
+ });
+ window.addEventListener("beforeunload", () => WindowManager.synchronizeFileSystem());
+ setInterval(() => WindowManager.synchronizeFileSystem(), 10000);
+ }
+ else {
+ console.warn("IndexedDB is not available (private mode?), changed will not be persisted.");
+ }
+ }
+ }
+ /**
+ * Determine if IndexDB is available, some browsers and modes disable it.
+ * */
+ static isIndexDBAvailable() {
+ try {
+ // IndexedDB may not be available in private mode
+ window.indexedDB;
+ return true;
+ }
+ catch (err) {
+ return false;
+ }
+ }
+ /**
+ * Synchronize the IDBFS memory cache back to IndexDB
+ * */
+ static synchronizeFileSystem() {
+ FS.syncfs(err => {
+ if (err) {
+ console.error(`Error synchronizing filsystem from IndexDB: ${err}`);
+ }
+ });
+ }
/**
* Creates the UWP-compatible splash screen
*
@@ -640,27 +698,32 @@ var Uno;
}
}
static initMethods() {
- if (!WindowManager.assembly) {
- WindowManager.assembly = MonoRuntime.assembly_load("Uno.UI");
- if (!WindowManager.assembly) {
- throw `Unable to find assembly Uno.UI`;
- }
+ if (WindowManager.isHosted) {
+ console.debug("Hosted Mode: Skipping MonoRuntime initialization ");
}
- if (!WindowManager.resizeMethod) {
- const type = MonoRuntime.find_class(WindowManager.assembly, "Windows.UI.Xaml", "Window");
- if (!type) {
- throw `Unable to find type Windows.UI.Xaml.Window`;
+ else {
+ if (!WindowManager.assembly) {
+ WindowManager.assembly = MonoRuntime.assembly_load("Uno.UI");
+ if (!WindowManager.assembly) {
+ throw `Unable to find assembly Uno.UI`;
+ }
}
- WindowManager.resizeMethod = MonoRuntime.find_method(type, "Resize", -1);
if (!WindowManager.resizeMethod) {
- throw `Unable to find Windows.UI.Xaml.Window.Resize method`;
+ const type = MonoRuntime.find_class(WindowManager.assembly, "Windows.UI.Xaml", "Window");
+ if (!type) {
+ throw `Unable to find type Windows.UI.Xaml.Window`;
+ }
+ WindowManager.resizeMethod = MonoRuntime.find_method(type, "Resize", -1);
+ if (!WindowManager.resizeMethod) {
+ throw `Unable to find Windows.UI.Xaml.Window.Resize method`;
+ }
}
- }
- if (!WindowManager.dispatchEventMethod) {
- const type = MonoRuntime.find_class(WindowManager.assembly, "Windows.UI.Xaml", "UIElement");
- WindowManager.dispatchEventMethod = MonoRuntime.find_method(type, "DispatchEvent", -1);
if (!WindowManager.dispatchEventMethod) {
- throw `Unable to find Windows.UI.Xaml.UIElement.DispatchEvent method`;
+ const type = MonoRuntime.find_class(WindowManager.assembly, "Windows.UI.Xaml", "UIElement");
+ WindowManager.dispatchEventMethod = MonoRuntime.find_method(type, "DispatchEvent", -1);
+ if (!WindowManager.dispatchEventMethod) {
+ throw `Unable to find Windows.UI.Xaml.UIElement.DispatchEvent method`;
+ }
}
}
}
@@ -686,8 +749,13 @@ var Uno;
body.style.backgroundColor = '#fff';
}
resize() {
- const sizeStr = this.getMonoString(`${window.innerWidth};${window.innerHeight}`);
- MonoRuntime.call_method(WindowManager.resizeMethod, null, [sizeStr]);
+ if (WindowManager.isHosted) {
+ UnoDispatch.resize(`${window.innerWidth};${window.innerHeight}`);
+ }
+ else {
+ const sizeStr = this.getMonoString(`${window.innerWidth};${window.innerHeight}`);
+ MonoRuntime.call_method(WindowManager.resizeMethod, null, [sizeStr]);
+ }
}
dispatchEvent(element, eventName, eventPayload = null) {
const htmlId = element.getAttribute("XamlHandle");
@@ -695,13 +763,22 @@ var Uno;
if (!htmlId) {
throw `No attribute XamlHandle on element ${element}. Can't raise event.`;
}
- const htmlIdStr = this.getMonoString(htmlId);
- const eventNameStr = this.getMonoString(eventName);
- const eventPayloadStr = this.getMonoString(eventPayload);
- var handledHandle = MonoRuntime.call_method(WindowManager.dispatchEventMethod, null, [htmlIdStr, eventNameStr, eventPayloadStr]);
- var handledStr = this.fromMonoString(handledHandle);
- var handled = handledStr == "True";
- return handled;
+ if (WindowManager.isHosted) {
+ // Dispatch to the C# backed UnoDispatch class. Events propagated
+ // this way always succeed because synchronous calls are not possible
+ // between the host and the browser, unlike wasm.
+ UnoDispatch.dispatch(htmlId, eventName, eventPayload);
+ return true;
+ }
+ else {
+ const htmlIdStr = this.getMonoString(htmlId);
+ const eventNameStr = this.getMonoString(eventName);
+ const eventPayloadStr = this.getMonoString(eventPayload);
+ var handledHandle = MonoRuntime.call_method(WindowManager.dispatchEventMethod, null, [htmlIdStr, eventNameStr, eventPayloadStr]);
+ var handledStr = this.fromMonoString(handledHandle);
+ var handled = handledStr == "True";
+ return handled;
+ }
}
getMonoString(str) {
return str ? MonoRuntime.mono_string(str) : null;
@@ -717,10 +794,23 @@ var Uno;
return rootElement === element || rootElement.contains(element);
}
}
+ WindowManager._isHosted = false;
WindowManager.unoRootClassName = "uno-root-element";
WindowManager.unoUnarrangedClassName = "uno-unarranged";
UI.WindowManager = WindowManager;
- document.addEventListener("DOMContentLoaded", () => WindowManager.setupSplashScreen());
+ if (typeof define === 'function') {
+ define(['AppManifest'], () => {
+ if (document.readyState === "loading") {
+ document.addEventListener("DOMContentLoaded", () => WindowManager.setupSplashScreen());
+ }
+ else {
+ WindowManager.setupSplashScreen();
+ }
+ });
+ }
+ else {
+ throw `The Uno.Wasm.Boostrap is not up to date, please upgrade to a later version`;
+ }
})(UI = Uno.UI || (Uno.UI = {}));
})(Uno || (Uno = {}));
// Ensure the "Uno" namespace is availablle globally
@@ -733,17 +823,22 @@ var Uno;
(function (Interop) {
class ManagedObject {
static init() {
- if (!ManagedObject.assembly) {
- ManagedObject.assembly = MonoRuntime.assembly_load("Uno.Foundation");
+ if (Uno.UI.WindowManager.isHosted) {
+ console.debug("Hosted Mode: skipping IndexDB initialization");
+ }
+ else {
if (!ManagedObject.assembly) {
- throw "Unable to find assembly Uno.Foundation";
+ ManagedObject.assembly = MonoRuntime.assembly_load("Uno.Foundation");
+ if (!ManagedObject.assembly) {
+ throw "Unable to find assembly Uno.Foundation";
+ }
}
- }
- if (!ManagedObject.dispatchMethod) {
- const type = MonoRuntime.find_class(ManagedObject.assembly, "Uno.Foundation.Interop", "JSObject");
- ManagedObject.dispatchMethod = MonoRuntime.find_method(type, "Dispatch", -1);
if (!ManagedObject.dispatchMethod) {
- throw "Unable to find Uno.Foundation.Interop.JSObject.Dispatch method";
+ const type = MonoRuntime.find_class(ManagedObject.assembly, "Uno.Foundation.Interop", "JSObject");
+ ManagedObject.dispatchMethod = MonoRuntime.find_method(type, "Dispatch", -1);
+ if (!ManagedObject.dispatchMethod) {
+ throw "Unable to find Uno.Foundation.Interop.JSObject.Dispatch method";
+ }
}
}
}
@@ -751,13 +846,18 @@ var Uno;
if (!ManagedObject.dispatchMethod) {
ManagedObject.init();
}
- const handleStr = handle ? MonoRuntime.mono_string(handle) : null;
- const methodStr = method ? MonoRuntime.mono_string(method) : null;
- const parametersStr = parameters ? MonoRuntime.mono_string(parameters) : null;
- if (methodStr == null) {
- throw "Cannot dispatch to unknown method";
+ if (Uno.UI.WindowManager.isHosted) {
+ const handleStr = handle ? MonoRuntime.mono_string(handle) : null;
+ const methodStr = method ? MonoRuntime.mono_string(method) : null;
+ const parametersStr = parameters ? MonoRuntime.mono_string(parameters) : null;
+ if (methodStr == null) {
+ throw "Cannot dispatch to unknown method";
+ }
+ MonoRuntime.call_method(ManagedObject.dispatchMethod, null, [handleStr, methodStr, parametersStr]);
+ }
+ else {
+ UnoDispatch.managedObjectDispatch(handle, method, parameters);
}
- MonoRuntime.call_method(ManagedObject.dispatchMethod, null, [handleStr, methodStr, parametersStr]);
}
}
Interop.ManagedObject = ManagedObject;
diff --git a/src/Uno.UI.Wasm/WasmScripts/jquery-pep.js b/src/Uno.UI.Wasm/WasmScripts/jquery-pep.js
new file mode 100644
index 000000000000..9263d13c54bd
--- /dev/null
+++ b/src/Uno.UI.Wasm/WasmScripts/jquery-pep.js
@@ -0,0 +1,1474 @@
+/*!
+ * PEP v0.4.3 | https://github.com/jquery/PEP
+ * Copyright jQuery Foundation and other contributors | http://jquery.org/license
+ */
+
+(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ (global.PointerEventsPolyfill = factory());
+}(this, function () {
+ 'use strict';
+
+ /**
+ * This is the constructor for new PointerEvents.
+ *
+ * New Pointer Events must be given a type, and an optional dictionary of
+ * initialization properties.
+ *
+ * Due to certain platform requirements, events returned from the constructor
+ * identify as MouseEvents.
+ *
+ * @constructor
+ * @param {String} inType The type of the event to create.
+ * @param {Object} [inDict] An optional dictionary of initial event properties.
+ * @return {Event} A new PointerEvent of type `inType`, initialized with properties from `inDict`.
+ */
+ var MOUSE_PROPS = [
+ 'bubbles',
+ 'cancelable',
+ 'view',
+ 'detail',
+ 'screenX',
+ 'screenY',
+ 'clientX',
+ 'clientY',
+ 'ctrlKey',
+ 'altKey',
+ 'shiftKey',
+ 'metaKey',
+ 'button',
+ 'relatedTarget',
+ 'pageX',
+ 'pageY'
+ ];
+
+ var MOUSE_DEFAULTS = [
+ false,
+ false,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ false,
+ false,
+ false,
+ false,
+ 0,
+ null,
+ 0,
+ 0
+ ];
+
+ function PointerEvent(inType, inDict) {
+ inDict = inDict || Object.create(null);
+
+ var e = document.createEvent('Event');
+ e.initEvent(inType, inDict.bubbles || false, inDict.cancelable || false);
+
+ // define inherited MouseEvent properties
+ // skip bubbles and cancelable since they're set above in initEvent()
+ for (var i = 2, p; i < MOUSE_PROPS.length; i++) {
+ p = MOUSE_PROPS[i];
+ e[p] = inDict[p] || MOUSE_DEFAULTS[i];
+ }
+ e.buttons = inDict.buttons || 0;
+
+ // Spec requires that pointers without pressure specified use 0.5 for down
+ // state and 0 for up state.
+ var pressure = 0;
+
+ if (inDict.pressure && e.buttons) {
+ pressure = inDict.pressure;
+ } else {
+ pressure = e.buttons ? 0.5 : 0;
+ }
+
+ // add x/y properties aliased to clientX/Y
+ e.x = e.clientX;
+ e.y = e.clientY;
+
+ // define the properties of the PointerEvent interface
+ e.pointerId = inDict.pointerId || 0;
+ e.width = inDict.width || 0;
+ e.height = inDict.height || 0;
+ e.pressure = pressure;
+ e.tiltX = inDict.tiltX || 0;
+ e.tiltY = inDict.tiltY || 0;
+ e.twist = inDict.twist || 0;
+ e.tangentialPressure = inDict.tangentialPressure || 0;
+ e.pointerType = inDict.pointerType || '';
+ e.hwTimestamp = inDict.hwTimestamp || 0;
+ e.isPrimary = inDict.isPrimary || false;
+ return e;
+ }
+
+ /**
+ * This module implements a map of pointer states
+ */
+ var USE_MAP = window.Map && window.Map.prototype.forEach;
+ var PointerMap = USE_MAP ? Map : SparseArrayMap;
+
+ function SparseArrayMap() {
+ this.array = [];
+ this.size = 0;
+ }
+
+ SparseArrayMap.prototype = {
+ set: function (k, v) {
+ if (v === undefined) {
+ return this.delete(k);
+ }
+ if (!this.has(k)) {
+ this.size++;
+ }
+ this.array[k] = v;
+ },
+ has: function (k) {
+ return this.array[k] !== undefined;
+ },
+ delete: function (k) {
+ if (this.has(k)) {
+ delete this.array[k];
+ this.size--;
+ }
+ },
+ get: function (k) {
+ return this.array[k];
+ },
+ clear: function () {
+ this.array.length = 0;
+ this.size = 0;
+ },
+
+ // return value, key, map
+ forEach: function (callback, thisArg) {
+ return this.array.forEach(function (v, k) {
+ callback.call(thisArg, v, k, this);
+ }, this);
+ }
+ };
+
+ var CLONE_PROPS = [
+
+ // MouseEvent
+ 'bubbles',
+ 'cancelable',
+ 'view',
+ 'detail',
+ 'screenX',
+ 'screenY',
+ 'clientX',
+ 'clientY',
+ 'ctrlKey',
+ 'altKey',
+ 'shiftKey',
+ 'metaKey',
+ 'button',
+ 'relatedTarget',
+
+ // DOM Level 3
+ 'buttons',
+
+ // PointerEvent
+ 'pointerId',
+ 'width',
+ 'height',
+ 'pressure',
+ 'tiltX',
+ 'tiltY',
+ 'pointerType',
+ 'hwTimestamp',
+ 'isPrimary',
+
+ // event instance
+ 'type',
+ 'target',
+ 'currentTarget',
+ 'which',
+ 'pageX',
+ 'pageY',
+ 'timeStamp'
+ ];
+
+ var CLONE_DEFAULTS = [
+
+ // MouseEvent
+ false,
+ false,
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0,
+ false,
+ false,
+ false,
+ false,
+ 0,
+ null,
+
+ // DOM Level 3
+ 0,
+
+ // PointerEvent
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ '',
+ 0,
+ false,
+
+ // event instance
+ '',
+ null,
+ null,
+ 0,
+ 0,
+ 0,
+ 0
+ ];
+
+ var BOUNDARY_EVENTS = {
+ 'pointerover': 1,
+ 'pointerout': 1,
+ 'pointerenter': 1,
+ 'pointerleave': 1
+ };
+
+ var HAS_SVG_INSTANCE = (typeof SVGElementInstance !== 'undefined');
+
+ /**
+ * This module is for normalizing events. Mouse and Touch events will be
+ * collected here, and fire PointerEvents that have the same semantics, no
+ * matter the source.
+ * Events fired:
+ * - pointerdown: a pointing is added
+ * - pointerup: a pointer is removed
+ * - pointermove: a pointer is moved
+ * - pointerover: a pointer crosses into an element
+ * - pointerout: a pointer leaves an element
+ * - pointercancel: a pointer will no longer generate events
+ */
+ var dispatcher = {
+ pointermap: new PointerMap(),
+ eventMap: Object.create(null),
+ captureInfo: Object.create(null),
+
+ // Scope objects for native events.
+ // This exists for ease of testing.
+ eventSources: Object.create(null),
+ eventSourceList: [],
+ /**
+ * Add a new event source that will generate pointer events.
+ *
+ * `inSource` must contain an array of event names named `events`, and
+ * functions with the names specified in the `events` array.
+ * @param {string} name A name for the event source
+ * @param {Object} source A new source of platform events.
+ */
+ registerSource: function (name, source) {
+ var s = source;
+ var newEvents = s.events;
+ if (newEvents) {
+ newEvents.forEach(function (e) {
+ if (s[e]) {
+ this.eventMap[e] = s[e].bind(s);
+ }
+ }, this);
+ this.eventSources[name] = s;
+ this.eventSourceList.push(s);
+ }
+ },
+ register: function (element) {
+ var l = this.eventSourceList.length;
+ for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {
+
+ // call eventsource register
+ es.register.call(es, element);
+ }
+ },
+ unregister: function (element) {
+ var l = this.eventSourceList.length;
+ for (var i = 0, es; (i < l) && (es = this.eventSourceList[i]); i++) {
+
+ // call eventsource register
+ es.unregister.call(es, element);
+ }
+ },
+ contains: /*scope.external.contains || */function (container, contained) {
+ try {
+ return container.contains(contained);
+ } catch (ex) {
+
+ // most likely: https://bugzilla.mozilla.org/show_bug.cgi?id=208427
+ return false;
+ }
+ },
+
+ // EVENTS
+ down: function (inEvent) {
+ inEvent.bubbles = true;
+ this.fireEvent('pointerdown', inEvent);
+ },
+ move: function (inEvent) {
+ inEvent.bubbles = true;
+ this.fireEvent('pointermove', inEvent);
+ },
+ up: function (inEvent) {
+ inEvent.bubbles = true;
+ this.fireEvent('pointerup', inEvent);
+ },
+ enter: function (inEvent) {
+ inEvent.bubbles = false;
+ this.fireEvent('pointerenter', inEvent);
+ },
+ leave: function (inEvent) {
+ inEvent.bubbles = false;
+ this.fireEvent('pointerleave', inEvent);
+ },
+ over: function (inEvent) {
+ inEvent.bubbles = true;
+ this.fireEvent('pointerover', inEvent);
+ },
+ out: function (inEvent) {
+ inEvent.bubbles = true;
+ this.fireEvent('pointerout', inEvent);
+ },
+ cancel: function (inEvent) {
+ inEvent.bubbles = true;
+ this.fireEvent('pointercancel', inEvent);
+ },
+ leaveOut: function (event) {
+ this.out(event);
+ this.propagate(event, this.leave, false);
+ },
+ enterOver: function (event) {
+ this.over(event);
+ this.propagate(event, this.enter, true);
+ },
+
+ // LISTENER LOGIC
+ eventHandler: function (inEvent) {
+
+ // This is used to prevent multiple dispatch of pointerevents from
+ // platform events. This can happen when two elements in different scopes
+ // are set up to create pointer events, which is relevant to Shadow DOM.
+ if (inEvent._handledByPE) {
+ return;
+ }
+ var type = inEvent.type;
+ var fn = this.eventMap && this.eventMap[type];
+ if (fn) {
+ fn(inEvent);
+ }
+ inEvent._handledByPE = true;
+ },
+
+ // set up event listeners
+ listen: function (target, events) {
+ events.forEach(function (e) {
+ this.addEvent(target, e);
+ }, this);
+ },
+
+ // remove event listeners
+ unlisten: function (target, events) {
+ events.forEach(function (e) {
+ this.removeEvent(target, e);
+ }, this);
+ },
+ addEvent: /*scope.external.addEvent || */function (target, eventName) {
+ target.addEventListener(eventName, this.boundHandler);
+ },
+ removeEvent: /*scope.external.removeEvent || */function (target, eventName) {
+ target.removeEventListener(eventName, this.boundHandler);
+ },
+
+ // EVENT CREATION AND TRACKING
+ /**
+ * Creates a new Event of type `inType`, based on the information in
+ * `inEvent`.
+ *
+ * @param {string} inType A string representing the type of event to create
+ * @param {Event} inEvent A platform event with a target
+ * @return {Event} A PointerEvent of type `inType`
+ */
+ makeEvent: function (inType, inEvent) {
+
+ // relatedTarget must be null if pointer is captured
+ if (this.captureInfo[inEvent.pointerId]) {
+ inEvent.relatedTarget = null;
+ }
+ var e = new PointerEvent(inType, inEvent);
+ if (inEvent.preventDefault) {
+ e.preventDefault = inEvent.preventDefault;
+ }
+ e._target = e._target || inEvent.target;
+ return e;
+ },
+
+ // make and dispatch an event in one call
+ fireEvent: function (inType, inEvent) {
+ var e = this.makeEvent(inType, inEvent);
+ return this.dispatchEvent(e);
+ },
+ /**
+ * Returns a snapshot of inEvent, with writable properties.
+ *
+ * @param {Event} inEvent An event that contains properties to copy.
+ * @return {Object} An object containing shallow copies of `inEvent`'s
+ * properties.
+ */
+ cloneEvent: function (inEvent) {
+ var eventCopy = Object.create(null);
+ var p;
+ for (var i = 0; i < CLONE_PROPS.length; i++) {
+ p = CLONE_PROPS[i];
+ eventCopy[p] = inEvent[p] || CLONE_DEFAULTS[i];
+
+ // Work around SVGInstanceElement shadow tree
+ // Return the