| 
				
			 | 
			
			
				@@ -1,26 +1,178 @@ 
			 | 
		
	
		
			
			| 
				1
			 | 
			
				
			 | 
			
			
				-using System; 
			 | 
		
	
		
			
			| 
				2
			 | 
			
				
			 | 
			
			
				-using System.Collections.Generic; 
			 | 
		
	
		
			
			| 
				3
			 | 
			
				
			 | 
			
			
				-using System.Linq; 
			 | 
		
	
		
			
			| 
				4
			 | 
			
				
			 | 
			
			
				-using System.Text; 
			 | 
		
	
		
			
			| 
				5
			 | 
			
				
			 | 
			
			
				-using System.Threading.Tasks; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				1
			 | 
			
			
				+using ReactNative.Bridge; 
			 | 
		
	
		
			
			| 
				6
			 | 
			
				2
			 | 
			
			
				 using ReactNative.UIManager; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				3
			 | 
			
			
				+using System; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				4
			 | 
			
			
				+using System.IO; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				5
			 | 
			
			
				+using System.Runtime.InteropServices.WindowsRuntime; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				6
			 | 
			
			
				+using System.Threading.Tasks; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				7
			 | 
			
			
				+using Windows.Graphics.Display; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				8
			 | 
			
			
				+using Windows.Graphics.Imaging; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				9
			 | 
			
			
				+using Windows.Storage; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				10
			 | 
			
			
				+using Windows.Storage.Streams; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				11
			 | 
			
			
				+using Windows.UI.Xaml; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				12
			 | 
			
			
				+using Windows.UI.Xaml.Media; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				13
			 | 
			
			
				+using Windows.UI.Xaml.Media.Imaging; 
			 | 
		
	
		
			
			| 
				7
			 | 
			
				14
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				8
			 | 
			
				15
			 | 
			
			
				 namespace RNViewShot 
			 | 
		
	
		
			
			| 
				9
			 | 
			
				16
			 | 
			
			
				 { 
			 | 
		
	
		
			
			| 
				10
			 | 
			
				17
			 | 
			
			
				     public class ViewShot : IUIBlock 
			 | 
		
	
		
			
			| 
				11
			 | 
			
				18
			 | 
			
			
				     { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				19
			 | 
			
			
				+        public const string ErrorUnableToSnapshot = "E_UNABLE_TO_SNAPSHOT"; 
			 | 
		
	
		
			
			| 
				12
			 | 
			
				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; 
			 | 
		
	
		
			
			| 
				13
			 | 
			
				28
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				14
			 | 
			
				
			 | 
			
			
				-        public ViewShot(int tag) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				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) 
			 | 
		
	
		
			
			| 
				15
			 | 
			
				38
			 | 
			
			
				         { 
			 | 
		
	
		
			
			| 
				16
			 | 
			
				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; 
			 | 
		
	
		
			
			| 
				17
			 | 
			
				47
			 | 
			
			
				         } 
			 | 
		
	
		
			
			| 
				18
			 | 
			
				48
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				19
			 | 
			
				
			 | 
			
			
				-        public void Execute(NativeViewHierarchyManager nvhm) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				49
			 | 
			
			
				+        public async void Execute(NativeViewHierarchyManager nvhm) 
			 | 
		
	
		
			
			| 
				20
			 | 
			
				50
			 | 
			
			
				         { 
			 | 
		
	
		
			
			| 
				21
			 | 
			
				
			 | 
			
			
				-            var view = nvhm.ResolveView(this.tag); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				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 (InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream()) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				63
			 | 
			
			
				+                    { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				64
			 | 
			
			
				+                        await CaptureView(view, ras); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				65
			 | 
			
			
				+                        StorageFile 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 (InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream()) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				76
			 | 
			
			
				+                    { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				77
			 | 
			
			
				+                        await CaptureView(view, ras); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				78
			 | 
			
			
				+                        byte[] 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 (InMemoryRandomAccessStream ras = new InMemoryRandomAccessStream()) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				87
			 | 
			
			
				+                    { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				88
			 | 
			
			
				+                        await CaptureView(view, ras); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				89
			 | 
			
			
				+                        byte[] 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
			 | 
			
			
				+                Console.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
			 | 
			
			
				+            } 
			 | 
		
	
		
			
			| 
				22
			 | 
			
				133
			 | 
			
			
				  
			 | 
		
	
		
			
			| 
				23
			 | 
			
				
			 | 
			
			
				-            string depObj = view.ToString(); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				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
			 | 
			
			
				+            StorageFolder storageFolder = ApplicationData.Current.LocalFolder; 
			 | 
		
	
		
			
			| 
				
			 | 
			
				166
			 | 
			
			
				+            if (string.IsNullOrEmpty(path)) 
			 | 
		
	
		
			
			| 
				
			 | 
			
				167
			 | 
			
			
				+            { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				168
			 | 
			
			
				+                string fileName = Guid.NewGuid().ToString(); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				169
			 | 
			
			
				+                fileName = Path.ChangeExtension(fileName, extension); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				170
			 | 
			
			
				+                return await storageFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				171
			 | 
			
			
				+            } 
			 | 
		
	
		
			
			| 
				
			 | 
			
				172
			 | 
			
			
				+            else 
			 | 
		
	
		
			
			| 
				
			 | 
			
				173
			 | 
			
			
				+            { 
			 | 
		
	
		
			
			| 
				
			 | 
			
				174
			 | 
			
			
				+                return await storageFolder.CreateFileAsync(path, CreationCollisionOption.ReplaceExisting); 
			 | 
		
	
		
			
			| 
				
			 | 
			
				175
			 | 
			
			
				+            } 
			 | 
		
	
		
			
			| 
				24
			 | 
			
				176
			 | 
			
			
				         } 
			 | 
		
	
		
			
			| 
				25
			 | 
			
				177
			 | 
			
			
				     } 
			 | 
		
	
		
			
			| 
				26
			 | 
			
				178
			 | 
			
			
				 } 
			 |