Browse Source

Merge pull request #45 from ryanlntn/react-native-windows

React Native Windows Support
Gaëtan Renaudeau 7 years ago
parent
commit
e406cb8d25

+ 12
- 8
README.md View File

@@ -66,17 +66,18 @@ takeSnapshot(viewRef, { path: PictureDir+"/foo.png" })
66 66
 
67 67
 Model tested: iPhone 6 (iOS), Nexus 5 (Android).
68 68
 
69
-| System             | iOS                | Android           |
70
-|--------------------|--------------------|-------------------|
71
-| View,Text,Image,.. | YES                | YES               |
72
-| WebView            | YES                | YES<sup>1</sup>   |
73
-| gl-react v2        | YES                | NO<sup>2</sup>    |
74
-| react-native-video | NO                 | NO                |
75
-| react-native-maps  | YES                | [NO](https://github.com/gre/react-native-view-shot/issues/36) |
69
+| System             | iOS                | Android           | Windows           |
70
+|--------------------|--------------------|-------------------|-------------------|
71
+| View,Text,Image,.. | YES                | YES               | YES               |                    
72
+| WebView            | YES                | YES<sup>1</sup>   | YES               |
73
+| gl-react v2        | YES                | NO<sup>2</sup>    | NO<sup>3</sup>    |
74
+| react-native-video | NO                 | NO                | NO
75
+| react-native-maps  | YES                | [NO](https://github.com/gre/react-native-view-shot/issues/36) | NO<sup>3</sup>
76 76
 
77 77
 >
78 78
 1. Only supported by wrapping a `<View collapsable={false}>` parent and snapshotting it.
79 79
 2. It returns an empty image (not a failure Promise).
80
+3. Component itself lacks platform support.
80 81
 
81 82
 ## Caveats
82 83
 
@@ -128,7 +129,10 @@ react-native link react-native-view-shot
128 129
 
129 130
 #### Windows
130 131
 
131
-Stay tuned, https://github.com/gre/react-native-view-shot/pull/45 will be merged soon!
132
+1. In Visual Studio, in the solution explorer, right click on your solution then select `Add` ➜ `ExisitingProject`
133
+2. Go to `node_modules` ➜ `react-native-view-shot` and add `RNViewShot.csproj` (UWP) or optionally `RNViewShot.Net46.csproj` (WPF)
134
+3. In Visual Studio, in the solution explorer, right click on your Application project then select `Add` ➜ `Reference`
135
+4. Under the projects tab select `RNViewShot` (UWP) or `RNViewShot.Net46` (WPF)
132 136
 
133 137
 ## Thanks
134 138
 

+ 9
- 0
jsconfig.json View File

@@ -0,0 +1,9 @@
1
+{
2
+    "compilerOptions": {
3
+        "allowJs": true,
4
+        "allowSyntheticDefaultImports": true
5
+    },
6
+    "exclude": [
7
+        "node_modules"
8
+    ]
9
+}

+ 281
- 0
windows/.gitignore View File

@@ -0,0 +1,281 @@
1
+## Ignore Visual Studio temporary files, build results, and
2
+## files generated by popular Visual Studio add-ons.
3
+##
4
+## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5
+
6
+# User-specific files
7
+*.suo
8
+*.user
9
+*.userosscache
10
+*.sln.docstates
11
+
12
+# User-specific files (MonoDevelop/Xamarin Studio)
13
+*.userprefs
14
+
15
+# Build results
16
+[Dd]ebug/
17
+[Dd]ebugPublic/
18
+[Rr]elease/
19
+[Rr]eleases/
20
+x64/
21
+x86/
22
+bld/
23
+[Bb]in/
24
+[Oo]bj/
25
+[Ll]og/
26
+
27
+# Visual Studio 2015 cache/options directory
28
+.vs/
29
+# Uncomment if you have tasks that create the project's static files in wwwroot
30
+#wwwroot/
31
+
32
+# MSTest test Results
33
+[Tt]est[Rr]esult*/
34
+[Bb]uild[Ll]og.*
35
+
36
+# NUNIT
37
+*.VisualState.xml
38
+TestResult.xml
39
+
40
+# Build Results of an ATL Project
41
+[Dd]ebugPS/
42
+[Rr]eleasePS/
43
+dlldata.c
44
+
45
+# .NET Core
46
+project.lock.json
47
+project.fragment.lock.json
48
+artifacts/
49
+**/Properties/launchSettings.json
50
+
51
+*_i.c
52
+*_p.c
53
+*_i.h
54
+*.ilk
55
+*.meta
56
+*.obj
57
+*.pch
58
+*.pdb
59
+*.pgc
60
+*.pgd
61
+*.rsp
62
+*.sbr
63
+*.tlb
64
+*.tli
65
+*.tlh
66
+*.tmp
67
+*.tmp_proj
68
+*.log
69
+*.vspscc
70
+*.vssscc
71
+.builds
72
+*.pidb
73
+*.svclog
74
+*.scc
75
+
76
+# Chutzpah Test files
77
+_Chutzpah*
78
+
79
+# Visual C++ cache files
80
+ipch/
81
+*.aps
82
+*.ncb
83
+*.opendb
84
+*.opensdf
85
+*.sdf
86
+*.cachefile
87
+*.VC.db
88
+*.VC.VC.opendb
89
+
90
+# Visual Studio profiler
91
+*.psess
92
+*.vsp
93
+*.vspx
94
+*.sap
95
+
96
+# TFS 2012 Local Workspace
97
+$tf/
98
+
99
+# Guidance Automation Toolkit
100
+*.gpState
101
+
102
+# ReSharper is a .NET coding add-in
103
+_ReSharper*/
104
+*.[Rr]e[Ss]harper
105
+*.DotSettings.user
106
+
107
+# JustCode is a .NET coding add-in
108
+.JustCode
109
+
110
+# TeamCity is a build add-in
111
+_TeamCity*
112
+
113
+# DotCover is a Code Coverage Tool
114
+*.dotCover
115
+
116
+# Visual Studio code coverage results
117
+*.coverage
118
+*.coveragexml
119
+
120
+# NCrunch
121
+_NCrunch_*
122
+.*crunch*.local.xml
123
+nCrunchTemp_*
124
+
125
+# MightyMoose
126
+*.mm.*
127
+AutoTest.Net/
128
+
129
+# Web workbench (sass)
130
+.sass-cache/
131
+
132
+# Installshield output folder
133
+[Ee]xpress/
134
+
135
+# DocProject is a documentation generator add-in
136
+DocProject/buildhelp/
137
+DocProject/Help/*.HxT
138
+DocProject/Help/*.HxC
139
+DocProject/Help/*.hhc
140
+DocProject/Help/*.hhk
141
+DocProject/Help/*.hhp
142
+DocProject/Help/Html2
143
+DocProject/Help/html
144
+
145
+# Click-Once directory
146
+publish/
147
+
148
+# Publish Web Output
149
+*.[Pp]ublish.xml
150
+*.azurePubxml
151
+# TODO: Comment the next line if you want to checkin your web deploy settings
152
+# but database connection strings (with potential passwords) will be unencrypted
153
+*.pubxml
154
+*.publishproj
155
+
156
+# Microsoft Azure Web App publish settings. Comment the next line if you want to
157
+# checkin your Azure Web App publish settings, but sensitive information contained
158
+# in these scripts will be unencrypted
159
+PublishScripts/
160
+
161
+# NuGet Packages
162
+*.nupkg
163
+# The packages folder can be ignored because of Package Restore
164
+**/packages/*
165
+# except build/, which is used as an MSBuild target.
166
+!**/packages/build/
167
+# Uncomment if necessary however generally it will be regenerated when needed
168
+#!**/packages/repositories.config
169
+# NuGet v3's project.json files produces more ignorable files
170
+*.nuget.props
171
+*.nuget.targets
172
+
173
+# Microsoft Azure Build Output
174
+csx/
175
+*.build.csdef
176
+
177
+# Microsoft Azure Emulator
178
+ecf/
179
+rcf/
180
+
181
+# Windows Store app package directories and files
182
+AppPackages/
183
+BundleArtifacts/
184
+Package.StoreAssociation.xml
185
+_pkginfo.txt
186
+
187
+# Visual Studio cache files
188
+# files ending in .cache can be ignored
189
+*.[Cc]ache
190
+# but keep track of directories ending in .cache
191
+!*.[Cc]ache/
192
+
193
+# Others
194
+ClientBin/
195
+~$*
196
+*~
197
+*.dbmdl
198
+*.dbproj.schemaview
199
+*.jfm
200
+*.pfx
201
+*.publishsettings
202
+orleans.codegen.cs
203
+
204
+# Since there are multiple workflows, uncomment next line to ignore bower_components
205
+# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
206
+#bower_components/
207
+
208
+# RIA/Silverlight projects
209
+Generated_Code/
210
+
211
+# Backup & report files from converting an old project file
212
+# to a newer Visual Studio version. Backup files are not needed,
213
+# because we have git ;-)
214
+_UpgradeReport_Files/
215
+Backup*/
216
+UpgradeLog*.XML
217
+UpgradeLog*.htm
218
+
219
+# SQL Server files
220
+*.mdf
221
+*.ldf
222
+
223
+# Business Intelligence projects
224
+*.rdl.data
225
+*.bim.layout
226
+*.bim_*.settings
227
+
228
+# Microsoft Fakes
229
+FakesAssemblies/
230
+
231
+# GhostDoc plugin setting file
232
+*.GhostDoc.xml
233
+
234
+# Node.js Tools for Visual Studio
235
+.ntvs_analysis.dat
236
+node_modules/
237
+
238
+# Typescript v1 declaration files
239
+typings/
240
+
241
+# Visual Studio 6 build log
242
+*.plg
243
+
244
+# Visual Studio 6 workspace options file
245
+*.opt
246
+
247
+# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
248
+*.vbw
249
+
250
+# Visual Studio LightSwitch build output
251
+**/*.HTMLClient/GeneratedArtifacts
252
+**/*.DesktopClient/GeneratedArtifacts
253
+**/*.DesktopClient/ModelManifest.xml
254
+**/*.Server/GeneratedArtifacts
255
+**/*.Server/ModelManifest.xml
256
+_Pvt_Extensions
257
+
258
+# Paket dependency manager
259
+.paket/paket.exe
260
+paket-files/
261
+
262
+# FAKE - F# Make
263
+.fake/
264
+
265
+# JetBrains Rider
266
+.idea/
267
+*.sln.iml
268
+
269
+# CodeRush
270
+.cr/
271
+
272
+# Python Tools for Visual Studio (PTVS)
273
+__pycache__/
274
+*.pyc
275
+
276
+# Cake - Uncomment if you are using it
277
+# tools/**
278
+# !tools/packages.config
279
+
280
+# Telerik's JustMock configuration file
281
+*.jmconfig

+ 36
- 0
windows/RNViewShot.Net46/Properties/AssemblyInfo.cs View File

@@ -0,0 +1,36 @@
1
+using System.Reflection;
2
+using System.Runtime.CompilerServices;
3
+using System.Runtime.InteropServices;
4
+
5
+// General Information about an assembly is controlled through the following 
6
+// set of attributes. Change these attribute values to modify the information
7
+// associated with an assembly.
8
+[assembly: AssemblyTitle("RNViewShot.Net46")]
9
+[assembly: AssemblyDescription("")]
10
+[assembly: AssemblyConfiguration("")]
11
+[assembly: AssemblyCompany("")]
12
+[assembly: AssemblyProduct("RNViewShot.Net46")]
13
+[assembly: AssemblyCopyright("Copyright ©  2017")]
14
+[assembly: AssemblyTrademark("")]
15
+[assembly: AssemblyCulture("")]
16
+
17
+// Setting ComVisible to false makes the types in this assembly not visible 
18
+// to COM components.  If you need to access a type in this assembly from 
19
+// COM, set the ComVisible attribute to true on that type.
20
+[assembly: ComVisible(false)]
21
+
22
+// The following GUID is for the ID of the typelib if this project is exposed to COM
23
+[assembly: Guid("1dd45d00-ddf4-43b4-ab28-f98e6dc325b5")]
24
+
25
+// Version information for an assembly consists of the following four values:
26
+//
27
+//      Major Version
28
+//      Minor Version 
29
+//      Build Number
30
+//      Revision
31
+//
32
+// You can specify all the values or you can default the Build and Revision Numbers 
33
+// by using the '*' as shown below:
34
+// [assembly: AssemblyVersion("1.0.*")]
35
+[assembly: AssemblyVersion("1.0.0.0")]
36
+[assembly: AssemblyFileVersion("1.0.0.0")]

+ 97
- 0
windows/RNViewShot.Net46/RNViewShot.Net46.csproj View File

@@ -0,0 +1,97 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4
+  <PropertyGroup>
5
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7
+    <ProjectGuid>{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}</ProjectGuid>
8
+    <OutputType>Library</OutputType>
9
+    <AppDesignerFolder>Properties</AppDesignerFolder>
10
+    <RootNamespace>RNViewShot.Net46</RootNamespace>
11
+    <AssemblyName>RNViewShot.Net46</AssemblyName>
12
+    <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
13
+    <FileAlignment>512</FileAlignment>
14
+  </PropertyGroup>
15
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
16
+    <DebugSymbols>true</DebugSymbols>
17
+    <OutputPath>bin\x86\Debug\</OutputPath>
18
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
19
+    <DebugType>full</DebugType>
20
+    <PlatformTarget>x86</PlatformTarget>
21
+    <ErrorReport>prompt</ErrorReport>
22
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
23
+  </PropertyGroup>
24
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
25
+    <OutputPath>bin\x86\Release\</OutputPath>
26
+    <DefineConstants>TRACE</DefineConstants>
27
+    <Optimize>true</Optimize>
28
+    <DebugType>pdbonly</DebugType>
29
+    <PlatformTarget>x86</PlatformTarget>
30
+    <ErrorReport>prompt</ErrorReport>
31
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
32
+  </PropertyGroup>
33
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
34
+    <DebugSymbols>true</DebugSymbols>
35
+    <OutputPath>bin\x64\Debug\</OutputPath>
36
+    <DefineConstants>DEBUG;TRACE</DefineConstants>
37
+    <DebugType>full</DebugType>
38
+    <PlatformTarget>x64</PlatformTarget>
39
+    <ErrorReport>prompt</ErrorReport>
40
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
41
+  </PropertyGroup>
42
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
43
+    <OutputPath>bin\x64\Release\</OutputPath>
44
+    <DefineConstants>TRACE</DefineConstants>
45
+    <Optimize>true</Optimize>
46
+    <DebugType>pdbonly</DebugType>
47
+    <PlatformTarget>x64</PlatformTarget>
48
+    <ErrorReport>prompt</ErrorReport>
49
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
50
+  </PropertyGroup>
51
+  <ItemGroup>
52
+    <Reference Include="Newtonsoft.Json, Version=9.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
53
+      <HintPath>..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
54
+      <Private>True</Private>
55
+    </Reference>
56
+    <Reference Include="PresentationCore" />
57
+    <Reference Include="PresentationFramework" />
58
+    <Reference Include="System" />
59
+    <Reference Include="System.Core" />
60
+    <Reference Include="System.Drawing" />
61
+    <Reference Include="System.Windows" />
62
+    <Reference Include="System.Xml.Linq" />
63
+    <Reference Include="System.Data.DataSetExtensions" />
64
+    <Reference Include="Microsoft.CSharp" />
65
+    <Reference Include="System.Data" />
66
+    <Reference Include="System.Net.Http" />
67
+    <Reference Include="System.Xml" />
68
+    <Reference Include="Windows.Foundation.UniversalApiContract">
69
+      <HintPath>..\..\..\..\..\..\..\..\..\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\2.0.0.0\Windows.Foundation.UniversalApiContract.winmd</HintPath>
70
+    </Reference>
71
+    <Reference Include="WindowsBase" />
72
+  </ItemGroup>
73
+  <ItemGroup>
74
+    <Compile Include="Properties\AssemblyInfo.cs" />
75
+    <Compile Include="RNViewShotModule.cs" />
76
+    <Compile Include="RNViewShotPackage.cs" />
77
+    <Compile Include="ViewShot.cs" />
78
+  </ItemGroup>
79
+  <ItemGroup>
80
+    <ProjectReference Include="..\..\node_modules\react-native-windows\ReactWindows\ReactNative.Net46\ReactNative.Net46.csproj">
81
+      <Project>{22cbff9c-fe36-43e8-a246-266c7635e662}</Project>
82
+      <Name>ReactNative.Net46</Name>
83
+    </ProjectReference>
84
+  </ItemGroup>
85
+  <ItemGroup>
86
+    <None Include="app.config" />
87
+    <None Include="packages.config" />
88
+  </ItemGroup>
89
+  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
90
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it. 
91
+       Other similar extension points exist, see Microsoft.Common.targets.
92
+  <Target Name="BeforeBuild">
93
+  </Target>
94
+  <Target Name="AfterBuild">
95
+  </Target>
96
+  -->
97
+</Project>

+ 58
- 0
windows/RNViewShot.Net46/RNViewShotModule.cs View File

@@ -0,0 +1,58 @@
1
+using Newtonsoft.Json.Linq;
2
+using ReactNative.Bridge;
3
+using ReactNative.UIManager;
4
+using System;
5
+using System.IO;
6
+using System.Collections.Generic;
7
+
8
+namespace RNViewShot
9
+{
10
+    /// <summary>
11
+    /// A module that allows JS to share data.
12
+    /// </summary>
13
+    class RNViewShotModule : ReactContextNativeModuleBase
14
+    {
15
+        private const string ErrorUnableToSnapshot = "E_UNABLE_TO_SNAPSHOT";
16
+        private readonly ReactContext _reactContext;
17
+
18
+        /// <summary>
19
+        /// Instantiates the <see cref="RNViewShotModule"/>.
20
+        /// </summary>
21
+        public RNViewShotModule(ReactContext reactContext) : base(reactContext)
22
+        {
23
+            this._reactContext = reactContext;
24
+        }
25
+
26
+        /// <summary>
27
+        /// The name of the native module.
28
+        /// </summary>
29
+        public override string Name
30
+        {
31
+            get
32
+            {
33
+                return "RNViewShot";
34
+            }
35
+        }
36
+
37
+        [ReactMethod]
38
+        public void takeSnapshot(int tag, JObject options, IPromise promise)
39
+        {
40
+            string format = options["format"] != null ? options.Value<string>("format") : "png";
41
+            double quality = options["quality"] != null ? options.Value<double>("quality") : 1.0;
42
+            int? width = options["width"] != null ? options.Value<int?>("width") : null;
43
+            int? height = options["height"] != null ? options.Value<int?>("height") : null;
44
+            string result = options["result"] != null ? options.Value<string>("result") : "file";
45
+            string path = options["path"] != null ? options.Value<string>("path") : null;
46
+
47
+            if (format != "png" && format != "jpg" && format != "jpeg")
48
+            {
49
+                promise.Reject(ViewShot.ErrorUnableToSnapshot, "Unsupported image format: " + format + ". Try one of: png | jpg | jpeg");
50
+                return;
51
+            }
52
+
53
+            UIManagerModule uiManager = this._reactContext.GetNativeModule<UIManagerModule>();
54
+            var viewShot = new ViewShot(tag, format, quality, width, height, path, result, promise);
55
+            uiManager.AddUIBlock(viewShot);
56
+        }
57
+    }
58
+}

+ 53
- 0
windows/RNViewShot.Net46/RNViewShotPackage.cs View File

@@ -0,0 +1,53 @@
1
+using ReactNative.Bridge;
2
+using ReactNative.Modules.Core;
3
+using ReactNative.UIManager;
4
+using System;
5
+using System.Collections.Generic;
6
+
7
+namespace RNViewShot
8
+{
9
+    /// <summary>
10
+    /// Package defining core framework modules (e.g., <see cref="UIManagerModule"/>).
11
+    /// It should be used for modules that require special integration with
12
+    /// other framework parts (e.g., with the list of packages to load view
13
+    /// managers from).
14
+    /// </summary>
15
+    public class RNViewShotPackage : IReactPackage
16
+    {
17
+        /// <summary>
18
+        /// Creates the list of native modules to register with the react
19
+        /// instance.
20
+        /// </summary>
21
+        /// <param name="reactContext">The react application context.</param>
22
+        /// <returns>The list of native modules.</returns>
23
+        public IReadOnlyList<INativeModule> CreateNativeModules(ReactContext reactContext)
24
+        {
25
+            return new List<INativeModule>
26
+            {
27
+                new RNViewShotModule(reactContext),
28
+            };
29
+        }
30
+
31
+        /// <summary>
32
+        /// Creates the list of JavaScript modules to register with the
33
+        /// react instance.
34
+        /// </summary>
35
+        /// <returns>The list of JavaScript modules.</returns>
36
+        public IReadOnlyList<Type> CreateJavaScriptModulesConfig()
37
+        {
38
+            return new List<Type>(0);
39
+        }
40
+
41
+        /// <summary>
42
+        /// Creates the list of view managers that should be registered with
43
+        /// the <see cref="UIManagerModule"/>.
44
+        /// </summary>
45
+        /// <param name="reactContext">The react application context.</param>
46
+        /// <returns>The list of view managers.</returns>
47
+        public IReadOnlyList<IViewManager> CreateViewManagers(
48
+            ReactContext reactContext)
49
+        {
50
+            return new List<IViewManager>(0);
51
+        }
52
+    }
53
+}

+ 156
- 0
windows/RNViewShot.Net46/ViewShot.cs View File

@@ -0,0 +1,156 @@
1
+using ReactNative.Bridge;
2
+using ReactNative.UIManager;
3
+using System;
4
+using System.Diagnostics;
5
+using System.IO;
6
+using System.Windows;
7
+using System.Windows.Media;
8
+using System.Windows.Media.Imaging;
9
+
10
+namespace RNViewShot
11
+{
12
+    public class ViewShot : IUIBlock
13
+    {
14
+        public const string ErrorUnableToSnapshot = "E_UNABLE_TO_SNAPSHOT";
15
+        private int tag;
16
+        private string extension;
17
+        private double quality;
18
+        private int? width;
19
+        private int? height;
20
+        private string path;
21
+        private string result;
22
+        private IPromise promise;
23
+
24
+        public ViewShot(
25
+            int tag,
26
+            string extension,
27
+            double quality,
28
+            int? width,
29
+            int? height,
30
+            string path,
31
+            string result,
32
+            IPromise promise)
33
+        {
34
+            this.tag = tag;
35
+            this.extension = extension;
36
+            this.quality = quality;
37
+            this.width = width;
38
+            this.height = height;
39
+            this.path = path;
40
+            this.result = result;
41
+            this.promise = promise;
42
+        }
43
+
44
+        public void Execute(NativeViewHierarchyManager nvhm)
45
+        {
46
+            var view = nvhm.ResolveView(tag) as FrameworkElement;
47
+            if (view == null)
48
+            {
49
+                promise.Reject(ErrorUnableToSnapshot, "No view found with reactTag: " + tag);
50
+                return;
51
+            }
52
+
53
+            try
54
+            {
55
+                BitmapEncoder image = CaptureView(view);
56
+
57
+                if ("file" == result)
58
+                {
59
+                    string filePath = GetFilePath();
60
+                    Stream stream = File.Create(filePath);
61
+                    image.Save(stream);
62
+                    promise.Resolve(filePath);
63
+                    stream.Close();
64
+                }
65
+                else if ("base64" == result)
66
+                {
67
+                    MemoryStream stream = new MemoryStream();
68
+                    image.Save(stream);
69
+                    byte[] imageBytes = stream.ToArray();
70
+                    string data = Convert.ToBase64String(imageBytes);
71
+                    promise.Resolve(data);
72
+                    stream.Close();
73
+                }
74
+                else if ("data-uri" == result)
75
+                {
76
+                    MemoryStream stream = new MemoryStream();
77
+                    image.Save(stream);
78
+                    byte[] imageBytes = stream.ToArray();
79
+                    string data = Convert.ToBase64String(imageBytes);
80
+                    data = "data:image/" + extension + ";base64," + data;
81
+                    promise.Resolve(data);
82
+                    stream.Close();
83
+                }
84
+                else
85
+                {
86
+                    promise.Reject(ErrorUnableToSnapshot, "Unsupported result: " + result + ". Try one of: file | base64 | data-uri");
87
+                }
88
+            }
89
+            catch (Exception ex)
90
+            {
91
+                Debug.WriteLine(ex.ToString());
92
+                promise.Reject(ErrorUnableToSnapshot, "Failed to capture view snapshot");
93
+            }
94
+        }
95
+
96
+        private BitmapEncoder CaptureView(FrameworkElement view)
97
+        {
98
+            int w = (int)view.ActualWidth;
99
+            int h = (int)view.ActualHeight;
100
+
101
+            if (w <= 0 || h <= 0)
102
+            {
103
+                throw new InvalidOperationException("Impossible to snapshot the view: view is invalid");
104
+            }
105
+
106
+            RenderTargetBitmap targetBitmap = new RenderTargetBitmap(w, h, 96, 96, PixelFormats.Default);
107
+            targetBitmap.Render(view);
108
+
109
+            BitmapSource bitmap;
110
+            if (width != null && height != null && (width != w || height != h))
111
+            {
112
+                double scaleX = (double)width / targetBitmap.PixelWidth;
113
+                double scaleY = (double)height / targetBitmap.PixelHeight;
114
+                bitmap = new TransformedBitmap(targetBitmap, new ScaleTransform(scaleX, scaleY));
115
+            }
116
+            else
117
+            {
118
+                bitmap = targetBitmap;
119
+            }
120
+
121
+            if (bitmap == null)
122
+            {
123
+                throw new InvalidOperationException("Impossible to snapshot the view");
124
+            }
125
+
126
+            if (extension == "png")
127
+            {
128
+                PngBitmapEncoder image = new PngBitmapEncoder();
129
+                image.Frames.Add(BitmapFrame.Create(bitmap));
130
+                return image;
131
+            }
132
+            else
133
+            {
134
+                JpegBitmapEncoder image = new JpegBitmapEncoder();
135
+                image.QualityLevel = (int)(100.0 * quality);
136
+                image.Frames.Add(BitmapFrame.Create(bitmap));
137
+                return image;
138
+            }
139
+        }
140
+
141
+        private string GetFilePath()
142
+        {
143
+            if (string.IsNullOrEmpty(path)) 
144
+            {
145
+                string tmpFilePath = Path.GetTempPath();
146
+                string fileName = Guid.NewGuid().ToString();
147
+                fileName = Path.ChangeExtension(fileName, extension);
148
+                return Path.Combine(tmpFilePath, fileName);
149
+            }
150
+            else
151
+            {
152
+                return path;
153
+            }
154
+        }
155
+    }
156
+}

+ 11
- 0
windows/RNViewShot.Net46/app.config View File

@@ -0,0 +1,11 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<configuration>
3
+  <runtime>
4
+    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
5
+      <dependentAssembly>
6
+        <assemblyIdentity name="System.Reactive.Core" publicKeyToken="94bc3704cddfc263" culture="neutral" />
7
+        <bindingRedirect oldVersion="0.0.0.0-3.0.3000.0" newVersion="3.0.3000.0" />
8
+      </dependentAssembly>
9
+    </assemblyBinding>
10
+  </runtime>
11
+</configuration>

+ 4
- 0
windows/RNViewShot.Net46/packages.config View File

@@ -0,0 +1,4 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<packages>
3
+  <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net46" />
4
+</packages>

+ 126
- 0
windows/RNViewShot.sln View File

@@ -0,0 +1,126 @@
1
+Microsoft Visual Studio Solution File, Format Version 12.00
2
+# Visual Studio 14
3
+VisualStudioVersion = 14.0.25420.1
4
+MinimumVisualStudioVersion = 10.0.40219.1
5
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RNViewShot", "RNViewShot\RNViewShot.csproj", "{391A35D0-FEBA-11E6-9171-BD5177E581B7}"
6
+EndProject
7
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactNative", "..\node_modules\react-native-windows\ReactWindows\ReactNative\ReactNative.csproj", "{C7673AD5-E3AA-468C-A5FD-FA38154E205C}"
8
+EndProject
9
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ChakraBridge", "..\node_modules\react-native-windows\ReactWindows\ChakraBridge\ChakraBridge.vcxproj", "{4B72C796-16D5-4E3A-81C0-3E36F531E578}"
10
+EndProject
11
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ReactNative.Net46", "..\node_modules\react-native-windows\ReactWindows\ReactNative.Net46\ReactNative.Net46.csproj", "{22CBFF9C-FE36-43E8-A246-266C7635E662}"
12
+EndProject
13
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RNViewShot.Net46", "RNViewShot.Net46\RNViewShot.Net46.csproj", "{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}"
14
+EndProject
15
+Global
16
+	GlobalSection(SharedMSBuildProjectFiles) = preSolution
17
+		..\node_modules\react-native-windows\ReactWindows\ReactNative.Shared\ReactNative.Shared.projitems*{22cbff9c-fe36-43e8-a246-266c7635e662}*SharedItemsImports = 4
18
+		..\node_modules\react-native-windows\ReactWindows\ReactNative.Shared\ReactNative.Shared.projitems*{c7673ad5-e3aa-468c-a5fd-fa38154e205c}*SharedItemsImports = 4
19
+	EndGlobalSection
20
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
21
+		Debug|ARM = Debug|ARM
22
+		Debug|x64 = Debug|x64
23
+		Debug|x86 = Debug|x86
24
+		Development|ARM = Development|ARM
25
+		Development|x64 = Development|x64
26
+		Development|x86 = Development|x86
27
+		Release|ARM = Release|ARM
28
+		Release|x64 = Release|x64
29
+		Release|x86 = Release|x86
30
+	EndGlobalSection
31
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
32
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Debug|ARM.ActiveCfg = Debug|ARM
33
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Debug|ARM.Build.0 = Debug|ARM
34
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Debug|x64.ActiveCfg = Debug|x64
35
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Debug|x64.Build.0 = Debug|x64
36
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Debug|x86.ActiveCfg = Debug|x86
37
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Debug|x86.Build.0 = Debug|x86
38
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Development|ARM.ActiveCfg = Development|ARM
39
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Development|ARM.Build.0 = Development|ARM
40
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Development|x64.ActiveCfg = Development|x64
41
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Development|x64.Build.0 = Development|x64
42
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Development|x86.ActiveCfg = Development|x86
43
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Development|x86.Build.0 = Development|x86
44
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Release|ARM.ActiveCfg = Release|ARM
45
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Release|ARM.Build.0 = Release|ARM
46
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Release|x64.ActiveCfg = Release|x64
47
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Release|x64.Build.0 = Release|x64
48
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Release|x86.ActiveCfg = Release|x86
49
+		{391A35D0-FEBA-11E6-9171-BD5177E581B7}.Release|x86.Build.0 = Release|x86
50
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|ARM.ActiveCfg = Debug|ARM
51
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|ARM.Build.0 = Debug|ARM
52
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x64.ActiveCfg = Debug|x64
53
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x64.Build.0 = Debug|x64
54
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x86.ActiveCfg = Debug|x86
55
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Debug|x86.Build.0 = Debug|x86
56
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Development|ARM.ActiveCfg = Debug|ARM
57
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Development|ARM.Build.0 = Debug|ARM
58
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Development|x64.ActiveCfg = Debug|x64
59
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Development|x64.Build.0 = Debug|x64
60
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Development|x86.ActiveCfg = Debug|x86
61
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Development|x86.Build.0 = Debug|x86
62
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|ARM.ActiveCfg = Release|ARM
63
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|ARM.Build.0 = Release|ARM
64
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x64.ActiveCfg = Release|x64
65
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x64.Build.0 = Release|x64
66
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x86.ActiveCfg = Release|x86
67
+		{C7673AD5-E3AA-468C-A5FD-FA38154E205C}.Release|x86.Build.0 = Release|x86
68
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|ARM.ActiveCfg = Debug|ARM
69
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|ARM.Build.0 = Debug|ARM
70
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|x64.ActiveCfg = Debug|x64
71
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|x64.Build.0 = Debug|x64
72
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|x86.ActiveCfg = Debug|Win32
73
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Debug|x86.Build.0 = Debug|Win32
74
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Development|ARM.ActiveCfg = Debug|ARM
75
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Development|ARM.Build.0 = Debug|ARM
76
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Development|x64.ActiveCfg = Debug|x64
77
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Development|x64.Build.0 = Debug|x64
78
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Development|x86.ActiveCfg = Debug|Win32
79
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Development|x86.Build.0 = Debug|Win32
80
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|ARM.ActiveCfg = Release|ARM
81
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|ARM.Build.0 = Release|ARM
82
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|x64.ActiveCfg = Release|x64
83
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|x64.Build.0 = Release|x64
84
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|x86.ActiveCfg = Release|Win32
85
+		{4B72C796-16D5-4E3A-81C0-3E36F531E578}.Release|x86.Build.0 = Release|Win32
86
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|ARM.ActiveCfg = Debug|ARM
87
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|ARM.Build.0 = Debug|ARM
88
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|x64.ActiveCfg = Debug|x64
89
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|x64.Build.0 = Debug|x64
90
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|x86.ActiveCfg = Debug|x86
91
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Debug|x86.Build.0 = Debug|x86
92
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Development|ARM.ActiveCfg = Debug|ARM
93
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Development|ARM.Build.0 = Debug|ARM
94
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Development|x64.ActiveCfg = Debug|x64
95
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Development|x64.Build.0 = Debug|x64
96
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Development|x86.ActiveCfg = Debug|x86
97
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Development|x86.Build.0 = Debug|x86
98
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|ARM.ActiveCfg = Release|ARM
99
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|ARM.Build.0 = Release|ARM
100
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|x64.ActiveCfg = Release|x64
101
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|x64.Build.0 = Release|x64
102
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|x86.ActiveCfg = Release|x86
103
+		{22CBFF9C-FE36-43E8-A246-266C7635E662}.Release|x86.Build.0 = Release|x86
104
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Debug|ARM.ActiveCfg = Debug|x86
105
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Debug|ARM.Build.0 = Debug|x86
106
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Debug|x64.ActiveCfg = Debug|x64
107
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Debug|x64.Build.0 = Debug|x64
108
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Debug|x86.ActiveCfg = Debug|x86
109
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Debug|x86.Build.0 = Debug|x86
110
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Development|ARM.ActiveCfg = Debug|x86
111
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Development|ARM.Build.0 = Debug|x86
112
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Development|x64.ActiveCfg = Debug|x64
113
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Development|x64.Build.0 = Debug|x64
114
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Development|x86.ActiveCfg = Debug|x86
115
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Development|x86.Build.0 = Debug|x86
116
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Release|ARM.ActiveCfg = Release|x86
117
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Release|ARM.Build.0 = Release|x86
118
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Release|x64.ActiveCfg = Release|x64
119
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Release|x64.Build.0 = Release|x64
120
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Release|x86.ActiveCfg = Release|x86
121
+		{1DD45D00-DDF4-43B4-AB28-F98E6DC325B5}.Release|x86.Build.0 = Release|x86
122
+	EndGlobalSection
123
+	GlobalSection(SolutionProperties) = preSolution
124
+		HideSolutionNode = FALSE
125
+	EndGlobalSection
126
+EndGlobal

+ 30
- 0
windows/RNViewShot/Properties/AssemblyInfo.cs View File

@@ -0,0 +1,30 @@
1
+using System.Reflection;
2
+using System.Runtime.CompilerServices;
3
+using System.Runtime.InteropServices;
4
+
5
+// General Information about an assembly is controlled through the following
6
+// set of attributes. Change these attribute values to modify the information
7
+// associated with an assembly.
8
+[assembly: AssemblyTitle("RNViewShot")]
9
+[assembly: AssemblyDescription("")]
10
+[assembly: AssemblyConfiguration("")]
11
+[assembly: AssemblyCompany("")]
12
+[assembly: AssemblyProduct("RNViewShot")]
13
+[assembly: AssemblyCopyright("Copyright ©  2016")]
14
+[assembly: AssemblyTrademark("")]
15
+[assembly: AssemblyCulture("")]
16
+
17
+// Version information for an assembly consists of the following four values:
18
+//
19
+//      Major Version
20
+//      Minor Version
21
+//      Build Number
22
+//      Revision
23
+//
24
+// You can specify all the values or you can default the Build and Revision Numbers
25
+// by using the '*' as shown below:
26
+// [assembly: AssemblyVersion("1.0.*")]
27
+[assembly: AssemblyVersion("1.0.0.0")]
28
+[assembly: AssemblyFileVersion("1.0.0.0")]
29
+[assembly: ComVisible(false)]
30
+  

+ 28
- 0
windows/RNViewShot/Properties/RNViewShot.rd.xml View File

@@ -0,0 +1,28 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<!--
3
+    This file contains Runtime Directives, specifications about types your application accesses
4
+    through reflection and other dynamic code patterns. Runtime Directives are used to control the
5
+    .NET Native optimizer and ensure that it does not remove code accessed by your library. If your
6
+    library does not do any reflection, then you generally do not need to edit this file. However,
7
+    if your library reflects over types, especially types passed to it or derived from its types,
8
+    then you should write Runtime Directives.
9
+    The most common use of reflection in libraries is to discover information about types passed
10
+    to the library. Runtime Directives have three ways to express requirements on types passed to
11
+    your library.
12
+    1.  Parameter, GenericParameter, TypeParameter, TypeEnumerableParameter
13
+        Use these directives to reflect over types passed as a parameter.
14
+    2.  SubTypes
15
+        Use a SubTypes directive to reflect over types derived from another type.
16
+    3.  AttributeImplies
17
+        Use an AttributeImplies directive to indicate that your library needs to reflect over
18
+        types or methods decorated with an attribute.
19
+    For more information on writing Runtime Directives for libraries, please visit
20
+    http://go.microsoft.com/fwlink/?LinkID=391919
21
+-->
22
+<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
23
+  <Library Name="RNViewShot">
24
+
25
+  	<!-- add directives for your library here -->
26
+
27
+  </Library>
28
+</Directives>

+ 184
- 0
windows/RNViewShot/RNViewShot.csproj View File

@@ -0,0 +1,184 @@
1
+<?xml version="1.0" encoding="utf-8"?>
2
+<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3
+  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
4
+  <PropertyGroup>
5
+    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
6
+    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
7
+    <ProjectGuid>{391A35D0-FEBA-11E6-9171-BD5177E581B7}</ProjectGuid>
8
+    <OutputType>Library</OutputType>
9
+    <AppDesignerFolder>Properties</AppDesignerFolder>
10
+    <RootNamespace>RNViewShot</RootNamespace>
11
+    <AssemblyName>RNViewShot</AssemblyName>
12
+    <DefaultLanguage>en-US</DefaultLanguage>
13
+    <TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
14
+    <TargetPlatformVersion>10.0.10586.0</TargetPlatformVersion>
15
+    <TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
16
+    <MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
17
+    <FileAlignment>512</FileAlignment>
18
+    <ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
19
+    <ReactWindowsRoot>$(SolutionDir)..\node_modules</ReactWindowsRoot>
20
+  </PropertyGroup>
21
+  <PropertyGroup Condition=" '$(Configuration)' != 'Development'">
22
+    <ReactWindowsRoot>..\..</ReactWindowsRoot>
23
+  </PropertyGroup>
24
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
25
+    <PlatformTarget>AnyCPU</PlatformTarget>
26
+    <DebugSymbols>true</DebugSymbols>
27
+    <DebugType>full</DebugType>
28
+    <Optimize>false</Optimize>
29
+    <OutputPath>bin\Debug\</OutputPath>
30
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
31
+    <ErrorReport>prompt</ErrorReport>
32
+    <WarningLevel>4</WarningLevel>
33
+  </PropertyGroup>
34
+  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
35
+    <PlatformTarget>AnyCPU</PlatformTarget>
36
+    <DebugType>pdbonly</DebugType>
37
+    <Optimize>true</Optimize>
38
+    <OutputPath>bin\Release\</OutputPath>
39
+    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
40
+    <ErrorReport>prompt</ErrorReport>
41
+    <WarningLevel>4</WarningLevel>
42
+  </PropertyGroup>
43
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
44
+    <PlatformTarget>x86</PlatformTarget>
45
+    <DebugSymbols>true</DebugSymbols>
46
+    <OutputPath>bin\x86\Debug\</OutputPath>
47
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
48
+    <NoWarn>;2008</NoWarn>
49
+    <DebugType>full</DebugType>
50
+    <PlatformTarget>x86</PlatformTarget>
51
+    <UseVSHostingProcess>false</UseVSHostingProcess>
52
+    <ErrorReport>prompt</ErrorReport>
53
+  </PropertyGroup>
54
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
55
+    <PlatformTarget>x86</PlatformTarget>
56
+    <OutputPath>bin\x86\Release\</OutputPath>
57
+    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
58
+    <Optimize>true</Optimize>
59
+    <NoWarn>;2008</NoWarn>
60
+    <DebugType>pdbonly</DebugType>
61
+    <PlatformTarget>x86</PlatformTarget>
62
+    <UseVSHostingProcess>false</UseVSHostingProcess>
63
+    <ErrorReport>prompt</ErrorReport>
64
+  </PropertyGroup>
65
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
66
+    <PlatformTarget>ARM</PlatformTarget>
67
+    <DebugSymbols>true</DebugSymbols>
68
+    <OutputPath>bin\ARM\Debug\</OutputPath>
69
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
70
+    <NoWarn>;2008</NoWarn>
71
+    <DebugType>full</DebugType>
72
+    <PlatformTarget>ARM</PlatformTarget>
73
+    <UseVSHostingProcess>false</UseVSHostingProcess>
74
+    <ErrorReport>prompt</ErrorReport>
75
+  </PropertyGroup>
76
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
77
+    <PlatformTarget>ARM</PlatformTarget>
78
+    <OutputPath>bin\ARM\Release\</OutputPath>
79
+    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
80
+    <Optimize>true</Optimize>
81
+    <NoWarn>;2008</NoWarn>
82
+    <DebugType>pdbonly</DebugType>
83
+    <PlatformTarget>ARM</PlatformTarget>
84
+    <UseVSHostingProcess>false</UseVSHostingProcess>
85
+    <ErrorReport>prompt</ErrorReport>
86
+  </PropertyGroup>
87
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
88
+    <PlatformTarget>x64</PlatformTarget>
89
+    <DebugSymbols>true</DebugSymbols>
90
+    <OutputPath>bin\x64\Debug\</OutputPath>
91
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
92
+    <NoWarn>;2008</NoWarn>
93
+    <DebugType>full</DebugType>
94
+    <PlatformTarget>x64</PlatformTarget>
95
+    <UseVSHostingProcess>false</UseVSHostingProcess>
96
+    <ErrorReport>prompt</ErrorReport>
97
+  </PropertyGroup>
98
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
99
+    <PlatformTarget>x64</PlatformTarget>
100
+    <OutputPath>bin\x64\Release\</OutputPath>
101
+    <DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
102
+    <Optimize>true</Optimize>
103
+    <NoWarn>;2008</NoWarn>
104
+    <DebugType>pdbonly</DebugType>
105
+    <PlatformTarget>x64</PlatformTarget>
106
+    <UseVSHostingProcess>false</UseVSHostingProcess>
107
+    <ErrorReport>prompt</ErrorReport>
108
+  </PropertyGroup>
109
+  <ItemGroup>
110
+    <!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
111
+    <None Include="project.json" />
112
+  </ItemGroup>
113
+  <ItemGroup>
114
+    <Compile Include="Properties\AssemblyInfo.cs" />
115
+    <Compile Include="RNViewShotModule.cs" />
116
+    <Compile Include="RNViewShotPackage.cs" />
117
+    <Compile Include="ViewShot.cs" />
118
+    <EmbeddedResource Include="Properties\RNViewShot.rd.xml" />
119
+  </ItemGroup>
120
+  <ItemGroup>
121
+    <ProjectReference Include="..\..\..\react-native-windows\ReactWindows\ReactNative\ReactNative.csproj">
122
+      <Project>{c7673ad5-e3aa-468c-a5fd-fa38154e205c}</Project>
123
+      <Name>ReactNative</Name>
124
+    </ProjectReference>
125
+  </ItemGroup>
126
+  <PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
127
+    <VisualStudioVersion>14.0</VisualStudioVersion>
128
+  </PropertyGroup>
129
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Development|AnyCPU'">
130
+    <DebugSymbols>true</DebugSymbols>
131
+    <OutputPath>bin\Development\</OutputPath>
132
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
133
+    <NoStdLib>true</NoStdLib>
134
+    <DebugType>full</DebugType>
135
+    <PlatformTarget>AnyCPU</PlatformTarget>
136
+    <UseVSHostingProcess>false</UseVSHostingProcess>
137
+    <ErrorReport>prompt</ErrorReport>
138
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
139
+  </PropertyGroup>
140
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Development|x86'">
141
+    <DebugSymbols>true</DebugSymbols>
142
+    <OutputPath>bin\x86\Development\</OutputPath>
143
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
144
+    <NoWarn>;2008</NoWarn>
145
+    <NoStdLib>true</NoStdLib>
146
+    <DebugType>full</DebugType>
147
+    <PlatformTarget>x86</PlatformTarget>
148
+    <UseVSHostingProcess>false</UseVSHostingProcess>
149
+    <ErrorReport>prompt</ErrorReport>
150
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
151
+  </PropertyGroup>
152
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Development|ARM'">
153
+    <DebugSymbols>true</DebugSymbols>
154
+    <OutputPath>bin\ARM\Development\</OutputPath>
155
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
156
+    <NoWarn>;2008</NoWarn>
157
+    <NoStdLib>true</NoStdLib>
158
+    <DebugType>full</DebugType>
159
+    <PlatformTarget>ARM</PlatformTarget>
160
+    <UseVSHostingProcess>false</UseVSHostingProcess>
161
+    <ErrorReport>prompt</ErrorReport>
162
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
163
+  </PropertyGroup>
164
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Development|x64'">
165
+    <DebugSymbols>true</DebugSymbols>
166
+    <OutputPath>bin\x64\Development\</OutputPath>
167
+    <DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
168
+    <NoWarn>;2008</NoWarn>
169
+    <NoStdLib>true</NoStdLib>
170
+    <DebugType>full</DebugType>
171
+    <PlatformTarget>x64</PlatformTarget>
172
+    <UseVSHostingProcess>false</UseVSHostingProcess>
173
+    <ErrorReport>prompt</ErrorReport>
174
+    <CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
175
+  </PropertyGroup>
176
+  <Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
177
+  <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
178
+       Other similar extension points exist, see Microsoft.Common.targets.
179
+  <Target Name="BeforeBuild">
180
+  </Target>
181
+  <Target Name="AfterBuild">
182
+  </Target>
183
+  -->
184
+</Project>

+ 58
- 0
windows/RNViewShot/RNViewShotModule.cs View File

@@ -0,0 +1,58 @@
1
+using Newtonsoft.Json.Linq;
2
+using ReactNative.Bridge;
3
+using ReactNative.UIManager;
4
+using System;
5
+using System.IO;
6
+using System.Collections.Generic;
7
+
8
+namespace RNViewShot
9
+{
10
+    /// <summary>
11
+    /// A module that allows JS to share data.
12
+    /// </summary>
13
+    class RNViewShotModule : ReactContextNativeModuleBase
14
+    {
15
+        private const string ErrorUnableToSnapshot = "E_UNABLE_TO_SNAPSHOT";
16
+        private readonly ReactContext _reactContext;
17
+
18
+        /// <summary>
19
+        /// Instantiates the <see cref="RNViewShotModule"/>.
20
+        /// </summary>
21
+        public RNViewShotModule(ReactContext reactContext) : base(reactContext)
22
+        {
23
+            this._reactContext = reactContext;
24
+        }
25
+
26
+        /// <summary>
27
+        /// The name of the native module.
28
+        /// </summary>
29
+        public override string Name
30
+        {
31
+            get
32
+            {
33
+                return "RNViewShot";
34
+            }
35
+        }
36
+
37
+        [ReactMethod]
38
+        public void takeSnapshot(int tag, JObject options, IPromise promise)
39
+        {
40
+            string format = options["format"] != null ? options.Value<string>("format") : "png";
41
+            double quality = options["quality"] != null ? options.Value<double>("quality") : 1.0;
42
+            int? width = options["width"] != null ? options.Value<int?>("width") : null;
43
+            int? height = options["height"] != null ? options.Value<int?>("height") : null;
44
+            string result = options["result"] != null ? options.Value<string>("result") : "file";
45
+            string path = options["path"] != null ? options.Value<string>("path") : null;
46
+
47
+            if (format != "png" && format != "jpg" && format != "jpeg")
48
+            {
49
+                promise.Reject(ViewShot.ErrorUnableToSnapshot, "Unsupported image format: " + format + ". Try one of: png | jpg | jpeg");
50
+                return;
51
+            }
52
+
53
+            UIManagerModule uiManager = this._reactContext.GetNativeModule<UIManagerModule>();
54
+            var viewShot = new ViewShot(tag, format, quality, width, height, path, result, promise);
55
+            uiManager.AddUIBlock(viewShot);
56
+        }
57
+    }
58
+}

+ 53
- 0
windows/RNViewShot/RNViewShotPackage.cs View File

@@ -0,0 +1,53 @@
1
+using ReactNative.Bridge;
2
+using ReactNative.Modules.Core;
3
+using ReactNative.UIManager;
4
+using System;
5
+using System.Collections.Generic;
6
+
7
+namespace RNViewShot
8
+{
9
+    /// <summary>
10
+    /// Package defining core framework modules (e.g., <see cref="UIManagerModule"/>).
11
+    /// It should be used for modules that require special integration with
12
+    /// other framework parts (e.g., with the list of packages to load view
13
+    /// managers from).
14
+    /// </summary>
15
+    public class RNViewShotPackage : IReactPackage
16
+    {
17
+        /// <summary>
18
+        /// Creates the list of native modules to register with the react
19
+        /// instance.
20
+        /// </summary>
21
+        /// <param name="reactContext">The react application context.</param>
22
+        /// <returns>The list of native modules.</returns>
23
+        public IReadOnlyList<INativeModule> CreateNativeModules(ReactContext reactContext)
24
+        {
25
+            return new List<INativeModule>
26
+            {
27
+                new RNViewShotModule(reactContext),
28
+            };
29
+        }
30
+
31
+        /// <summary>
32
+        /// Creates the list of JavaScript modules to register with the
33
+        /// react instance.
34
+        /// </summary>
35
+        /// <returns>The list of JavaScript modules.</returns>
36
+        public IReadOnlyList<Type> CreateJavaScriptModulesConfig()
37
+        {
38
+            return new List<Type>(0);
39
+        }
40
+
41
+        /// <summary>
42
+        /// Creates the list of view managers that should be registered with
43
+        /// the <see cref="UIManagerModule"/>.
44
+        /// </summary>
45
+        /// <param name="reactContext">The react application context.</param>
46
+        /// <returns>The list of view managers.</returns>
47
+        public IReadOnlyList<IViewManager> CreateViewManagers(
48
+            ReactContext reactContext)
49
+        {
50
+            return new List<IViewManager>(0);
51
+        }
52
+    }
53
+}

+ 170
- 0
windows/RNViewShot/ViewShot.cs View File

@@ -0,0 +1,170 @@
1
+using ReactNative.Bridge;
2
+using ReactNative.UIManager;
3
+using System;
4
+using System.Diagnostics;
5
+using System.IO;
6
+using System.Runtime.InteropServices.WindowsRuntime;
7
+using System.Threading.Tasks;
8
+using Windows.Graphics.Display;
9
+using Windows.Graphics.Imaging;
10
+using Windows.Storage;
11
+using Windows.Storage.Streams;
12
+using Windows.UI.Xaml;
13
+using Windows.UI.Xaml.Media.Imaging;
14
+
15
+namespace RNViewShot
16
+{
17
+    public class ViewShot : IUIBlock
18
+    {
19
+        public const string ErrorUnableToSnapshot = "E_UNABLE_TO_SNAPSHOT";
20
+        private int tag;
21
+        private string extension;
22
+        private double quality;
23
+        private int? width;
24
+        private int? height;
25
+        private string path;
26
+        private string result;
27
+        private IPromise promise;
28
+
29
+        public ViewShot(
30
+            int tag,
31
+            string extension,
32
+            double quality,
33
+            int? width,
34
+            int? height,
35
+            string path,
36
+            string result,
37
+            IPromise promise)
38
+        {
39
+            this.tag = tag;
40
+            this.extension = extension;
41
+            this.quality = quality;
42
+            this.width = width;
43
+            this.height = height;
44
+            this.path = path;
45
+            this.result = result;
46
+            this.promise = promise;
47
+        }
48
+
49
+        public async void Execute(NativeViewHierarchyManager nvhm)
50
+        {
51
+            var view = nvhm.ResolveView(tag) as FrameworkElement;
52
+            if (view == null)
53
+            {
54
+                promise.Reject(ErrorUnableToSnapshot, "No view found with reactTag: " + tag);
55
+                return;
56
+            }
57
+
58
+            try
59
+            {
60
+                if ("file" == result)
61
+                {
62
+                    using (var ras = new InMemoryRandomAccessStream())
63
+                    {
64
+                        await CaptureView(view, ras);
65
+                        var file = await GetStorageFile();
66
+                        using (var fileStream = await file.OpenAsync(FileAccessMode.ReadWrite))
67
+                        {
68
+                            await RandomAccessStream.CopyAndCloseAsync(ras.GetInputStreamAt(0), fileStream.GetOutputStreamAt(0));
69
+                            promise.Resolve(file.Path);
70
+                        }
71
+                    }
72
+                }
73
+                else if ("base64" == result)
74
+                {
75
+                    using (var ras = new InMemoryRandomAccessStream())
76
+                    {
77
+                        await CaptureView(view, ras);
78
+                        var imageBytes = new byte[ras.Size];
79
+                        await ras.AsStream().ReadAsync(imageBytes, 0, imageBytes.Length);
80
+                        string data = Convert.ToBase64String(imageBytes);
81
+                        promise.Resolve(data);
82
+                    }
83
+                }
84
+                else if ("data-uri" == result)
85
+                {
86
+                    using (var ras = new InMemoryRandomAccessStream())
87
+                    {
88
+                        await CaptureView(view, ras);
89
+                        var imageBytes = new byte[ras.Size];
90
+                        await ras.AsStream().ReadAsync(imageBytes, 0, imageBytes.Length);
91
+                        string data = Convert.ToBase64String(imageBytes);
92
+                        data = "data:image/" + extension + ";base64," + data;
93
+                        promise.Resolve(data);
94
+                    }
95
+                }
96
+                else
97
+                {
98
+                    promise.Reject(ErrorUnableToSnapshot, "Unsupported result: " + result + ". Try one of: file | base64 | data-uri");
99
+                }
100
+            }
101
+            catch (Exception ex)
102
+            {
103
+                Debug.WriteLine(ex.ToString());
104
+                promise.Reject(ErrorUnableToSnapshot, "Failed to capture view snapshot");
105
+            }
106
+        }
107
+
108
+        private async Task<BitmapEncoder> CaptureView(FrameworkElement view, IRandomAccessStream stream)
109
+        {
110
+            int w = (int)view.ActualWidth;
111
+            int h = (int)view.ActualHeight;
112
+
113
+            if (w <= 0 || h <= 0)
114
+            {
115
+                throw new InvalidOperationException("Impossible to snapshot the view: view is invalid");
116
+            }
117
+
118
+            RenderTargetBitmap targetBitmap = new RenderTargetBitmap();
119
+            await targetBitmap.RenderAsync(view, w, h);
120
+
121
+            BitmapEncoder encoder;
122
+            if (extension != "png")
123
+            {
124
+                var propertySet = new BitmapPropertySet();
125
+                var qualityValue = new BitmapTypedValue(quality, Windows.Foundation.PropertyType.Single);
126
+                propertySet.Add("ImageQuality", qualityValue);
127
+                encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, stream, propertySet);
128
+            }
129
+            else
130
+            {
131
+                encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
132
+            }
133
+
134
+            var displayInformation = DisplayInformation.GetForCurrentView();
135
+            var pixelBuffer = await targetBitmap.GetPixelsAsync();
136
+
137
+            encoder.SetPixelData(
138
+                BitmapPixelFormat.Bgra8,
139
+                BitmapAlphaMode.Ignore,
140
+                (uint)targetBitmap.PixelWidth,
141
+                (uint)targetBitmap.PixelHeight,
142
+                displayInformation.LogicalDpi,
143
+                displayInformation.LogicalDpi,
144
+                pixelBuffer.ToArray());                
145
+
146
+
147
+            if (width != null && height != null && (width != w || height != h))
148
+            {
149
+                encoder.BitmapTransform.ScaledWidth = (uint)width;
150
+                encoder.BitmapTransform.ScaledWidth = (uint)height;
151
+            }
152
+
153
+            if (encoder == null)
154
+            {
155
+                throw new InvalidOperationException("Impossible to snapshot the view");
156
+            }
157
+
158
+            await encoder.FlushAsync();
159
+
160
+            return encoder;            
161
+        }
162
+
163
+        private async Task<StorageFile> GetStorageFile()
164
+        {
165
+            var storageFolder = ApplicationData.Current.LocalFolder;
166
+            var fileName = string.IsNullOrEmpty(path) ? path : Path.ChangeExtension(Guid.NewGuid().ToString(), extension);                
167
+            return await storageFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
168
+        }
169
+    }
170
+}

+ 17
- 0
windows/RNViewShot/project.json View File

@@ -0,0 +1,17 @@
1
+{
2
+  "dependencies": {
3
+    "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2",
4
+    "Newtonsoft.Json": "10.0.1-beta1"
5
+  },
6
+  "frameworks": {
7
+    "uap10.0": {}
8
+  },
9
+  "runtimes": {
10
+    "win10-arm": {},
11
+    "win10-arm-aot": {},
12
+    "win10-x86": {},
13
+    "win10-x86-aot": {},
14
+    "win10-x64": {},
15
+    "win10-x64-aot": {}
16
+  }
17
+}