From 3abb5ad9b21e9d1b758db7f57a223cbe4678a44e Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Tue, 1 Dec 2020 13:04:11 +0100 Subject: [PATCH 01/10] Add Windows support Adds basic Windows implementation for the module. --- README.md | 114 ++-- example/.gitignore | 64 ++ example/PDFExample.js | 1 + example/metro.config.js | 12 + example/package.json | 7 +- example/windows/.gitignore | 92 +++ example/windows/PDFExample.sln | 264 ++++++++ example/windows/PDFExample/.gitignore | 1 + example/windows/PDFExample/App.cpp | 80 +++ example/windows/PDFExample/App.h | 20 + example/windows/PDFExample/App.idl | 3 + example/windows/PDFExample/App.xaml | 10 + .../Assets/LockScreenLogo.scale-200.png | Bin 0 -> 1430 bytes .../Assets/SplashScreen.scale-200.png | Bin 0 -> 7700 bytes .../Assets/Square150x150Logo.scale-200.png | Bin 0 -> 2937 bytes .../Assets/Square44x44Logo.scale-200.png | Bin 0 -> 1647 bytes ...x44Logo.targetsize-24_altform-unplated.png | Bin 0 -> 1255 bytes .../windows/PDFExample/Assets/StoreLogo.png | Bin 0 -> 1451 bytes .../Assets/Wide310x150Logo.scale-200.png | Bin 0 -> 3204 bytes .../PDFExample/AutolinkedNativeModules.g.cpp | 18 + .../PDFExample/AutolinkedNativeModules.g.h | 10 + .../AutolinkedNativeModules.g.targets | 10 + example/windows/PDFExample/MainPage.cpp | 24 + example/windows/PDFExample/MainPage.h | 21 + example/windows/PDFExample/MainPage.idl | 8 + example/windows/PDFExample/MainPage.xaml | 16 + example/windows/PDFExample/PDFExample.vcxproj | 205 ++++++ .../PDFExample/PDFExample.vcxproj.filters | 64 ++ .../PDFExample/PDFExample_TemporaryKey.pfx | Bin 0 -> 2598 bytes .../windows/PDFExample/Package.appxmanifest | 50 ++ .../windows/PDFExample/PropertySheet.props | 16 + .../PDFExample/ReactPackageProvider.cpp | 18 + .../windows/PDFExample/ReactPackageProvider.h | 15 + example/windows/PDFExample/packages.config | 5 + example/windows/PDFExample/pch.cpp | 1 + example/windows/PDFExample/pch.h | 29 + index.js | 21 +- windows/RCTPdf/PropertySheet.props | 16 + windows/RCTPdf/RCTPdf.def | 3 + windows/RCTPdf/RCTPdf.vcxproj | 180 ++++++ windows/RCTPdf/RCTPdf.vcxproj.filters | 38 ++ windows/RCTPdf/RCTPdfControl.cpp | 586 ++++++++++++++++++ windows/RCTPdf/RCTPdfControl.h | 115 ++++ windows/RCTPdf/RCTPdfControl.idl | 10 + windows/RCTPdf/RCTPdfControl.xaml | 32 + windows/RCTPdf/RCTPdfViewManager.cpp | 69 +++ windows/RCTPdf/RCTPdfViewManager.h | 51 ++ windows/RCTPdf/ReactPackageProvider.cpp | 15 + windows/RCTPdf/ReactPackageProvider.h | 16 + windows/RCTPdf/ReactPackageProvider.idl | 9 + windows/RCTPdf/packages.config | 4 + windows/RCTPdf/pch.cpp | 1 + windows/RCTPdf/pch.h | 28 + windows/README.md | 23 + 54 files changed, 2344 insertions(+), 51 deletions(-) create mode 100644 example/windows/.gitignore create mode 100644 example/windows/PDFExample.sln create mode 100644 example/windows/PDFExample/.gitignore create mode 100644 example/windows/PDFExample/App.cpp create mode 100644 example/windows/PDFExample/App.h create mode 100644 example/windows/PDFExample/App.idl create mode 100644 example/windows/PDFExample/App.xaml create mode 100644 example/windows/PDFExample/Assets/LockScreenLogo.scale-200.png create mode 100644 example/windows/PDFExample/Assets/SplashScreen.scale-200.png create mode 100644 example/windows/PDFExample/Assets/Square150x150Logo.scale-200.png create mode 100644 example/windows/PDFExample/Assets/Square44x44Logo.scale-200.png create mode 100644 example/windows/PDFExample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png create mode 100644 example/windows/PDFExample/Assets/StoreLogo.png create mode 100644 example/windows/PDFExample/Assets/Wide310x150Logo.scale-200.png create mode 100644 example/windows/PDFExample/AutolinkedNativeModules.g.cpp create mode 100644 example/windows/PDFExample/AutolinkedNativeModules.g.h create mode 100644 example/windows/PDFExample/AutolinkedNativeModules.g.targets create mode 100644 example/windows/PDFExample/MainPage.cpp create mode 100644 example/windows/PDFExample/MainPage.h create mode 100644 example/windows/PDFExample/MainPage.idl create mode 100644 example/windows/PDFExample/MainPage.xaml create mode 100644 example/windows/PDFExample/PDFExample.vcxproj create mode 100644 example/windows/PDFExample/PDFExample.vcxproj.filters create mode 100644 example/windows/PDFExample/PDFExample_TemporaryKey.pfx create mode 100644 example/windows/PDFExample/Package.appxmanifest create mode 100644 example/windows/PDFExample/PropertySheet.props create mode 100644 example/windows/PDFExample/ReactPackageProvider.cpp create mode 100644 example/windows/PDFExample/ReactPackageProvider.h create mode 100644 example/windows/PDFExample/packages.config create mode 100644 example/windows/PDFExample/pch.cpp create mode 100644 example/windows/PDFExample/pch.h create mode 100644 windows/RCTPdf/PropertySheet.props create mode 100644 windows/RCTPdf/RCTPdf.def create mode 100644 windows/RCTPdf/RCTPdf.vcxproj create mode 100644 windows/RCTPdf/RCTPdf.vcxproj.filters create mode 100644 windows/RCTPdf/RCTPdfControl.cpp create mode 100644 windows/RCTPdf/RCTPdfControl.h create mode 100644 windows/RCTPdf/RCTPdfControl.idl create mode 100644 windows/RCTPdf/RCTPdfControl.xaml create mode 100644 windows/RCTPdf/RCTPdfViewManager.cpp create mode 100644 windows/RCTPdf/RCTPdfViewManager.h create mode 100644 windows/RCTPdf/ReactPackageProvider.cpp create mode 100644 windows/RCTPdf/ReactPackageProvider.h create mode 100644 windows/RCTPdf/ReactPackageProvider.idl create mode 100644 windows/RCTPdf/packages.config create mode 100644 windows/RCTPdf/pch.cpp create mode 100644 windows/RCTPdf/pch.h create mode 100644 windows/README.md diff --git a/README.md b/README.md index 308849f2..94e0d7b7 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,8 @@ So you should install react-native-pdf and rn-fetch-blob | progress-bar-android | | | | 1.0.3+ | | progress-view | | | | 1.0.3+ | +Currently, Windows support is partial. The rn-fetch-blob module is not yet available on Windows, only loading bundled PDFs is supported. + ### Installation ```bash @@ -86,6 +88,31 @@ react-native link react-native-pdf +### Windows installation +
+ Windows details + +- Open your solution in Visual Studio 2019 (eg. `windows\yourapp.sln`) +- Right-click Solution icon in Solution Explorer > Add > Existing Project... +- Add `node_modules\@react-native-community\progress-view\windows\progress-view\progress-view.vcxproj` +- If running RNW 0.62: add `node_modules\react-native-pdf\windows\RCTPdf\RCTPdf.vcxproj` +- Right-click main application project > Add > Reference... + - Select `progress-view` and in Solution Projects + - If running 0.62, also select `RCTPdf` +- In app `pch.h` add `#include "winrt/progress-view.h"` and `#include "winrt/RCTPdf.h"` +- In `App.cpp` add `PackageProviders().Append(winrt::progress-view::ReactPackageProvider());` before `InitializeComponent();` +- If running RNW 0.62, also add `PackageProviders().Append(winrt::RCTPdf::ReactPackageProvider());` + +#### Bundling PDFs with the app +To add a `test.pdf` like in the example add: +``` + + true + +``` +in the app `.vcxproj` file, before ``. +
+ ### FAQ
FAQ details @@ -270,55 +297,56 @@ const styles = StyleSheet.create({ ### Configuration -| Property | Type | Default | Description | iOS | Android | FirstRelease | -| ------------- |:-------------:|:----------------:| ------------------- | ------| ------- | ------------ | -| source | object | not null | PDF source like {uri:xxx, cache:false}. see the following for detail.| ✔ | ✔ | <3.0 | -| page | number | 1 | initial page index | ✔ | ✔ | <3.0 | -| scale | number | 1.0 | should minScale<=scale<=maxScale| ✔ | ✔ | <3.0 | -| minScale | number | 1.0 | min scale| ✔ | ✔ | 5.0.5 | -| maxScale | number | 3.0 | max scale| ✔ | ✔ | 5.0.5 | -| horizontal | bool | false | draw page direction, if you want to listen the orientation change, you can use [[react-native-orientation-locker]](https://github.com/wonday/react-native-orientation-locker)| ✔ | ✔ | <3.0 | -| fitWidth | bool | false | if true fit the width of view, can not use fitWidth=true together with scale| ✔ | ✔ | <3.0, abandoned from 3.0 | -| fitPolicy | number | 2 | 0:fit width, 1:fit height, 2:fit both(default)| ✔ | ✔ | 3.0 | -| spacing | number | 10 | the breaker size between pages| ✔ | ✔ | <3.0 | -| password | string | "" | pdf password, if password error, will call OnError() with message "Password required or incorrect password." | ✔ | ✔ | <3.0 | -| style | object | {backgroundColor:"#eee"} | support normal view style, you can use this to set border/spacing color... | ✔ | ✔ | <3.0 | -| activityIndicator | Component | | when loading show it as an indicator, you can use your component| ✔ | ✔ | <3.0 | -| activityIndicatorProps | object | {color:'#009900', progressTintColor:'#009900'} | activityIndicator props | ✔ | ✔ | 3.1 | -| enableAntialiasing | bool | true | improve rendering a little bit on low-res screens, but maybe course some problem on Android 4.4, so add a switch | ✖ | ✔ | <3.0 | -| enablePaging | bool | false | only show one page in screen | ✔ | ✔ | 5.0.1 | -| enableRTL | bool | false | scroll page as "page3, page2, page1" | ✔ | ✖ | 5.0.1 | -| enableAnnotationRendering | bool | true | enable rendering annotation, notice:iOS only support initial setting,not support realtime changing | ✔ | ✔ | 5.0.3 | -| trustAllCerts | bool | true | Allow connections to servers with self-signed certification | ✔ | ✔ | 6.0.? | -| singlePage | bool | false | Only show first page, useful for thumbnail views | ✔ | ✔ | 6.1.2 | -| onLoadProgress | function(percent) | null | callback when loading, return loading progress (0-1) | ✔ | ✔ | <3.0 | -| onLoadComplete | function(numberOfPages, path, {width, height}, tableContents) | null | callback when pdf load completed, return total page count, pdf local/cache path, {width,height} and table of contents | ✔ | ✔ | <3.0 | -| onPageChanged | function(page,numberOfPages) | null | callback when page changed ,return current page and total page count | ✔ | ✔ | <3.0 | -| onError | function(error) | null | callback when error happened | ✔ | ✔ | <3.0 | -| onPageSingleTap | function(page) | null | callback when page was single tapped | ✔ | ✔ | 3.0 | -| onScaleChanged | function(scale) | null | callback when scale page | ✔ | ✔ | 3.0 | -| onPressLink | function(uri) | null | callback when link tapped | ✔ | ✔ | 6.0.0 | +| Property | Type | Default | Description | iOS | Android | Windows | FirstRelease | +| ------------- |:-------------:|:----------------:| ------------------- | ------| ------- | ------- | ------------ | +| source | object | not null | PDF source like {uri:xxx, cache:false}. see the following for detail.| ✔ | ✔ | partial | <3.0 | +| page | number | 1 | initial page index | ✔ | ✔ | ✔ | <3.0 | +| scale | number | 1.0 | should minScale<=scale<=maxScale| ✔ | ✔ | ✔ | <3.0 | +| minScale | number | 1.0 | min scale| ✔ | ✔ | ✔ | 5.0.5 | +| maxScale | number | 3.0 | max scale| ✔ | ✔ | ✔ | 5.0.5 | +| horizontal | bool | false | draw page direction, if you want to listen the orientation change, you can use [[react-native-orientation-locker]](https://github.com/wonday/react-native-orientation-locker)| ✔ | ✔ | ✔ | <3.0 | +| fitWidth | bool | false | if true fit the width of view, can not use fitWidth=true together with scale| ✔ | ✔ | ✔ | <3.0, abandoned from 3.0 | +| fitPolicy | number | 2 | 0:fit width, 1:fit height, 2:fit both(default)| ✔ | ✔ | ✔ | 3.0 | +| spacing | number | 10 | the breaker size between pages| ✔ | ✔ | ✔ | <3.0 | +| password | string | "" | pdf password, if password error, will call OnError() with message "Password required or incorrect password." | ✔ | ✔ | ✔ | <3.0 | +| style | object | {backgroundColor:"#eee"} | support normal view style, you can use this to set border/spacing color... | ✔ | ✔ | ✖ | <3.0 | +| activityIndicator | Component | | when loading show it as an indicator, you can use your component| ✔ | ✔ | ✖ | <3.0 | +| activityIndicatorProps | object | {color:'#009900', progressTintColor:'#009900'} | activityIndicator props | ✔ | ✔ | ✖ | 3.1 | +| enableAntialiasing | bool | true | improve rendering a little bit on low-res screens, but maybe course some problem on Android 4.4, so add a switch | ✖ | ✔ | ✖ | <3.0 | +| enablePaging | bool | false | only show one page in screen | ✔ | ✔ | ✖ | 5.0.1 | +| enableRTL | bool | false | scroll page as "page3, page2, page1" | ✔ | ✖ | ✔ | 5.0.1 | +| enableAnnotationRendering | bool | true | enable rendering annotation, notice:iOS only support initial setting,not support realtime changing | ✔ | ✔ | ✖ | 5.0.3 | +| trustAllCerts | bool | true | Allow connections to servers with self-signed certification | ✔ | ✔ | ✖ | 6.0.? | +| singlePage | bool | false | Only show first page, useful for thumbnail views | ✔ | ✔ | ✔ | 6.1.2 | +| onLoadProgress | function(percent) | null | callback when loading, return loading progress (0-1) | ✔ | ✔ | ✖ | <3.0 | +| onLoadComplete | function(numberOfPages, path, {width, height}, tableContents) | null | callback when pdf load completed, return total page count, pdf local/cache path, {width,height} and table of contents | ✔ | ✔ | ✔ but without tableContents | <3.0 | +| onPageChanged | function(page,numberOfPages) | null | callback when page changed ,return current page and total page count | ✔ | ✔ | ✔ | <3.0 | +| onError | function(error) | null | callback when error happened | ✔ | ✔ | ✔ | <3.0 | +| onPageSingleTap | function(page) | null | callback when page was single tapped | ✔ | ✔ | ✖ | 3.0 | +| onScaleChanged | function(scale) | null | callback when scale page | ✔ | ✔ | ✔ | 3.0 | +| onPressLink | function(uri) | null | callback when link tapped | ✔ | ✔ | ✔ | 6.0.0 | #### parameters of source -| parameter | Description | default | iOS | Android | -| ------------ | ----------- | ------- | --- | ------- | -| uri | pdf source, see the forllowing for detail.| required | ✔ | ✔ | -| cache | use cache or not | false | ✔ | ✔ | -| expiration | cache file expired seconds (0 is not expired) | 0 | ✔ | ✔ | -| method | request method when uri is a url | "GET" | ✔ | ✔ | -| headers | request headers when uri is a url | {} | ✔ | ✔ | +| parameter | Description | default | iOS | Android | Windows | +| ------------ | ----------- | ------- | --- | ------- | ------- | +| uri | pdf source, see the forllowing for detail.| required | ✔ | ✔ | ✔ | +| cache | use cache or not | false | ✔ | ✔ | ✖ | +| expiration | cache file expired seconds (0 is not expired) | 0 | ✔ | ✔ | ✖ | +| method | request method when uri is a url | "GET" | ✔ | ✔ | ✖ | +| headers | request headers when uri is a url | {} | ✔ | ✔ | ✖ | #### types of source.uri -| Usage | Description | iOS | Android | -| ------------ | ----------- | --- | ------- | -| `{uri:"http://xxx/xxx.pdf"}` | load pdf from a url | ✔ | ✔ | -| `{require("./test.pdf")}` | load pdf relate to js file (do not need add by xcode) | ✔ | ✖ | -| `{uri:"bundle-assets://path/to/xxx.pdf"}` | load pdf from assets, the file should be at android/app/src/main/assets/path/to/xxx.pdf | ✖ | ✔ | -| `{uri:"bundle-assets://xxx.pdf"}` | load pdf from assets, you must add pdf to project by xcode. this does not support folder. | ✔ | ✖ | -| `{uri:"data:application/pdf;base64,JVBERi0xLjcKJc..."}` | load pdf from base64 string | ✔ | ✔ | -| `{uri:"file:///absolute/path/to/xxx.pdf"}` | load pdf from local file system | ✔ | ✔ | +| Usage | Description | iOS | Android | Windows | +| ------------ | ----------- | --- | ------- | ------- | +| `{uri:"http://xxx/xxx.pdf"}` | load pdf from a url | ✔ | ✔ | ✖ | +| `{require("./test.pdf")}` | load pdf relate to js file (do not need add by xcode) | ✔ | ✖ | ✖ | +| `{uri:"bundle-assets://path/to/xxx.pdf"}` | load pdf from assets, the file should be at android/app/src/main/assets/path/to/xxx.pdf | ✖ | ✔ | ✖ | +| `{uri:"bundle-assets://xxx.pdf"}` | load pdf from assets, you must add pdf to project by xcode. this does not support folder. | ✔ | ✖ | ✖ | +| `{uri:"data:application/pdf;base64,JVBERi0xLjcKJc..."}` | load pdf from base64 string | ✔ | ✔ | ✖ | +| `{uri:"file:///absolute/path/to/xxx.pdf"}` | load pdf from local file system | ✔ | ✔ | ✖ | +| `{uri: 'ms-appx:///xxx.pdf'}} | load pdf bundled with UWP app | ✖ | ✖ | ✔ | ### Methods diff --git a/example/.gitignore b/example/.gitignore index 828cc884..f3bcfdf4 100644 --- a/example/.gitignore +++ b/example/.gitignore @@ -57,3 +57,67 @@ buck-out/ # CocoaPods /ios/Pods/ + +# OSX +# +.DS_Store + +# Xcode +# +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata +*.xccheckout +*.moved-aside +DerivedData +*.hmap +*.ipa +*.xcuserstate + +# Android/IntelliJ +# +build/ +.idea +.gradle +local.properties +*.iml + +# node.js +# +node_modules/ +npm-debug.log +yarn-error.log + +# BUCK +buck-out/ +\.buckd/ +*.keystore +!debug.keystore + +# fastlane +# +# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +# screenshots whenever they are needed. +# For more information about the recommended setup visit: +# https://docs.fastlane.tools/best-practices/source-control/ + +*/fastlane/report.xml +*/fastlane/Preview.html +*/fastlane/screenshots + +# Bundle artifact +*.jsbundle + +# CocoaPods +/ios/Pods/ + +# VS +*.binlog +*.ProjectImports.zip diff --git a/example/PDFExample.js b/example/PDFExample.js index e9dc4048..d9ef4980 100644 --- a/example/PDFExample.js +++ b/example/PDFExample.js @@ -83,6 +83,7 @@ export default class PDFExample extends React.Component { render() { let source = {uri:'http://samples.leanpub.com/thereactnativebook-sample.pdf',cache:true}; + //let source = {uri: 'ms-appx:///test.pdf'} //let source = require('./test.pdf'); // ios only //let source = {uri:'bundle-assets://test.pdf'}; diff --git a/example/metro.config.js b/example/metro.config.js index 13a96421..1b710a4d 100644 --- a/example/metro.config.js +++ b/example/metro.config.js @@ -4,8 +4,20 @@ * * @format */ +const path = require('path'); +const blacklist = require('metro-config/src/defaults/blacklist'); module.exports = { + resolver: { + blacklistRE: blacklist([ + // This stops "react-native run-windows" from causing the metro server to crash if its already running + new RegExp( + `${path.resolve(__dirname, 'windows').replace(/[/\\]/g, '/')}.*`, + ), + // This prevents "react-native run-windows" from hitting: EBUSY: resource busy or locked, open msbuild.ProjectImports.zip + /.*\.ProjectImports\.zip/, + ]), + }, transformer: { getTransformOptions: async () => ({ transform: { diff --git a/example/package.json b/example/package.json index 0595815c..173c3b15 100644 --- a/example/package.json +++ b/example/package.json @@ -20,10 +20,11 @@ "url": "https://github.com/wonday/react-native-pdf/issues" }, "dependencies": { - "react": "16.8.6", - "react-native": "0.60.4", + "react": "16.13.1", + "react-native": "0.63.2", "react-native-orientation-locker": "^1.1.6", - "react-native-pdf": "github:wonday/react-native-pdf#master", + "react-native-pdf": "file:../", + "react-native-windows": "^0.63.11", "rn-fetch-blob": "^0.10.16" }, "devDependencies": { diff --git a/example/windows/.gitignore b/example/windows/.gitignore new file mode 100644 index 00000000..4ea0c7b5 --- /dev/null +++ b/example/windows/.gitignore @@ -0,0 +1,92 @@ +*AppPackages* +*BundleArtifacts* + +#OS junk files +[Tt]humbs.db +*.DS_Store + +#Visual Studio files +*.[Oo]bj +*.user +*.aps +*.pch +*.vspscc +*.vssscc +*_i.c +*_p.c +*.ncb +*.suo +*.tlb +*.tlh +*.bak +*.[Cc]ache +*.ilk +*.log +*.lib +*.sbr +*.sdf +*.opensdf +*.opendb +*.unsuccessfulbuild +ipch/ +[Oo]bj/ +[Bb]in +[Dd]ebug*/ +[Rr]elease*/ +Ankh.NoLoad + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +#MonoDevelop +*.pidb +*.userprefs + +#Tooling +_ReSharper*/ +*.resharper +[Tt]est[Rr]esult* +*.sass-cache + +#Project files +[Bb]uild/ + +#Subversion files +.svn + +# Office Temp Files +~$* + +# vim Temp Files +*~ + +#NuGet +packages/ +*.nupkg + +#ncrunch +*ncrunch* +*crunch*.local.xml + +# visual studio database projects +*.dbmdl + +#Test files +*.testsettings + +#Other files +*.DotSettings +.vs/ +*project.lock.json + +#Files generated by the VS build +**/Generated Files/** + diff --git a/example/windows/PDFExample.sln b/example/windows/PDFExample.sln new file mode 100644 index 00000000..4116b9d5 --- /dev/null +++ b/example/windows/PDFExample.sln @@ -0,0 +1,264 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29215.179 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "PDFExample", "PDFExample\PDFExample.vcxproj", "{95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}" + ProjectSection(ProjectDependencies) = postProject + {F7D32BD0-2749-483E-9A0D-1635EF7E3136} = {F7D32BD0-2749-483E-9A0D-1635EF7E3136} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Folly", "..\node_modules\react-native-windows\Folly\Folly.vcxproj", "{A990658C-CE31-4BCC-976F-0FC6B1AF693D}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ReactCommon", "..\node_modules\react-native-windows\ReactCommon\ReactCommon.vcxproj", "{A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}" + ProjectSection(ProjectDependencies) = postProject + {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {A990658C-CE31-4BCC-976F-0FC6B1AF693D} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Chakra", "..\node_modules\react-native-windows\Chakra\Chakra.vcxitems", "{C38970C0-5FBF-4D69-90D8-CBAC225AE895}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative", "..\node_modules\react-native-windows\Microsoft.ReactNative\Microsoft.ReactNative.vcxproj", "{F7D32BD0-2749-483E-9A0D-1635EF7E3136}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSI.Shared", "..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems", "{0CC28589-39E4-4288-B162-97B959F8B843}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JSI.Universal", "..\node_modules\react-native-windows\JSI\Universal\JSI.Universal.vcxproj", "{A62D504A-16B8-41D2-9F19-E2E86019E5E4}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Cxx", "..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems", "{DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Common", "..\node_modules\react-native-windows\Common\Common.vcxproj", "{FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "ReactNative", "ReactNative", "{5EA20F54-880A-49F3-99FA-4B3FE54E8AB1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Microsoft.ReactNative.Shared", "..\node_modules\react-native-windows\Shared\Shared.vcxitems", "{2049DBE9-8D13-42C9-AE4B-413AE38FFFD0}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Mso", "..\node_modules\react-native-windows\Mso\Mso.vcxitems", "{84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Include", "..\node_modules\react-native-windows\include\Include.vcxitems", "{EF074BA1-2D54-4D49-A28E-5E040B47CD2E}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.ReactNative.Managed", "..\node_modules\react-native-windows\Microsoft.ReactNative.Managed\Microsoft.ReactNative.Managed.csproj", "{F2824844-CE15-4242-9420-308923CD76C3}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.ReactNative.Managed.CodeGen", "..\node_modules\react-native-windows\Microsoft.ReactNative.Managed.CodeGen\Microsoft.ReactNative.Managed.CodeGen.csproj", "{ADED4FBE-887D-4271-AF24-F0823BCE7961}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RCTPdf", "..\node_modules\react-native-pdf\windows\RCTPdf\RCTPdf.vcxproj", "{03B8503F-F40D-4013-829C-71B304537D90}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "progress-view", "..\node_modules\@react-native-community\progress-view\windows\progress-view\progress-view.vcxproj", "{CA54A654-5E81-44DC-AF3F-CF55EF5B493A}" +EndProject +Global + GlobalSection(SharedMSBuildProjectFiles) = preSolution + ..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems*{0cc28589-39e4-4288-b162-97b959f8b843}*SharedItemsImports = 9 + ..\node_modules\react-native-windows\Shared\Shared.vcxitems*{2049dbe9-8d13-42c9-ae4b-413ae38fffd0}*SharedItemsImports = 9 + ..\node_modules\react-native-windows\Mso\Mso.vcxitems*{84e05bfa-cbaf-4f0d-bfb6-4ce85742a57e}*SharedItemsImports = 9 + ..\node_modules\react-native-windows\JSI\Shared\JSI.Shared.vcxitems*{a62d504a-16b8-41d2-9f19-e2e86019e5e4}*SharedItemsImports = 4 + ..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{c38970c0-5fbf-4d69-90d8-cbac225ae895}*SharedItemsImports = 9 + ..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{ca54a654-5e81-44dc-af3f-cf55ef5b493a}*SharedItemsImports = 4 + ..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{da8b35b3-da00-4b02-bde6-6a397b3fd46b}*SharedItemsImports = 9 + ..\node_modules\react-native-windows\include\Include.vcxitems*{ef074ba1-2d54-4d49-a28e-5e040b47cd2e}*SharedItemsImports = 9 + ..\node_modules\react-native-windows\Chakra\Chakra.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 + ..\node_modules\react-native-windows\Microsoft.ReactNative.Cxx\Microsoft.ReactNative.Cxx.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 + ..\node_modules\react-native-windows\Mso\Mso.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 + ..\node_modules\react-native-windows\Shared\Shared.vcxitems*{f7d32bd0-2749-483e-9a0d-1635ef7e3136}*SharedItemsImports = 4 + EndGlobalSection + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|ARM = Debug|ARM + Debug|ARM64 = Debug|ARM64 + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 + Release|ARM = Release|ARM + Release|ARM64 = Release|ARM64 + Release|x64 = Release|x64 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Debug|ARM.ActiveCfg = Debug|ARM + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Debug|ARM.Build.0 = Debug|ARM + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Debug|ARM.Deploy.0 = Debug|ARM + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Debug|ARM64.Build.0 = Debug|ARM64 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Debug|ARM64.Deploy.0 = Debug|ARM64 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Debug|x64.ActiveCfg = Debug|x64 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Debug|x64.Build.0 = Debug|x64 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Debug|x64.Deploy.0 = Debug|x64 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Debug|x86.ActiveCfg = Debug|Win32 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Debug|x86.Build.0 = Debug|Win32 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Debug|x86.Deploy.0 = Debug|Win32 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Release|ARM.ActiveCfg = Release|ARM + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Release|ARM.Build.0 = Release|ARM + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Release|ARM.Deploy.0 = Release|ARM + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Release|ARM64.ActiveCfg = Release|ARM64 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Release|ARM64.Build.0 = Release|ARM64 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Release|ARM64.Deploy.0 = Release|ARM64 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Release|x64.ActiveCfg = Release|x64 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Release|x64.Build.0 = Release|x64 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Release|x64.Deploy.0 = Release|x64 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Release|x86.ActiveCfg = Release|Win32 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Release|x86.Build.0 = Release|Win32 + {95F9323C-1039-4B6A-B69E-A9EFDDFEFB54}.Release|x86.Deploy.0 = Release|Win32 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM.ActiveCfg = Debug|ARM + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM.Build.0 = Debug|ARM + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|ARM64.Build.0 = Debug|ARM64 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x64.ActiveCfg = Debug|x64 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x64.Build.0 = Debug|x64 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x86.ActiveCfg = Debug|Win32 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Debug|x86.Build.0 = Debug|Win32 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM.ActiveCfg = Release|ARM + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM.Build.0 = Release|ARM + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM64.ActiveCfg = Release|ARM64 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|ARM64.Build.0 = Release|ARM64 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x64.ActiveCfg = Release|x64 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x64.Build.0 = Release|x64 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.ActiveCfg = Release|Win32 + {A990658C-CE31-4BCC-976F-0FC6B1AF693D}.Release|x86.Build.0 = Release|Win32 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM.ActiveCfg = Debug|ARM + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM.Build.0 = Debug|ARM + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|ARM64.Build.0 = Debug|ARM64 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x64.ActiveCfg = Debug|x64 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x64.Build.0 = Debug|x64 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x86.ActiveCfg = Debug|Win32 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Debug|x86.Build.0 = Debug|Win32 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM.ActiveCfg = Release|ARM + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM.Build.0 = Release|ARM + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM64.ActiveCfg = Release|ARM64 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|ARM64.Build.0 = Release|ARM64 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x64.ActiveCfg = Release|x64 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x64.Build.0 = Release|x64 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.ActiveCfg = Release|Win32 + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD}.Release|x86.Build.0 = Release|Win32 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM.ActiveCfg = Debug|ARM + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM.Build.0 = Debug|ARM + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|ARM64.Build.0 = Debug|ARM64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x64.ActiveCfg = Debug|x64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x64.Build.0 = Debug|x64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x86.ActiveCfg = Debug|Win32 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Debug|x86.Build.0 = Debug|Win32 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM.ActiveCfg = Release|ARM + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM.Build.0 = Release|ARM + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM64.ActiveCfg = Release|ARM64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|ARM64.Build.0 = Release|ARM64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.ActiveCfg = Release|x64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x64.Build.0 = Release|x64 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.ActiveCfg = Release|Win32 + {F7D32BD0-2749-483E-9A0D-1635EF7E3136}.Release|x86.Build.0 = Release|Win32 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM.ActiveCfg = Debug|ARM + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM.Build.0 = Debug|ARM + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|ARM64.Build.0 = Debug|ARM64 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x64.ActiveCfg = Debug|x64 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x64.Build.0 = Debug|x64 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x86.ActiveCfg = Debug|Win32 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Debug|x86.Build.0 = Debug|Win32 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM.ActiveCfg = Release|ARM + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM.Build.0 = Release|ARM + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM64.ActiveCfg = Release|ARM64 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|ARM64.Build.0 = Release|ARM64 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x64.ActiveCfg = Release|x64 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x64.Build.0 = Release|x64 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x86.ActiveCfg = Release|Win32 + {A62D504A-16B8-41D2-9F19-E2E86019E5E4}.Release|x86.Build.0 = Release|Win32 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM.ActiveCfg = Debug|ARM + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM.Build.0 = Debug|ARM + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|ARM64.Build.0 = Debug|ARM64 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x64.ActiveCfg = Debug|x64 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x64.Build.0 = Debug|x64 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x86.ActiveCfg = Debug|Win32 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Debug|x86.Build.0 = Debug|Win32 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM.ActiveCfg = Release|ARM + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM.Build.0 = Release|ARM + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM64.ActiveCfg = Release|ARM64 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|ARM64.Build.0 = Release|ARM64 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x64.ActiveCfg = Release|x64 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x64.Build.0 = Release|x64 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.ActiveCfg = Release|Win32 + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D}.Release|x86.Build.0 = Release|Win32 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.ActiveCfg = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM.Build.0 = Debug|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|ARM64.Build.0 = Debug|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.ActiveCfg = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x64.Build.0 = Debug|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.ActiveCfg = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Debug|x86.Build.0 = Debug|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.ActiveCfg = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM.Build.0 = Release|ARM + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.ActiveCfg = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|ARM64.Build.0 = Release|ARM64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.ActiveCfg = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x64.Build.0 = Release|x64 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.ActiveCfg = Release|x86 + {F2824844-CE15-4242-9420-308923CD76C3}.Release|x86.Build.0 = Release|x86 + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Debug|ARM.ActiveCfg = Debug|ARM + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Debug|ARM.Build.0 = Debug|ARM + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Debug|ARM64.Build.0 = Debug|ARM64 + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Debug|x64.ActiveCfg = Debug|x64 + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Debug|x64.Build.0 = Debug|x64 + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Debug|x86.ActiveCfg = Debug|x86 + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Debug|x86.Build.0 = Debug|x86 + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Release|ARM.ActiveCfg = Release|ARM + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Release|ARM.Build.0 = Release|ARM + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Release|ARM64.ActiveCfg = Release|ARM64 + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Release|ARM64.Build.0 = Release|ARM64 + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Release|x64.ActiveCfg = Release|x64 + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Release|x64.Build.0 = Release|x64 + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Release|x86.ActiveCfg = Release|x86 + {ADED4FBE-887D-4271-AF24-F0823BCE7961}.Release|x86.Build.0 = Release|x86 + {03B8503F-F40D-4013-829C-71B304537D90}.Debug|ARM.ActiveCfg = Debug|ARM + {03B8503F-F40D-4013-829C-71B304537D90}.Debug|ARM.Build.0 = Debug|ARM + {03B8503F-F40D-4013-829C-71B304537D90}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {03B8503F-F40D-4013-829C-71B304537D90}.Debug|ARM64.Build.0 = Debug|ARM64 + {03B8503F-F40D-4013-829C-71B304537D90}.Debug|x64.ActiveCfg = Debug|x64 + {03B8503F-F40D-4013-829C-71B304537D90}.Debug|x64.Build.0 = Debug|x64 + {03B8503F-F40D-4013-829C-71B304537D90}.Debug|x86.ActiveCfg = Debug|Win32 + {03B8503F-F40D-4013-829C-71B304537D90}.Debug|x86.Build.0 = Debug|Win32 + {03B8503F-F40D-4013-829C-71B304537D90}.Release|ARM.ActiveCfg = Release|ARM + {03B8503F-F40D-4013-829C-71B304537D90}.Release|ARM.Build.0 = Release|ARM + {03B8503F-F40D-4013-829C-71B304537D90}.Release|ARM64.ActiveCfg = Release|ARM64 + {03B8503F-F40D-4013-829C-71B304537D90}.Release|ARM64.Build.0 = Release|ARM64 + {03B8503F-F40D-4013-829C-71B304537D90}.Release|x64.ActiveCfg = Release|x64 + {03B8503F-F40D-4013-829C-71B304537D90}.Release|x64.Build.0 = Release|x64 + {03B8503F-F40D-4013-829C-71B304537D90}.Release|x86.ActiveCfg = Release|Win32 + {03B8503F-F40D-4013-829C-71B304537D90}.Release|x86.Build.0 = Release|Win32 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Debug|ARM.ActiveCfg = Debug|ARM + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Debug|ARM.Build.0 = Debug|ARM + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Debug|ARM64.ActiveCfg = Debug|ARM64 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Debug|ARM64.Build.0 = Debug|ARM64 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Debug|x64.ActiveCfg = Debug|x64 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Debug|x64.Build.0 = Debug|x64 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Debug|x86.ActiveCfg = Debug|Win32 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Debug|x86.Build.0 = Debug|Win32 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Debug|x86.Deploy.0 = Debug|Win32 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Release|ARM.ActiveCfg = Release|ARM + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Release|ARM.Build.0 = Release|ARM + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Release|ARM64.ActiveCfg = Release|ARM64 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Release|ARM64.Build.0 = Release|ARM64 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Release|x64.ActiveCfg = Release|x64 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Release|x64.Build.0 = Release|x64 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Release|x86.ActiveCfg = Release|Win32 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Release|x86.Build.0 = Release|Win32 + {CA54A654-5E81-44DC-AF3F-CF55EF5B493A}.Release|x86.Deploy.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {A990658C-CE31-4BCC-976F-0FC6B1AF693D} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {A9D95A91-4DB7-4F72-BEB6-FE8A5C89BFBD} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {C38970C0-5FBF-4D69-90D8-CBAC225AE895} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {F7D32BD0-2749-483E-9A0D-1635EF7E3136} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {0CC28589-39E4-4288-B162-97B959F8B843} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {A62D504A-16B8-41D2-9F19-E2E86019E5E4} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {DA8B35B3-DA00-4B02-BDE6-6A397B3FD46B} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {FCA38F3C-7C73-4C47-BE4E-32F77FA8538D} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {2049DBE9-8D13-42C9-AE4B-413AE38FFFD0} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {84E05BFA-CBAF-4F0D-BFB6-4CE85742A57E} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {EF074BA1-2D54-4D49-A28E-5E040B47CD2E} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {F2824844-CE15-4242-9420-308923CD76C3} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + {ADED4FBE-887D-4271-AF24-F0823BCE7961} = {5EA20F54-880A-49F3-99FA-4B3FE54E8AB1} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {D43FAD39-F619-437D-BB40-04A3982ACB6A} + EndGlobalSection +EndGlobal diff --git a/example/windows/PDFExample/.gitignore b/example/windows/PDFExample/.gitignore new file mode 100644 index 00000000..917243bd --- /dev/null +++ b/example/windows/PDFExample/.gitignore @@ -0,0 +1 @@ +/Bundle diff --git a/example/windows/PDFExample/App.cpp b/example/windows/PDFExample/App.cpp new file mode 100644 index 00000000..d21b7c72 --- /dev/null +++ b/example/windows/PDFExample/App.cpp @@ -0,0 +1,80 @@ +#include "pch.h" + +#include "App.h" + +#include "AutolinkedNativeModules.g.h" +#include "ReactPackageProvider.h" + + +using namespace winrt::PDFExample; +using namespace winrt::PDFExample::implementation; +using namespace winrt; +using namespace Windows::UI::Xaml; +using namespace Windows::UI::Xaml::Controls; +using namespace Windows::UI::Xaml::Navigation; +using namespace Windows::ApplicationModel; + +/// +/// 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(). +/// +App::App() noexcept +{ +#if BUNDLE + JavaScriptBundleFile(L"index.windows"); + InstanceSettings().UseWebDebugger(false); + InstanceSettings().UseFastRefresh(false); +#else + JavaScriptMainModuleName(L"index"); + InstanceSettings().UseWebDebugger(true); + InstanceSettings().UseFastRefresh(true); +#endif + +#if _DEBUG + InstanceSettings().UseDeveloperSupport(true); +#else + InstanceSettings().UseDeveloperSupport(false); +#endif + + RegisterAutolinkedNativeModulePackages(PackageProviders()); // Includes any autolinked modules + + PackageProviders().Append(make()); // Includes all modules in this project + PackageProviders().Append(winrt::progress_view::ReactPackageProvider()); + InitializeComponent(); +} + +/// +/// 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. +void App::OnLaunched(activation::LaunchActivatedEventArgs const& e) +{ + super::OnLaunched(e); + + Frame rootFrame = Window::Current().Content().as(); + rootFrame.Navigate(xaml_typename(), box_value(e.Arguments())); +} + +/// +/// 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. +void App::OnSuspending([[maybe_unused]] IInspectable const& sender, [[maybe_unused]] SuspendingEventArgs const& e) +{ + // Save application state and stop any background activity +} + +/// +/// Invoked when Navigation to a certain page fails +/// +/// The Frame which failed navigation +/// Details about the navigation failure +void App::OnNavigationFailed(IInspectable const&, NavigationFailedEventArgs const& e) +{ + throw hresult_error(E_FAIL, hstring(L"Failed to load Page ") + e.SourcePageType().Name); +} diff --git a/example/windows/PDFExample/App.h b/example/windows/PDFExample/App.h new file mode 100644 index 00000000..e94396f5 --- /dev/null +++ b/example/windows/PDFExample/App.h @@ -0,0 +1,20 @@ +#pragma once + +#include "App.xaml.g.h" + +namespace activation = winrt::Windows::ApplicationModel::Activation; + +namespace winrt::PDFExample::implementation +{ + struct App : AppT + { + App() noexcept; + void OnLaunched(activation::LaunchActivatedEventArgs const&); + void OnSuspending(IInspectable const&, Windows::ApplicationModel::SuspendingEventArgs const&); + void OnNavigationFailed(IInspectable const&, Windows::UI::Xaml::Navigation::NavigationFailedEventArgs const&); + private: + using super = AppT; + }; +} // namespace winrt::PDFExample::implementation + + diff --git a/example/windows/PDFExample/App.idl b/example/windows/PDFExample/App.idl new file mode 100644 index 00000000..0c75a56d --- /dev/null +++ b/example/windows/PDFExample/App.idl @@ -0,0 +1,3 @@ +namespace PDFExample +{ +} diff --git a/example/windows/PDFExample/App.xaml b/example/windows/PDFExample/App.xaml new file mode 100644 index 00000000..5117f6f4 --- /dev/null +++ b/example/windows/PDFExample/App.xaml @@ -0,0 +1,10 @@ + + + + + diff --git a/example/windows/PDFExample/Assets/LockScreenLogo.scale-200.png b/example/windows/PDFExample/Assets/LockScreenLogo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..735f57adb5dfc01886d137b4e493d7e97cf13af3 GIT binary patch literal 1430 zcmaJ>TTC2P7~aKltDttVHYH6u8Io4i*}3fO&d$gd*bA_<3j~&e7%8(eXJLfhS!M@! zKrliY>>6yT4+Kr95$!DoD(Qn-5TP|{V_KS`k~E6(LGS@#`v$hQo&^^BKsw3HIsZBT z_y6C2n`lK@apunKojRQ^(_P}Mgewt$(^BBKCTZ;*xa?J3wQ7~@S0lUvbcLeq1Bg4o zH-bvQi|wt~L7q$~a-gDFP!{&TQfc3fX*6=uHv* zT&1&U(-)L%Xp^djI2?~eBF2cxC@YOP$+9d?P&h?lPy-9M2UT9fg5jKm1t$m#iWE{M zIf%q9@;fyT?0UP>tcw-bLkz;s2LlKl2qeP0w zECS7Ate+Awk|KQ+DOk;fl}Xsy4o^CY=pwq%QAAKKl628_yNPsK>?A>%D8fQG6IgdJ ztnxttBz#NI_a@fk7SU`WtrpsfZsNs9^0(2a z@C3#YO3>k~w7?2hipBf{#b6`}Xw1hlG$yi?;1dDs7k~xDAw@jiI*+tc;t2Lflg&bM)0!Y;0_@=w%`LW^8DsYpS#-bLOklX9r?Ei}TScw|4DbpW%+7 zFgAI)f51s}{y-eWb|vrU-Ya!GuYKP)J7z#*V_k^Xo>4!1Yqj*m)x&0L^tg3GJbVAJ zJ-Pl$R=NAabouV=^z_t;^K*0AvFs!vYU>_<|I^#c?>>CR<(T?=%{;U=aI*SbZADLH z&(f2wz_Y0??Tf|g;?|1Znw6}6U43Q#qNRwv1vp9uFn1)V#*4p&%$mP9x&15^OaBiDS(XppT|z^>;B{PLVEbS3IFYV yGvCsSX*m literal 0 HcmV?d00001 diff --git a/example/windows/PDFExample/Assets/SplashScreen.scale-200.png b/example/windows/PDFExample/Assets/SplashScreen.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..023e7f1feda78d5100569825acedfd213a0d84e9 GIT binary patch literal 7700 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 literal 0 HcmV?d00001 diff --git a/example/windows/PDFExample/Assets/Square150x150Logo.scale-200.png b/example/windows/PDFExample/Assets/Square150x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..af49fec1a5484db1d52a7f9b5ec90a27c7030186 GIT binary patch literal 2937 zcma)84OCO-8BSud5)jwMLRVKgX(S?$n?Ld|vrsm<$CF7)&zTbyy1FE5bU`Q17MRv`9ue$;R(@8kR;#vJ*IM0>cJIAOte!d7oRgdH zd%ySjdB6L9=gX^A6)VzH7p2l@v~3zJAMw|DFy#^)F@@F*`mqUn=Il>l)8_+ab;nOW{%+iPx z+s{Eu|&pIs)Z7{La9~?xKfyl z#43?gjEL15d4WbOZo#SiP%>DB^+BcnJ=7dHEe;r#G=tuw|ka z%q@}##Uh7;tc%L_64m(kHtw74ty%BJMb)_1)#S0j`)F8_1jF7vScpsnH=0V19bO8y zR`0SjIdCUo&=>JwMQF8KHA<{ODHTiQh}0^@5QRmCA?gOH6_H3K^-_sNB^RrdNuK-R zOO*vOrKCVvDwgUck`kF(E7j{I#iiN;b*ZdCt4m@HPA`EuEqGGf4%!K<;(=I=&Vyrw z%TwcWtxa}8mCZ%Cyf&ActJ6_$ox5z6-D!0-dvnRx6t7y3d+h6QYpKWO;8OdnvERo7 zuEf>ih5`wqY)~o@OeVt-wM?Q!>QzdGRj!bz6fzYrfw$hZfAKzr2-M+D+R>}~oT574c;_3zquHcElqKIsryILt3g8n3jcMb+j?i?-L3FpZJ z2WRVBRdDPc+G5aaYg#5hpE+6nQ|(VSoxT3|biF;BUq#==-27Xi=gihDPYP$7?=9cP zYKE$jeQ|3~_L0VG-(F~2ZPyD0=k{J4Q~h(t__{-mz_w8{JDY9{`1ouzz!Vr5!ECdE z6U~O1k8c}24V7~zzXWTV-Pe4)y}wQJS&q%H5`Fo_f_JvIU489aCX$;P`u#!I-=^4ijC2{&9!O&h>mi?9oYD=GC#%)6{GzN6nQYw+Fal50!#x^asjBBR50i`+mho*ttoqV)ubM2KD9S~k7+FR4>{29?6 z{!l6kDdyTN0YJ9LgkPWeXm|gyi@zM3?0@{&pXT12w|78&W-q!RRF)&iLCEZVH<|fR zN0fr2^t8H(>L?>K#>^+jWROLral(Qy-xoBq1U7A&DV||wClb)Otd9?(gZ|8znMF}D zf<1haWz^s0qgecz;RFGt0C-B4g`jNGHsFU+;{<%t65v^sjk^h$lmWn#B0#_)9ij&d z-~lc`A)YYExi^7sBuPM^Y|wA2g*5?`K?#7tzELQYNxGo$UB$4J8RJp1k(8Jj+~hMT zlN~>M@KTTh^--8y3PK_NZ@AC!{PT=CziBzGd+wTJ^@icH!Bd}%)g8V)%K?|c&WTUk zy}qv1C%(fjRoZ4ozC3{O%@5?)XzH35zHns$pgU*Q?fj4v?fp1Qbm+j;3l;9jam9Da zXVcKjPlQ73x78QPu|Ffm6x?`~e3oD=gl=4kYK?={kD5j~QCXU)`HSdduNNENzA*2$ zOm3PzF!lN5e*06-f1Uot67wY#{o-S1!KZ7E=!~7ynnk9_iJR#kFoNbAOT#^2Gd17F zMmvU6>lndZQGd|ax9kUoXXO+$N?|j@6qpsF&_j7YXvwo_C{JpmLw5&#e6k>atv%es z5)7r*Wvv_JkUpT}M!_o!nVlEk1Zbl=a*2hQ*<|%*K1Glj^FcF`6kTzGQ3lz~2tCc@ z&x|tj;aH&1&9HwcJBcT`;{?a+pnej;M1HO(6Z{#J!cZA04hnFl;NXA+&`=7bjW_^o zfC40u3LMG?NdPtwGl>Tq6u}*QG)}-y;)lu-_>ee3kibW(69n0$0Zy!}9rQz%*v1iO zT9_H>99yIrSPYVy6^);rR}7Yo=J_T@hi+qhTZXnVWyf;JDYm5#eYLTxr*?kiNn!+Y zQ+LUkBafNJ#rH#C(?d5^;gw9o#%daEI{mA*LHPIHPU`#|H$hD zwm>0&+kahQ)E#%~k>&5@&#Vg82H?s%71=)(soi@174pi9--2{w{1$}Sz4zGn3Du&x bht0Iza^2ykEt4(epJ78uh5nDlX8(TxzDYwP literal 0 HcmV?d00001 diff --git a/example/windows/PDFExample/Assets/Square44x44Logo.scale-200.png b/example/windows/PDFExample/Assets/Square44x44Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..ce342a2ec8a61291ba76c54604aea7e9d20af11b GIT binary patch literal 1647 zcmaJ?eM}Q)7(e+G1Q(|`V9JhTI2>MkceK4;p;PR&$Pi?ejk3YQ_3o`S&|W_dsOZ8# zWPTt69g`t$ab`0cj-Y0yiBSOqmd)tG7G(}M5aP0_%&9TijB#&)I{zSE^4@#z^FF`l z`8{8`o%wlL(UI|y2!cdsuVamHH~H86F!*-15em4)NqUpCQM5?aoC_eCf@lV4wvF2a zjDQn1JBL69f&@2M3rvzJcfE!eZ8FZUBlFlC5RD)it33{mF9#B82AiyQE%w)`vlwa> zv{<1sm&kSKK$&%2jSFn7$t&P%%6Ue>R=EAnG8N7fqynWG8L3p!4801a;8{+nliO(qd(jNJ_?+9W3#hLIDLoT6~3fx9=`CC-D}-AMrpEO7HK zt3$GicGPc?GmDjy7K2P@La;eu4!$zWCZ`ym{Z$b zu-O6RM&K4JT|BIZB`E-gxqG%FzanI#+2FFmqHqXG7yxWB=w55RGOM)$xMb(>kSNR z2w=1AZi%z=AmG~yea~XaXJR!v7vLn(RUnELfiB1|6D84ICOS}^Zo2AdN}<&*h}G_u z{xZ!(%>tLT3J3<5XhWy-tg+6)0nmUUENLW8TWA{R6bgVd3X;anYFZ^IRis*_P-C-r z;i>%1^eL3UI2-{w8nuFFcs0e~7J{O2k^~Ce%+Ly4U?|=!0LH=t6()xi<^I-rs+9sF z*q{E-CxZbGPeu#a;XJwE;9S1?#R&uns>^0G3p`hEUF*v`M?@h%T%J%RChmD|EVydq zmHWh*_=S%emRC*mhxaVLzT@>Z2SX0u9v*DIJ@WC^kLVdlGV6LpK$KIrlJqc zpJ921)+3JJdTx|<`G&kXpKkjGJv=76R`yYIQ{#c-`%+`#V(7}Q;&@6U8!Td1`d;?N z_9mnI#?AA}4J!r)LN4!E-@H5eXauuB7TOawS>Y|{-P?NNx-lq+z1W-+y(;39P&&LP zL{N80?&=C*qKmdA^moMZRuPcD!B<*mq$ch=0Cnlitw#txRWhb3%TQvPqjkC`F69G4b! ze7z9MZ#+;_#l?H37UqUhDFb^l&s2{oM$3I0o^Q!yx;;V)QmCMo)Tb_ui|mit8MS?U zm##6$sZZ1$@|s%?l@>4Z<*Q}sRBSKMhb4I{e5LdEhsHIHTe8Bod5c>6QtT>$XgUBz z6MK`kO$=jmt@FqggOhJ5j~e@ygRbG;<{Vu)*+nn9aQeo0;$#j;|MS=S$&L?BeV25z xs3B`@=#`5TF{^6(A1rvdY@|-RtQ|iS5{tyX+wH?;n8E)G$kykv-D^wh{{!TZT%7;_ literal 0 HcmV?d00001 diff --git a/example/windows/PDFExample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png b/example/windows/PDFExample/Assets/Square44x44Logo.targetsize-24_altform-unplated.png new file mode 100644 index 0000000000000000000000000000000000000000..f6c02ce97e0a802b85f6021e822c89f8bf57d5cd GIT binary patch literal 1255 zcmaJ>TWs4@7*5+{G#S+&C!qC#> zf>5N3P6jO*Cz>ug*(_DmW=)kea&m$gZ^+nyiF`;j%w@}y8)>p*SH}C`m?DXeieF2U zyQHecc_L%Gh!7GMt+hG06y;+|p4>m~}PjA}rKViGiEnn7G0ZO<>G|7q;2?NwGCM3s?eued6%hd$B+ z*kQJ{#~$S=DFE(%=E+UkmlEI*%3llUf~8Ja9YU1Vui0IbGBkW_gHB%Rd&!!ioX zs40O?i9I{};kle7GMvE7(rk`la=gTI)47=>%?q@^iL-nUo3}h4S}N-KHn8t5mVP8w z&bSErwp+37 zNJJ8?a|{r5Q3R0Z5s-LB1WHOwYC@7pCHWND#cL1cZ?{kJ368_*(UDWUDyb<}0y@o# zfMF016iMWPCb6obAxT$JlB6(2DrlXDTB&!0`!m??4F(qWMhjVZo?JXQmz`1*58Z=& zcDmB|S-E@j?BoFGix0flckqdS4jsPNzhfWyWIM98GxcLs89C(~dw%$_t;JjX-SD}E zfiGV;{8Q%8r}w9x>EEigW81>`kvnU@pK)4+xk9@+bNj9L!AAZ@SZ@q|)&BmY3+HZx zul~BeG4|}-;L%cHViQGQX?^zFfO0&#cHwel=d`lH9sJ-@Sl@n*(8J2>%Ac`IxyY?Q z{=GhWvC#gu-~Ia7*n{=+;qM?Ul_wy1+u7ho;=`>EwP^g~R@{unBds`!#@}tluZQpS zm)M~nYEifJWJGx?_6DcTy>#uh%>!H9=hb^(v`=m3F1{L>db=<5_tm+_&knAQ2EU$s Mu9UqpbNZeC0BbUo^Z)<= literal 0 HcmV?d00001 diff --git a/example/windows/PDFExample/Assets/StoreLogo.png b/example/windows/PDFExample/Assets/StoreLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..7385b56c0e4d3c6b0efe3324aa1194157d837826 GIT binary patch literal 1451 zcmaJ>eN5D57_Z|bH;{0+1#mbl)eTU3{h)Wf7EZV?;HD@XL@{B`Ui%(2aMxQ~xdXSv z5nzWi(LW)U2=Vc-cY@s7nPt{i0hc6!7xN4NNHI#EQl>YNBy8l4%x9gr_W-j zEZMQmmTIy(>;lblRfh`dIyTgc9W5d!VP$L4(kKrN1c5G~(O_#xG zAJCNTstD^5SeXFB+&$h=ToJP2H>xr$iqPs-#O*;4(!Fjw25-!gEb*)mU}=)J;Iu>w zxK(5XoD0wrPSKQ~rbL^Cw6O_03*l*}i=ydbu7adJ6y;%@tjFeXIXT+ms30pmbOP%Q zX}S;+LBh8Tea~TSkHzvX6$rYb)+n&{kSbIqh|c7hmlxmwSiq5iVhU#iEQ<>a18|O^Sln-8t&+t`*{qBWo5M?wFM(JuimAOb5!K#D}XbslM@#1ZVz_;!9U zpfEpLAOz=0g@bd6Xj_ILi-x^!M}73h^o@}hM$1jflTs|Yuj9AL@A3<-?MV4!^4q`e z)fO@A;{9K^?W?DbnesnPr6kK>$zaKo&;FhFd(GYFCIU^T+OIMb%Tqo+P%oq(IdX7S zf6+HLO?7o0m+p>~Tp5UrXWh!UH!wZ5kv!E`_w)PTpI(#Iw{AS`gH4^b(bm^ZCq^FZ zY9DD7bH}rq9mg88+KgA$Zp!iWncuU2n1AuIa@=sWvUR-s`Qb{R*kk(SPU^`$6BXz8 zn#7yaFOIK%qGxyi`dYtm#&qqox0$h=pNi#u=M8zUG@bpiZ=3sT=1}Trr}39cC)H|v zbL?W)=&s4zrh)7>L(|cc%$1#!zfL?HjpeP%T+x_a+jZ16b^iKOHxFEX$7d|8${H-* zIrOJ5w&i$>*D>AKaIoYg`;{L@jM((Kt?$N$5OnuPqVvq**Nm}(f0wwOF%iX_Pba;V z;m@wxX&NcV3?<1+u?A{y_DIj7#m3Af1rCE)o`D&Y3}0%7E;iX1yMDiS)sh0wKi!36 zL!Wmq?P^Ku&rK~HJd97KkLTRl>ScGFYZNlYytWnhmuu|)L&ND8_PmkayQb{HOY640 bno1(wj@u8DCVuFR|31B*4ek@pZJqxCDDe1x literal 0 HcmV?d00001 diff --git a/example/windows/PDFExample/Assets/Wide310x150Logo.scale-200.png b/example/windows/PDFExample/Assets/Wide310x150Logo.scale-200.png new file mode 100644 index 0000000000000000000000000000000000000000..288995b397fdbef1fb7e85afd71445d5de1952c5 GIT binary patch literal 3204 zcmbVPeQXow8NYmBd90>}0NP?GhXW~VaeThm=a0tV#EwJMI!)6M3}|c4_Bl3=Kd>G0 z(GHx1wl<7(tP?FsOQkTilSo*iIvF%uArExJ73~P zSv1xEy!U(Wd4A9D`FQV@W3@F^qJ@PEF$@z`Z!*BbFsS(^?B zyiAzJ+q})bkgiQHWqEb*jJD-coHYr1^iocg)l!Qa{Xqs-l~6J}p-|##ZHYofskQ3$ zI0;xzXyhazBeXhIsg5A=%ufo@f)1yy&ScKS0;HF^!r_2UE^lpZEom(+@duma3awTv zCrCL-%D_SvYWIcdHkmI}#50(fkUi)Qgx!80ju>g1za^}ff>JI8Z@^-iCiaCgg@TgF z+vtE?Q9{VQUX&MW9SYYmGcxA14%N2@7FwBTD4N<(2{nWgV8$e3?-F=L^&FrtWn~(U_Q~~^uYiyeY6-KoTnfh9AWz@ zIKje0)u!_Lw)E}G!#kEfwKVdNt(UAf9*f>tEL_(=xco-T%jTi@7YlC3hs2ik%Le0H ztj}RTeCF(5mwvi3_56>-yB?l;J>-1%!9~=fs|QcNG3J~a@JCu`4SB460s0ZO+##4fFUSGLcj_ja^fL4&BKALfb#$6$O?>P@qx2Agl^x0i&ugt zsy5Pyu=()`7HRMG3IB7F1@`_ z+-!J%#i6e^U$e#+C%Q>_qVRzWRsG^W_n+@OcX@vzI&z;mzHNb!GQ?LWA(wtpqHqTM z1OFw_{Zn?fD)p)`c`kOgv{de=v@suGRqY{N^U7gI1VF3*F=obwaXI6ob5__Yn zVTguS!%(NI09J8x#AO_aW!9W7k*UvB;IWDFC3srwftr{kHj%g)fvnAm;&h_dnl~

MY- zf+K}sCe8qU6Ujs`3ua{U0Of$R_gVQBuUA za0v=mu#vIOqiiAZOr&h*$WyOw&k-xr$;G4Ixa!#TJNr>95(h>l%)PUy4p+^SgR(uR zta%k*?ny-+nAr8spEk1fo{J4i!b^Fia`N{_F6@zidA2ZTTrjl#^5Z-2KfB@Cu}l9s z(*|Z2jc?p~vn2f)3y9i*7zJV1L{$?|&q)4oaT;uXi6>1GkRXVTOzAz(RHEmr=eFIi z`}<>-Q?K0GN8!IYxeP1XKXO+jsJbp~o^);Bc;%b7Flpe7;1`Ny@3r7ZR;?R)aJt8C ziNlEC<@3f_lIV4TwV}&e;D!Ee5_|e#g0LUh=5vmYWYm7&2h*M>QPKvGh9-)wfMMW3 z8J9b%1k7dzPzO0_NGQy92BZ^FR6R~6;^6?lqO;-QUP4BY%cG%3vEhbm#>4vIhPBh3 z-+pZGjh$x%Hp{?=FHsMp0&wNPlj00us{&`1ZOZTqs8%4X&xH=UDr*xyBW(Zp&Em94 zf)ZSfn#yg0N)>!1kWdkqJ^S*z0FF5|fj&qcE#Na|%OY0$uO>!&hP+1ywfD_WXk@4J(?MBftK7>$Nvqh@tDuarN%PrTLQ2Uzysx>UV=V zk^RrDSvdQ?0;=hY67EgII-f4`t=+i*yS=Y~!XlqIy_4x&%+OdfbKOFPXS2X5%4R{N z$SQMX^AK6(fA + +namespace winrt::Microsoft::ReactNative +{ + +void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders) +{ + // IReactPackageProviders from react-native-pdf + packageProviders.Append(winrt::RCTPdf::ReactPackageProvider()); +} + +} diff --git a/example/windows/PDFExample/AutolinkedNativeModules.g.h b/example/windows/PDFExample/AutolinkedNativeModules.g.h new file mode 100644 index 00000000..1bf5f894 --- /dev/null +++ b/example/windows/PDFExample/AutolinkedNativeModules.g.h @@ -0,0 +1,10 @@ +// AutolinkedNativeModules.g.h contents generated by "react-native autolink-windows" + +#pragma once + +namespace winrt::Microsoft::ReactNative +{ + +void RegisterAutolinkedNativeModulePackages(winrt::Windows::Foundation::Collections::IVector const& packageProviders); + +} diff --git a/example/windows/PDFExample/AutolinkedNativeModules.g.targets b/example/windows/PDFExample/AutolinkedNativeModules.g.targets new file mode 100644 index 00000000..c3cec5b0 --- /dev/null +++ b/example/windows/PDFExample/AutolinkedNativeModules.g.targets @@ -0,0 +1,10 @@ + + + + + + + {03b8503f-f40d-4013-829c-71b304537d90} + + + diff --git a/example/windows/PDFExample/MainPage.cpp b/example/windows/PDFExample/MainPage.cpp new file mode 100644 index 00000000..9027fe33 --- /dev/null +++ b/example/windows/PDFExample/MainPage.cpp @@ -0,0 +1,24 @@ +#include "pch.h" +#include "MainPage.h" +#if __has_include("MainPage.g.cpp") +#include "MainPage.g.cpp" +#endif + +#include "App.h" + + + +using namespace winrt; +using namespace Windows::UI::Xaml; + +namespace winrt::PDFExample::implementation +{ + MainPage::MainPage() + { + InitializeComponent(); + auto app = Application::Current().as(); + ReactRootView().ReactNativeHost(app->Host()); + } +} + + diff --git a/example/windows/PDFExample/MainPage.h b/example/windows/PDFExample/MainPage.h new file mode 100644 index 00000000..7c1579c9 --- /dev/null +++ b/example/windows/PDFExample/MainPage.h @@ -0,0 +1,21 @@ +#pragma once +#include "MainPage.g.h" +#include + + +namespace winrt::PDFExample::implementation +{ + struct MainPage : MainPageT + { + MainPage(); + }; +} + +namespace winrt::PDFExample::factory_implementation +{ + struct MainPage : MainPageT + { + }; +} + + diff --git a/example/windows/PDFExample/MainPage.idl b/example/windows/PDFExample/MainPage.idl new file mode 100644 index 00000000..dd74bbf0 --- /dev/null +++ b/example/windows/PDFExample/MainPage.idl @@ -0,0 +1,8 @@ +namespace PDFExample +{ + [default_interface] + runtimeclass MainPage : Windows.UI.Xaml.Controls.Page + { + MainPage(); + } +} diff --git a/example/windows/PDFExample/MainPage.xaml b/example/windows/PDFExample/MainPage.xaml new file mode 100644 index 00000000..37f0b163 --- /dev/null +++ b/example/windows/PDFExample/MainPage.xaml @@ -0,0 +1,16 @@ + + + diff --git a/example/windows/PDFExample/PDFExample.vcxproj b/example/windows/PDFExample/PDFExample.vcxproj new file mode 100644 index 00000000..b0eb7ee5 --- /dev/null +++ b/example/windows/PDFExample/PDFExample.vcxproj @@ -0,0 +1,205 @@ + + + + + true + true + true + {95f9323c-1039-4b6a-b69e-a9efddfefb54} + PDFExample + PDFExample + en-US + 16.0 + true + Windows Store + 10.0 + 10.0.18362.0 + 10.0.16299.0 + PDFExample_TemporaryKey.pfx + E03C74524183D74C00377AF0154C246C9456C18F + password + + + + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + Application + Unicode + + + true + true + + + false + true + false + + + + + + + + + + + + + + + + + + Use + pch.h + $(IntDir)pch.pch + Level4 + %(AdditionalOptions) /bigobj + 4453;28204 + + + + + _DEBUG;%(PreprocessorDefinitions) + + + + + NDEBUG;%(PreprocessorDefinitions) + + + + + MainPage.xaml + Code + + + + + + App.xaml + + + + + Designer + + + + + Designer + + + + + + + + + + + + + + MainPage.xaml + Code + + + + + Create + + + App.xaml + + + + + + App.xaml + + + MainPage.xaml + Code + + + + + true + + + + + false + + + + + Designer + + + + + {ca54a654-5e81-44dc-af3f-cf55ef5b493a} + + + + + + + + + This project references targets in your node_modules\react-native-windows folder. The missing file is {0}. + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/example/windows/PDFExample/PDFExample.vcxproj.filters b/example/windows/PDFExample/PDFExample.vcxproj.filters new file mode 100644 index 00000000..0f299790 --- /dev/null +++ b/example/windows/PDFExample/PDFExample.vcxproj.filters @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + Assets + + + + + + + + {e48dc53e-40b1-40cb-970a-f89935452892} + + + + + + + + + + + + + + \ No newline at end of file diff --git a/example/windows/PDFExample/PDFExample_TemporaryKey.pfx b/example/windows/PDFExample/PDFExample_TemporaryKey.pfx new file mode 100644 index 0000000000000000000000000000000000000000..2fb7facd6afaff34abde40d783c740f84b343eea GIT binary patch literal 2598 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 t`Fjq+>r#8QWPI$lLcA`VO~-#7gLBS%`z literal 0 HcmV?d00001 diff --git a/example/windows/PDFExample/Package.appxmanifest b/example/windows/PDFExample/Package.appxmanifest new file mode 100644 index 00000000..16dbe241 --- /dev/null +++ b/example/windows/PDFExample/Package.appxmanifest @@ -0,0 +1,50 @@ + + + + + + + + + + PDFExample + ja + Assets\StoreLogo.png + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/example/windows/PDFExample/PropertySheet.props b/example/windows/PDFExample/PropertySheet.props new file mode 100644 index 00000000..5942ba39 --- /dev/null +++ b/example/windows/PDFExample/PropertySheet.props @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/example/windows/PDFExample/ReactPackageProvider.cpp b/example/windows/PDFExample/ReactPackageProvider.cpp new file mode 100644 index 00000000..9a3b3bb0 --- /dev/null +++ b/example/windows/PDFExample/ReactPackageProvider.cpp @@ -0,0 +1,18 @@ +#include "pch.h" +#include "ReactPackageProvider.h" +#include "NativeModules.h" + + +using namespace winrt::Microsoft::ReactNative; + +namespace winrt::PDFExample::implementation +{ + +void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept +{ + AddAttributedModules(packageBuilder); +} + +} // namespace winrt::PDFExample::implementation + + diff --git a/example/windows/PDFExample/ReactPackageProvider.h b/example/windows/PDFExample/ReactPackageProvider.h new file mode 100644 index 00000000..1be3c878 --- /dev/null +++ b/example/windows/PDFExample/ReactPackageProvider.h @@ -0,0 +1,15 @@ +#pragma once + +#include "winrt/Microsoft.ReactNative.h" + + +namespace winrt::PDFExample::implementation +{ + struct ReactPackageProvider : winrt::implements + { + public: // IReactPackageProvider + void CreatePackage(winrt::Microsoft::ReactNative::IReactPackageBuilder const &packageBuilder) noexcept; + }; +} // namespace winrt::PDFExample::implementation + + diff --git a/example/windows/PDFExample/packages.config b/example/windows/PDFExample/packages.config new file mode 100644 index 00000000..7ad3ffb8 --- /dev/null +++ b/example/windows/PDFExample/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/example/windows/PDFExample/pch.cpp b/example/windows/PDFExample/pch.cpp new file mode 100644 index 00000000..bcb5590b --- /dev/null +++ b/example/windows/PDFExample/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/example/windows/PDFExample/pch.h b/example/windows/PDFExample/pch.h new file mode 100644 index 00000000..e3d762be --- /dev/null +++ b/example/windows/PDFExample/pch.h @@ -0,0 +1,29 @@ +#pragma once + +#define NOMINMAX + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "winrt/RCTPdf.h" +#include "winrt/progress_view.h" diff --git a/index.js b/index.js index edd49e82..740c3e72 100644 --- a/index.js +++ b/index.js @@ -21,7 +21,16 @@ import { import { ProgressBar } from '@react-native-community/progress-bar-android' import { ProgressView } from '@react-native-community/progress-view' -import RNFetchBlob from 'rn-fetch-blob'; +let RNFetchBlob = { + fs : { + dirs: { + CacheDir: '' + } + } +}; +if (Platform.OS !== 'windows') { + RNFetchBlob = require('rn-fetch-blob'); +} const SHA1 = require('crypto-js/sha1'); import PdfView from './PdfView'; @@ -166,12 +175,10 @@ export default class Pdf extends Component { const source = Image.resolveAssetSource(newSource) || {}; let uri = source.uri || ''; - // first set to initial state if (this._mounted) { this.setState({isDownloaded: false, path: '', progress: 0}); } - const cacheFile = RNFetchBlob.fs.dirs.CacheDir + '/' + SHA1(uri) + '.pdf'; if (source.cache) { @@ -392,7 +399,7 @@ export default class Pdf extends Component { }; render() { - if (Platform.OS === "android" || Platform.OS === "ios") { + if (Platform.OS === "android" || Platform.OS === "ios" || Platform.OS === "windows") { return ( {!this.state.isDownloaded? @@ -415,7 +422,7 @@ export default class Pdf extends Component { {...this.props.activityIndicatorProps} />} ):( - Platform.OS === "android"?( + Platform.OS === "android" || Platform.OS === "windows"?( (this._root = component)} {...this.props} @@ -463,6 +470,10 @@ if (Platform.OS === "android") { var PdfCustom = requireNativeComponent('RCTPdfView', Pdf, { nativeOnly: {path: true, onChange: true}, }) +} else if (Platform.OS === "windows") { + var PdfCustom = requireNativeComponent('RCTPdf', Pdf, { + nativeOnly: {path: true, onChange: true}, + }) } diff --git a/windows/RCTPdf/PropertySheet.props b/windows/RCTPdf/PropertySheet.props new file mode 100644 index 00000000..5942ba39 --- /dev/null +++ b/windows/RCTPdf/PropertySheet.props @@ -0,0 +1,16 @@ + + + + + + + + \ No newline at end of file diff --git a/windows/RCTPdf/RCTPdf.def b/windows/RCTPdf/RCTPdf.def new file mode 100644 index 00000000..24e7c123 --- /dev/null +++ b/windows/RCTPdf/RCTPdf.def @@ -0,0 +1,3 @@ +EXPORTS +DllCanUnloadNow = WINRT_CanUnloadNow PRIVATE +DllGetActivationFactory = WINRT_GetActivationFactory PRIVATE diff --git a/windows/RCTPdf/RCTPdf.vcxproj b/windows/RCTPdf/RCTPdf.vcxproj new file mode 100644 index 00000000..16839929 --- /dev/null +++ b/windows/RCTPdf/RCTPdf.vcxproj @@ -0,0 +1,180 @@ + + + + + true + true + true + {03b8503f-f40d-4013-829c-71b304537d90} + RCTPdf + RCTPdf + en-US + 16.0 + true + Windows Store + 10.0 + 10.0.18362.0 + 10.0.16299.0 + + + + $([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), 'node_modules\react-native-windows\package.json'))\node_modules\react-native-windows\ + + + + Debug + ARM + + + Debug + ARM64 + + + Debug + Win32 + + + Debug + x64 + + + Release + ARM + + + Release + ARM64 + + + Release + Win32 + + + Release + x64 + + + + DynamicLibrary + Unicode + false + + + true + true + + + false + true + false + + + + + + + + + + + + + + + + + + Use + pch.h + $(IntDir)pch.pch + Level4 + %(AdditionalOptions) /bigobj + + /DWINRT_NO_MAKE_DETECTION %(AdditionalOptions) + 28204 + _WINRT_DLL;%(PreprocessorDefinitions) + $(WindowsSDK_WindowsMetadata);$(AdditionalUsingDirectories) + + + Console + true + RCTPdf.def + + + + + _DEBUG;%(PreprocessorDefinitions) + ProgramDatabase + + + + + NDEBUG;%(PreprocessorDefinitions) + + + + + RCTPdfControl.xaml + Code + + + + + ReactPackageProvider.idl + + + + + RCTPdfControl.xaml + Code + + + Create + + + + ReactPackageProvider.idl + + + + + + RCTPdfControl.xaml + Code + + + + + + + + + + + + + Designer + + + + + + + + + This project references targets in your node_modules\react-native-windows folder. The missing file is {0}. + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/windows/RCTPdf/RCTPdf.vcxproj.filters b/windows/RCTPdf/RCTPdf.vcxproj.filters new file mode 100644 index 00000000..bd7347df --- /dev/null +++ b/windows/RCTPdf/RCTPdf.vcxproj.filters @@ -0,0 +1,38 @@ + + + + + accd3aa8-1ba0-4223-9bbe-0c431709210b + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tga;tiff;tif;png;wav;mfcribbon-ms + + + {926ab91d-31b5-48c3-b9a4-e681349f27f0} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/windows/RCTPdf/RCTPdfControl.cpp b/windows/RCTPdf/RCTPdfControl.cpp new file mode 100644 index 00000000..9a8b164b --- /dev/null +++ b/windows/RCTPdf/RCTPdfControl.cpp @@ -0,0 +1,586 @@ +#include "pch.h" +#include "RCTPdfControl.h" +#if __has_include("RCTPdfControl.g.cpp") +#include "RCTPdfControl.g.cpp" +#endif + +using namespace winrt; +using namespace Windows::UI::Xaml; +using namespace Microsoft::ReactNative; +using namespace Windows::Data::Json; +using namespace Windows::Data::Pdf; +using namespace Windows::Foundation; +using namespace Windows::Storage; +using namespace Windows::Storage::Streams; +using namespace Windows::Storage::Pickers; +using namespace Windows::UI; +using namespace Windows::UI::Core; +using namespace Windows::UI::Popups; +using namespace Windows::UI::Xaml; +using namespace Windows::UI::Xaml::Controls; +using namespace Windows::UI::Xaml::Input; +using namespace Windows::UI::Xaml::Media; +using namespace Windows::UI::Xaml::Media::Imaging; + +namespace winrt::RCTPdf::implementation +{ + PDFPageInfo::PDFPageInfo(winrt::Windows::UI::Xaml::Controls::Image image, winrt::Windows::Data::Pdf::PdfPage page, double imageScale, double renderScale) : + image(image), page(page), imageScale(imageScale), renderScale(renderScale), scaledTopOffset(0), scaledLeftOffset(0) { + auto dims = page.Size(); + height = (unsigned)dims.Height; + width = (unsigned)dims.Width; + scaledHeight = (unsigned)(height * imageScale); + scaledWidth = (unsigned)(width * imageScale); + } + PDFPageInfo::PDFPageInfo(const PDFPageInfo& rhs) : + height(rhs.height), width(rhs.width), scaledHeight(rhs.scaledHeight), scaledWidth(rhs.scaledWidth), + scaledTopOffset(rhs.scaledTopOffset), scaledLeftOffset(rhs.scaledTopOffset), imageScale(rhs.imageScale), + renderScale((double)rhs.renderScale), image(rhs.image), page(rhs.page) + { } + PDFPageInfo::PDFPageInfo(PDFPageInfo&& rhs) : + height(rhs.height), width(rhs.width), scaledHeight(rhs.scaledHeight), scaledWidth(rhs.scaledWidth), + scaledTopOffset(rhs.scaledTopOffset), scaledLeftOffset(rhs.scaledTopOffset), imageScale(rhs.imageScale), + renderScale((double)rhs.renderScale), image(std::move(rhs.image)), page(std::move(rhs.page)) + { } + unsigned PDFPageInfo::pageVisiblePixels(bool horizontal, double viewportStart, double viewportEnd) const { + if (viewportEnd < viewportStart) + std::swap(viewportStart, viewportEnd); + auto pageStart = horizontal ? scaledLeftOffset : scaledTopOffset; + auto pageSize = PDFPageInfo::pageSize(horizontal); + auto pageEnd = pageStart + pageSize; + auto uViewportStart = (unsigned)viewportStart; + auto uViewportEnd = (unsigned)viewportEnd; + if (pageStart >= uViewportStart && pageStart <= uViewportEnd) { // we see the top edge + return (std::min)(pageEnd, uViewportEnd) - pageStart; + } + if (pageEnd >= uViewportStart && pageEnd <= uViewportEnd) { // we see the bottom edge + return pageEnd - (std::max)(pageStart, uViewportStart); + } + if (pageStart <= uViewportStart && pageEnd >= uViewportEnd) {// we see the entire page + return uViewportEnd - uViewportStart; + } + return 0; + } + unsigned PDFPageInfo::pageSize(bool horizontal) const { + return horizontal ? scaledWidth : scaledHeight; + } + bool PDFPageInfo::needsRender() const { + double currentRenderScale = renderScale; + return currentRenderScale < imageScale || currentRenderScale > imageScale * m_downscaleTreshold; + } + winrt::IAsyncAction PDFPageInfo::render() { + return render(imageScale); + } + winrt::IAsyncAction PDFPageInfo::render(double useScale) { + double currentRenderScale; + while (true) { + currentRenderScale = renderScale; + if (!(currentRenderScale < imageScale || currentRenderScale > imageScale * m_downscaleTreshold)) + co_return; + if (renderScale.compare_exchange_weak(currentRenderScale, useScale)) + break; + if (renderScale > useScale) + co_return; + } + PdfPageRenderOptions renderOptions; + auto dims = page.Size(); + renderOptions.DestinationHeight(static_cast(dims.Height * useScale)); + renderOptions.DestinationWidth(static_cast(dims.Width * useScale)); + InMemoryRandomAccessStream stream; + co_await page.RenderToStreamAsync(stream, renderOptions); + BitmapImage bitmap; + co_await bitmap.SetSourceAsync(stream); + if (renderScale == useScale) + image.Source(bitmap); + } + + RCTPdfControl::RCTPdfControl(IReactContext const& reactContext) : m_reactContext(reactContext) { + InitializeComponent(); + } + + winrt::Windows::Foundation::Collections::IMapView RCTPdfControl::NativeProps() noexcept { + auto nativeProps = winrt::single_threaded_map(); + nativeProps.Insert(L"path", ViewManagerPropertyType::String); + nativeProps.Insert(L"page", ViewManagerPropertyType::Number); + nativeProps.Insert(L"scale", ViewManagerPropertyType::Number); + nativeProps.Insert(L"minScale", ViewManagerPropertyType::Number); + nativeProps.Insert(L"maxScale", ViewManagerPropertyType::Number); + nativeProps.Insert(L"horizontal", ViewManagerPropertyType::Boolean); + nativeProps.Insert(L"fitWidth", ViewManagerPropertyType::Boolean); + nativeProps.Insert(L"fitPolicy", ViewManagerPropertyType::Number); + nativeProps.Insert(L"spacing", ViewManagerPropertyType::Number); + nativeProps.Insert(L"password", ViewManagerPropertyType::String); + nativeProps.Insert(L"background", ViewManagerPropertyType::Color); + // TODO: nativeProps.Insert(L"enablePaging", ViewManagerPropertyType::Boolean); + nativeProps.Insert(L"enableRTL", ViewManagerPropertyType::Boolean); + nativeProps.Insert(L"singlePage", ViewManagerPropertyType::Boolean); + + return nativeProps.GetView(); + } + + void RCTPdfControl::UpdateProperties(winrt::Microsoft::ReactNative::IJSValueReader const& propertyMapReader) noexcept { + const JSValueObject& propertyMap = JSValue::ReadObjectFrom(propertyMapReader); + std::optional pdfURI; + std::optional pdfPassword; + std::optional setPage; + std::optional minScale, maxScale, scale; + std::optional horizontal; + std::optional fitWidth; + std::optional fitPolicy; + std::optional spacing; + std::optional reverse; + std::optional singlePage; + for (auto const& pair : propertyMap) { + auto const& propertyName = pair.first; + auto const& propertyValue = pair.second; + if (propertyName == "path") { + pdfURI = propertyValue != nullptr ? propertyValue.AsString() : ""; + } + else if (propertyName == "password") { + pdfPassword = propertyValue != nullptr ? propertyValue.AsString() : ""; + } + else if (propertyName == "page" && propertyValue != nullptr) { + setPage = propertyValue.AsInt32() - 1; + } + else if (propertyName == "scale" && propertyValue != nullptr) { + scale = propertyValue.AsDouble(); + } + else if (propertyName == "minScale" && propertyValue != nullptr) { + minScale = propertyValue.AsDouble(); + } + else if (propertyName == "maxScale" && propertyValue != nullptr) { + maxScale = propertyValue.AsDouble(); + } + else if (propertyName == "horizontal" && propertyValue != nullptr) { + horizontal = propertyValue.AsBoolean(); + } + else if (propertyName == "fitWidth" && propertyValue != nullptr) { + fitWidth = propertyValue.AsBoolean(); + } + else if (propertyName == "fitPolic" && propertyValue != nullptr) { + fitPolicy = propertyValue.AsInt32(); + } + else if (propertyName == "spacing" && propertyValue != nullptr) { + maxScale = propertyValue.AsInt32(); + } + else if (propertyName == "enableRTL" && propertyValue != nullptr) { + reverse = propertyValue.AsBoolean(); + } + else if (propertyName == "singlePage" && propertyValue != nullptr) { + singlePage = propertyValue.AsBoolean(); + } + else if (propertyName == "background" && propertyValue != nullptr) { + auto color = propertyValue.AsInt32(); + winrt::Windows::UI::Color brushColor; + brushColor.A = (color >> 24) & 0xff; + brushColor.R = (color >> 16) & 0xff; + brushColor.G = (color >> 8) & 0xff; + brushColor.B = color & 0xff; + PagesContainer().Background(SolidColorBrush(brushColor)); + } + } + // If we are loading a new PDF: + std::shared_lock lock(m_rwlock); + if (pdfURI && *pdfURI != m_pdfURI || + pdfPassword && *pdfPassword != m_pdfPassword || + (reverse && *reverse != m_reverse) || + (singlePage && (m_pages.empty() || *singlePage && m_pages.size() != 1 || !*singlePage && m_pages.size() == 1)) ) { + lock.unlock(); + std::unique_lock write_lock(m_rwlock); + m_pdfURI = pdfURI.value_or(""); + m_pdfPassword = pdfPassword.value_or(""); + m_currentPage = setPage.value_or(0); + m_scale = scale.value_or(m_defualtZoom); + m_minScale = minScale.value_or(m_defaultMinZoom); + m_maxScale = maxScale.value_or(m_defaultMaxZoom); + m_horizontal = horizontal.value_or(false); + int useFitPolicy = 2; + if (fitWidth) + useFitPolicy = 0; + if (fitPolicy) + useFitPolicy = *fitPolicy; + m_margins = spacing.value_or(m_defaultMargins); + m_reverse = reverse.value_or(false); + LoadPDF(std::move(write_lock), useFitPolicy, singlePage.value_or(false)); + } else { + // If we are updating the pdf: + m_minScale = minScale.value_or(m_minScale); + m_maxScale = maxScale.value_or(m_maxScale); + bool needScroll = false; + if (horizontal && *horizontal != m_horizontal) { + SetOrientation(*horizontal); + needScroll = true; + } + if (setPage) { + m_currentPage = *setPage; + needScroll = true; + } + if ((scale && *scale != m_scale) || (spacing && *spacing != m_margins)) { + Rescale(scale.value_or(m_scale), spacing.value_or(m_margins), !needScroll); + } + if (needScroll) { + GoToPage(m_currentPage); + } + } + } + + winrt::Microsoft::ReactNative::ConstantProviderDelegate RCTPdfControl::ExportedCustomBubblingEventTypeConstants() noexcept { + return [](IJSValueWriter const& constantWriter) { + WriteCustomDirectEventTypeConstant(constantWriter, "Change"); + }; + } + winrt::Microsoft::ReactNative::ConstantProviderDelegate RCTPdfControl::ExportedCustomDirectEventTypeConstants() noexcept { + return nullptr; + } + + winrt::Windows::Foundation::Collections::IVectorView RCTPdfControl::Commands() noexcept { + auto commands = winrt::single_threaded_vector(); + commands.Append(L"setPage"); + return commands.GetView(); + } + + void RCTPdfControl::DispatchCommand(winrt::hstring const& commandId, winrt::Microsoft::ReactNative::IJSValueReader const& commandArgsReader) noexcept { + auto commandArgs = JSValue::ReadArrayFrom(commandArgsReader); + if (commandId == L"setPage" && commandArgs.size() > 0) { + std::shared_lock lock(m_rwlock); + auto page = commandArgs[0].AsInt32() - 1; + GoToPage(page); + } + } + + void RCTPdfControl::PagesContainer_PointerWheelChanged(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e) { + winrt::Windows::System::VirtualKeyModifiers modifiers = e.KeyModifiers(); + if ((modifiers & winrt::Windows::System::VirtualKeyModifiers::Control) != winrt::Windows::System::VirtualKeyModifiers::Control) + return; + double delta = (e.GetCurrentPoint(*this).Properties().MouseWheelDelta() / WHEEL_DELTA); + std::shared_lock lock(m_rwlock); + auto newScale = (std::max)((std::min)(m_scale * pow(m_zoomMultiplier, delta), m_maxScale), m_minScale); + Rescale(newScale, m_margins, true); + e.Handled(true); + } + + void RCTPdfControl::Pages_SizeChanged(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::SizeChangedEventArgs const&) { + if (m_targetHorizontalOffset || m_targetVerticalOffset) { + auto container = PagesContainer(); + PagesContainer().ChangeView(m_targetHorizontalOffset.value_or(container.HorizontalOffset()), + m_targetVerticalOffset.value_or(container.VerticalOffset()), + nullptr, + true); + m_targetHorizontalOffset.reset(); + m_targetVerticalOffset.reset(); + } + } + + winrt::fire_and_forget RCTPdfControl::PagesContainer_ViewChanged(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::Controls::ScrollViewerViewChangedEventArgs const& args) + { + auto lifetime = get_strong(); + auto container = PagesContainer(); + auto currentHorizontalOffset = container.HorizontalOffset(); + auto currentVerticalOffset = container.VerticalOffset(); + double offsetStart = m_horizontal ? currentHorizontalOffset : currentVerticalOffset; + double viewSize = m_horizontal ? container.ViewportWidth() : container.ViewportHeight(); + double offsetEnd = offsetStart + viewSize; + std::shared_lock lock(m_rwlock, std::defer_lock); + if (args.IsIntermediate() || !lock.try_lock() || viewSize == 0 || m_pages.empty()) + return; + // Go through pages until we reach a visible page + int page = 0; + double visiblePagePixels = 0; + for (; page < (int)m_pages.size(); ++page) { + visiblePagePixels = m_pages[page].pageVisiblePixels(m_horizontal, offsetStart, offsetEnd); + if (visiblePagePixels > 0) + break; + } + if (page == (int)m_pages.size()) { + --page; + } + else { + double pagePixels = m_pages[page].pageSize(m_horizontal); + // #"page" is the first visible page. Check how much of the view port this page covers... + double viewCoveredByPage = visiblePagePixels / viewSize; + // ...and how much of the page is visible: + double pageVisiblePart = visiblePagePixels / pagePixels; + // If: + // - less than 50% of the screen is covered by the page + // - less than 50% of the page is visible (important if more than one page fits the screen) + // - there is a next page + // move the indicator to that page: + if (viewCoveredByPage < 0.5 && pageVisiblePart < 0.5 && page + 1 < (int)m_pages.size()) { + ++page; + } + } + // Render all visible pages - first the current one, then the next visible ones and one + // more, then the one before that might be partly visible, then one more before + co_await RenderVisiblePages(page); + if (page != m_currentPage) { + m_currentPage = page; + SignalPageChange(m_currentPage + 1, m_pages.size()); + } + } + + void RCTPdfControl::PagesContainer_DoubleTapped(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::Input::DoubleTappedRoutedEventArgs const&) + { + std::shared_lock lock(m_rwlock); + double newScale = (std::min)(m_scale * m_zoomMultiplier, m_maxScale); + Rescale(newScale, m_margins, true); + } + + void RCTPdfControl::ChangeScroll(double targetHorizontalOffset, double targetVerticalOffset) { + auto container = PagesContainer(); + auto maxHorizontalOffset = container.ScrollableWidth(); + auto maxVerticalOffset = container.ScrollableHeight(); + // If viewport is bigger than a page, it is possible that target offset is + // smaller than max offset. Take that into account: + if (targetHorizontalOffset <= maxHorizontalOffset + container.ViewportWidth() && + targetVerticalOffset <= maxVerticalOffset + container.ViewportHeight()) { + PagesContainer().ChangeView((std::min)(targetHorizontalOffset, maxHorizontalOffset), + (std::min)(targetVerticalOffset, maxVerticalOffset), + nullptr, true); + } + else { + m_targetHorizontalOffset = targetHorizontalOffset; + m_targetVerticalOffset = targetVerticalOffset; + } + } + + void RCTPdfControl::UpdatePagesInfoMarginOrScale() { + unsigned scaledMargin = (unsigned)(m_scale * m_margins); + for (auto& page : m_pages) { + page.imageScale = m_scale; + page.scaledWidth = (unsigned)(page.width * m_scale); + page.scaledHeight = (unsigned)(page.height * m_scale); + page.image.Margin(ThicknessHelper::FromUniformLength(scaledMargin)); + page.image.Width(page.scaledWidth); + page.image.Height(page.scaledHeight); + } + unsigned totalTopOffset = 0; + unsigned totalLeftOffset = 0; + unsigned doubleScaledMargin = scaledMargin * 2; + if (m_reverse) { + for (int page = m_pages.size() - 1; page >= 0; --page) { + m_pages[page].scaledTopOffset = totalTopOffset; + totalTopOffset += m_pages[page].scaledHeight + doubleScaledMargin; + m_pages[page].scaledLeftOffset = totalLeftOffset; + totalLeftOffset += m_pages[page].scaledWidth + doubleScaledMargin; + } + } + else { + for (int page = 0; page < (int)m_pages.size(); ++page) { + m_pages[page].scaledTopOffset = totalTopOffset; + totalTopOffset += m_pages[page].scaledHeight + doubleScaledMargin; + m_pages[page].scaledLeftOffset = totalLeftOffset; + totalLeftOffset += m_pages[page].scaledWidth + doubleScaledMargin; + } + } + } + + void RCTPdfControl::GoToPage(int page) { + if (page < 0 || page >= (int)m_pages.size()) { + return; + } + auto neededOffset = m_horizontal ? m_pages[page].scaledLeftOffset : m_pages[page].scaledTopOffset; + double horizontalOffset = m_horizontal ? neededOffset : PagesContainer().HorizontalOffset(); + double verticalOffset = m_horizontal ? PagesContainer().VerticalOffset() : neededOffset; + ChangeScroll(horizontalOffset, verticalOffset); + SignalPageChange(page + 1, m_pages.size()); + } + + winrt::fire_and_forget RCTPdfControl::LoadPDF(std::unique_lock lock, int fitPolicy, bool singlePage) { + auto lifetime = get_strong(); + auto uri = Uri(winrt::to_hstring(m_pdfURI)); + PdfDocument document = nullptr; + try { + auto file = co_await StorageFile::GetFileFromApplicationUriAsync(uri); + document = co_await PdfDocument::LoadFromFileAsync(file, winrt::to_hstring(m_pdfPassword)); + } + catch (winrt::hresult_error const& ex) { + switch (ex.to_abi()) { + case __HRESULT_FROM_WIN32(ERROR_WRONG_PASSWORD): + SignalError("Password required or incorrect password."); + co_return; + case E_FAIL: + SignalError("Document is not a valid PDF."); + co_return; + default: + SignalError(winrt::to_string(ex.message())); + co_return; + } + } + auto items = Pages().Items(); + items.Clear(); + m_pages.clear(); + SetOrientation(m_horizontal); + if (document.PageCount() == 0) { + if (fitPolicy != -1) + m_scale = 1; + } + else { + auto firstPageSize = document.GetPage(0).Size(); + auto viewWidth = PagesContainer().ViewportWidth(); + auto viewHeight = PagesContainer().ViewportHeight(); + switch (fitPolicy) { + case 0: + m_scale = viewWidth / (firstPageSize.Width + 2 * (double)m_margins); + break; + case 1: + m_scale = viewHeight / (firstPageSize.Height + 2 * (double)m_margins); + break; + case 2: + m_scale = (std::min)(viewWidth / (firstPageSize.Width + 2 * (double)m_margins), viewHeight / (firstPageSize.Height + 2 * (double)m_margins)); + break; + default: + break; + } + } + unsigned pagesCount = document.PageCount(); + if (singlePage && pagesCount > 0) + pagesCount = 1; + for (unsigned pageIdx = 0; pageIdx < pagesCount; ++pageIdx) { + auto page = document.GetPage(pageIdx); + auto dims = page.Size(); + Image pageImage; + pageImage.HorizontalAlignment(HorizontalAlignment::Center); + m_pages.emplace_back(pageImage, page, m_scale, 0); + } + if (m_reverse) { + for (int page = m_pages.size() - 1; page >= 0; --page) + items.Append(m_pages[page].image); + } + else { + for (int page = 0; page < (int)m_pages.size(); ++page) + items.Append(m_pages[page].image); + } + UpdatePagesInfoMarginOrScale(); + lock.unlock(); + std::shared_lock shared_lock(m_rwlock); + if (m_currentPage < 0) + m_currentPage = 0; + if (m_currentPage < (int)m_pages.size()) { + co_await m_pages[m_currentPage].render(); + GoToPage(m_currentPage); + } + if (m_pages.empty()) { + SignalLoadComplete(0, 0, 0); + } + else { + SignalLoadComplete(m_pages.size(), m_pages.front().width, m_pages.front().height); + } + // Render low-res preview of the pages + double useScale = (std::min)(m_scale, m_previewZoom); + for (unsigned page = 0; page < m_pages.size(); ++page) { + co_await m_pages[page].render(useScale); + } + } + + void RCTPdfControl::Rescale(double newScale, double newMargin, bool goToNewPosition) { + if (newScale != m_scale || newMargin != m_margins) { + double rescale = newScale / m_scale; + double targetHorizontalOffset = PagesContainer().HorizontalOffset() * rescale; + double targetVerticalOffset = PagesContainer().VerticalOffset() * rescale; + if (newMargin != m_margins) { + if (m_horizontal) { + targetVerticalOffset += (double)m_currentPage * 2 * (newMargin - m_margins) * rescale; + } + else { + targetHorizontalOffset += (double)m_currentPage * 2 * (newMargin - m_margins) * rescale; + } + } + m_scale = newScale; + m_margins = (int)newMargin; + UpdatePagesInfoMarginOrScale(); + if (goToNewPosition) { + ChangeScroll(targetHorizontalOffset, targetVerticalOffset); + } + SignalScaleChanged(m_scale); + } + } + + void RCTPdfControl::SetOrientation(bool horizontal) { + m_horizontal = horizontal; + FindName(winrt::to_hstring("OrientationSelector")).try_as().Orientation(m_horizontal ? Orientation::Horizontal : Orientation::Vertical); + } + + winrt::IAsyncAction RCTPdfControl::RenderVisiblePages(int page) { + auto lifetime = get_strong(); + auto container = PagesContainer(); + auto currentHorizontalOffset = container.HorizontalOffset(); + auto currentVerticalOffset = container.VerticalOffset(); + double offsetStart = m_horizontal ? currentHorizontalOffset : currentVerticalOffset; + double viewSize = m_horizontal ? container.ViewportWidth() : container.ViewportHeight(); + double offsetEnd = offsetStart + viewSize; + if (m_pages[page].needsRender()) { + co_await m_pages[page].render(); + } + auto pageToRender = page + 1; + while (pageToRender < (int)m_pages.size() && + m_pages[pageToRender].pageVisiblePixels(m_horizontal, offsetStart, offsetEnd) > 0) { + if (m_pages[pageToRender].needsRender()) { + co_await m_pages[pageToRender].render(); + } + ++pageToRender; + } + if (pageToRender < (int)m_pages.size() && m_pages[pageToRender].needsRender()) { + co_await m_pages[pageToRender].render(); + } + if (page >= 1 && m_pages[page - 1].needsRender()) { + co_await m_pages[page - 1].render(); + } + if (page >= 2 && m_pages[page - 2].needsRender()) { + co_await m_pages[page - 2].render(); + } + } + + void RCTPdfControl::SignalError(const std::string& error) { + m_reactContext.DispatchEvent( + *this, + L"topChange", + [&](winrt::Microsoft::ReactNative::IJSValueWriter const& eventDataWriter) noexcept { + eventDataWriter.WriteObjectBegin(); + { + WriteProperty(eventDataWriter, L"message", winrt::to_hstring("error|" + error)); + } + eventDataWriter.WriteObjectEnd(); + }); + } + void RCTPdfControl::SignalLoadComplete(int totalPages, int width, int height) { + auto message = "loadComplete|" + + std::to_string(totalPages) + "|" + + std::to_string(width) + "|" + + std::to_string(height) + "|"; + m_reactContext.DispatchEvent( + *this, + L"topChange", + [&](winrt::Microsoft::ReactNative::IJSValueWriter const& eventDataWriter) noexcept { + eventDataWriter.WriteObjectBegin(); + { + WriteProperty(eventDataWriter, L"message", winrt::to_hstring(message)); + } + eventDataWriter.WriteObjectEnd(); + }); + } + void RCTPdfControl::SignalPageChange(int page, int totalPages) { + auto message = "pageChanged|" + std::to_string(page) + "|" + std::to_string(totalPages); + m_reactContext.DispatchEvent( + *this, + L"topChange", + [&](winrt::Microsoft::ReactNative::IJSValueWriter const& eventDataWriter) noexcept { + eventDataWriter.WriteObjectBegin(); + { + WriteProperty(eventDataWriter, L"message", winrt::to_hstring(message)); + } + eventDataWriter.WriteObjectEnd(); + }); + } + void RCTPdfControl::SignalScaleChanged(double scale) { + m_reactContext.DispatchEvent( + *this, + L"topChange", + [&](winrt::Microsoft::ReactNative::IJSValueWriter const& eventDataWriter) noexcept { + eventDataWriter.WriteObjectBegin(); + { + WriteProperty(eventDataWriter, L"message", winrt::to_hstring("scale|" + std::to_string(scale))); + } + eventDataWriter.WriteObjectEnd(); + }); + } +} diff --git a/windows/RCTPdf/RCTPdfControl.h b/windows/RCTPdf/RCTPdfControl.h new file mode 100644 index 00000000..6926998a --- /dev/null +++ b/windows/RCTPdf/RCTPdfControl.h @@ -0,0 +1,115 @@ +#pragma once + +#include +#include "winrt/Windows.UI.Xaml.h" +#include "winrt/Windows.UI.Xaml.Markup.h" +#include "winrt/Windows.UI.Xaml.Interop.h" +#include "winrt/Windows.UI.Xaml.Controls.Primitives.h" +#include "winrt/Microsoft.ReactNative.h" +#include "NativeModules.h" +#include "RCTPdfControl.g.h" + +namespace winrt::RCTPdf::implementation +{ + struct PDFPageInfo { + PDFPageInfo(winrt::Windows::UI::Xaml::Controls::Image image, winrt::Windows::Data::Pdf::PdfPage page, double imageScale, double renderScale); + PDFPageInfo(const PDFPageInfo&); + PDFPageInfo(PDFPageInfo&&); + unsigned pageVisiblePixels(bool horizontal, double viewportStart, double viewportEnd) const; + unsigned pageSize(bool horizontal) const; + bool needsRender() const; + winrt::IAsyncAction render(); + winrt::IAsyncAction render(double useScale); + unsigned height, width; + unsigned scaledHeight, scaledWidth; + unsigned scaledTopOffset, scaledLeftOffset; + double imageScale; // scale at which the image is displayed + // Multiple tasks can update the image, use the render scale as the sync point + std::atomic renderScale; // scale at which the image is rendered + winrt::Windows::UI::Xaml::Controls::Image image; + winrt::Windows::Data::Pdf::PdfPage page; + + // If zooming-out at what point we rerender the image with smaller scale? + // E.g. value of 2 means if the image is currently rendered at scale 1.0 + // we will rerender it when the scale is smaller than 0.5 + static constexpr double m_downscaleTreshold = 2; + }; + + struct RCTPdfControl : RCTPdfControlT + { + public: + RCTPdfControl(Microsoft::ReactNative::IReactContext const& reactContext); + + static winrt::Windows::Foundation::Collections::IMapView NativeProps() noexcept; + void UpdateProperties(winrt::Microsoft::ReactNative::IJSValueReader const& propertyMapReader) noexcept; + + static winrt::Microsoft::ReactNative::ConstantProviderDelegate ExportedCustomBubblingEventTypeConstants() noexcept; + static winrt::Microsoft::ReactNative::ConstantProviderDelegate ExportedCustomDirectEventTypeConstants() noexcept; + + static winrt::Windows::Foundation::Collections::IVectorView Commands() noexcept; + void DispatchCommand(winrt::hstring const& commandId, winrt::Microsoft::ReactNative::IJSValueReader const& commandArgsReader) noexcept; + + void PagesContainer_PointerWheelChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); + void Pages_SizeChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::SizeChangedEventArgs const& e); + winrt::fire_and_forget PagesContainer_ViewChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::ScrollViewerViewChangedEventArgs const& e); + void PagesContainer_DoubleTapped(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::DoubleTappedRoutedEventArgs const& e); + private: + Microsoft::ReactNative::IReactContext m_reactContext{ nullptr }; + + // Global lock to access the data stuff + // the pages are rendered in an async way + std::shared_mutex m_rwlock; + // URI and password of the PDF + std::string m_pdfURI; + std::string m_pdfPassword; + // Current active page + int m_currentPage = 0; + // Margins of each page + int m_margins = 10; + // Scale at which the PDF is displayed + double m_scale = 0.2; + double m_minScale = 0.1; + double m_maxScale = 3.0; + // Are we in "horizontal" mode? + bool m_horizontal = false; + // Render the pages in reverse order + bool m_reverse = false; + + // When we rescale or change the margins, we can jump to the new position in the view + // only after the ScrollViewer has updated. We store the target offsets here, and go + // to them when the control finishes updating; + std::optional m_targetHorizontalOffset; + std::optional m_targetVerticalOffset; + // It is possible, that the new position is reachable even before the control is updated. + // A helper function that either schedules a change in the view or jumps right to + // the position + void ChangeScroll(double targetHorizontalOffset, double targetVerticalOffset); + + // Pages info + std::vector m_pages; + + void UpdatePagesInfoMarginOrScale(); + winrt::fire_and_forget LoadPDF(std::unique_lock lock, int fitPolicy, bool singlePage); + void GoToPage(int page); + void Rescale(double newScale, double newMargin, bool goToNewPosition); + void SetOrientation(bool horizontal); + winrt::IAsyncAction RenderVisiblePages(int page); + void SignalError(const std::string& error); + void SignalLoadComplete(int totalPages, int width, int height); + void SignalPageChange(int page, int totalPages); + void SignalScaleChanged(double scale); + + // Zoom in/out scale multiplier + static constexpr double m_zoomMultiplier = 1.2; + static constexpr double m_defaultMaxZoom = 3.0; + static constexpr double m_defaultMinZoom = 1.0; + static constexpr double m_defualtZoom = 1.0; + static constexpr int m_defaultMargins = 10; + static constexpr double m_previewZoom = 0.5; + }; +} + +namespace winrt::RCTPdf::factory_implementation { + struct RCTPdfControl : RCTPdfControlT { + }; +} diff --git a/windows/RCTPdf/RCTPdfControl.idl b/windows/RCTPdf/RCTPdfControl.idl new file mode 100644 index 00000000..0d0591d3 --- /dev/null +++ b/windows/RCTPdf/RCTPdfControl.idl @@ -0,0 +1,10 @@ +namespace RCTPdf +{ + [default_interface] + runtimeclass RCTPdfControl : Windows.UI.Xaml.Controls.UserControl + { + RCTPdfControl(Microsoft.ReactNative.IReactContext context); + void UpdateProperties(Microsoft.ReactNative.IJSValueReader reader); + void DispatchCommand(String commandId, Microsoft.ReactNative.IJSValueReader commandArgsReader); + } +} diff --git a/windows/RCTPdf/RCTPdfControl.xaml b/windows/RCTPdf/RCTPdfControl.xaml new file mode 100644 index 00000000..4a7a3ac6 --- /dev/null +++ b/windows/RCTPdf/RCTPdfControl.xaml @@ -0,0 +1,32 @@ + + + + + + + + + + + diff --git a/windows/RCTPdf/RCTPdfViewManager.cpp b/windows/RCTPdf/RCTPdfViewManager.cpp new file mode 100644 index 00000000..b1d1386a --- /dev/null +++ b/windows/RCTPdf/RCTPdfViewManager.cpp @@ -0,0 +1,69 @@ +#include "pch.h" +#include "NativeModules.h" +#include "JSValueXaml.h" +#include "RCTPdfViewManager.h" +#include "RCTPdfControl.h" + +namespace winrt { + using namespace Microsoft::ReactNative; + using namespace Windows::Foundation; + using namespace Windows::Foundation::Collections; + using namespace Windows::UI; + using namespace Windows::UI::Xaml; + using namespace Windows::UI::Xaml::Controls; +} + +namespace winrt::RCTPdf::implementation { + // IViewManager + winrt::hstring RCTPdfViewManager::Name() noexcept { + return L"RCTPdf"; + } + + winrt::FrameworkElement RCTPdfViewManager::CreateView() noexcept { + return winrt::RCTPdf::RCTPdfControl(m_reactContext); + } + + // IViewManagerWithReactContext + winrt::IReactContext RCTPdfViewManager::ReactContext() noexcept { + return m_reactContext; + } + + void RCTPdfViewManager::ReactContext(IReactContext reactContext) noexcept { + m_reactContext = reactContext; + } + + // IViewManagerWithNativeProperties + IMapView RCTPdfViewManager::NativeProps() noexcept { + return winrt::RCTPdf::implementation::RCTPdfControl::NativeProps(); + } + + void RCTPdfViewManager::UpdateProperties( + FrameworkElement const& view, + IJSValueReader const& propertyMapReader) noexcept { + if (auto module = view.try_as()) { + module.UpdateProperties(propertyMapReader); + } + } + // IViewManagerWithExportedEventTypeConstants + ConstantProviderDelegate RCTPdfViewManager::ExportedCustomBubblingEventTypeConstants() noexcept { + return winrt::RCTPdf::implementation::RCTPdfControl::ExportedCustomBubblingEventTypeConstants(); + } + + ConstantProviderDelegate RCTPdfViewManager::ExportedCustomDirectEventTypeConstants() noexcept { + return winrt::RCTPdf::implementation::RCTPdfControl::ExportedCustomDirectEventTypeConstants(); + } + + // IViewManagerWithCommands + IVectorView RCTPdfViewManager::Commands() noexcept { + return winrt::RCTPdf::implementation::RCTPdfControl::Commands(); + } + + void RCTPdfViewManager::DispatchCommand( + FrameworkElement const& view, + winrt::hstring const& commandId, + winrt::IJSValueReader const& commandArgsReader) noexcept { + if (auto module = view.try_as()) { + module.DispatchCommand(commandId, commandArgsReader); + } + } +} diff --git a/windows/RCTPdf/RCTPdfViewManager.h b/windows/RCTPdf/RCTPdfViewManager.h new file mode 100644 index 00000000..fa2aaee0 --- /dev/null +++ b/windows/RCTPdf/RCTPdfViewManager.h @@ -0,0 +1,51 @@ +#pragma once +#include "winrt/Microsoft.ReactNative.h" +#include "NativeModules.h" + + +namespace winrt::RCTPdf::implementation { + + class RCTPdfViewManager : public winrt::implements< + RCTPdfViewManager, + winrt::Microsoft::ReactNative::IViewManager, + winrt::Microsoft::ReactNative::IViewManagerWithReactContext, + winrt::Microsoft::ReactNative::IViewManagerWithNativeProperties, + winrt::Microsoft::ReactNative::IViewManagerWithExportedEventTypeConstants, + winrt::Microsoft::ReactNative::IViewManagerWithCommands> { + public: + RCTPdfViewManager() = default; + + // IViewManager + winrt::hstring Name() noexcept; + winrt::Windows::UI::Xaml::FrameworkElement CreateView() noexcept; + + // IViewManagerWithReactContext + winrt::Microsoft::ReactNative::IReactContext ReactContext() noexcept; + void ReactContext(winrt::Microsoft::ReactNative::IReactContext reactContext) noexcept; + + // IViewManagerWithNativeProperties + winrt::Windows::Foundation::Collections:: + IMapView + NativeProps() noexcept; + + void UpdateProperties( + winrt::Windows::UI::Xaml::FrameworkElement const& view, + winrt::Microsoft::ReactNative::IJSValueReader const& propertyMapReader) noexcept; + + // IViewManagerWithExportedEventTypeConstants + winrt::Microsoft::ReactNative::ConstantProviderDelegate ExportedCustomBubblingEventTypeConstants() noexcept; + winrt::Microsoft::ReactNative::ConstantProviderDelegate ExportedCustomDirectEventTypeConstants() noexcept; + + + // IViewManagerWithCommands + winrt::Windows::Foundation::Collections::IVectorView Commands() noexcept; + + void DispatchCommand( + winrt::Windows::UI::Xaml::FrameworkElement const &view, + winrt::hstring const &commandId, + winrt::Microsoft::ReactNative::IJSValueReader const &commandArgsReader) noexcept; + + private: + winrt::Microsoft::ReactNative::IReactContext m_reactContext{ nullptr }; + }; +} diff --git a/windows/RCTPdf/ReactPackageProvider.cpp b/windows/RCTPdf/ReactPackageProvider.cpp new file mode 100644 index 00000000..af554dd0 --- /dev/null +++ b/windows/RCTPdf/ReactPackageProvider.cpp @@ -0,0 +1,15 @@ +#include "pch.h" +#include "ReactPackageProvider.h" +#if __has_include("ReactPackageProvider.g.cpp") +# include "ReactPackageProvider.g.cpp" +#endif + +#include "RCTPdfViewManager.h" + +using namespace winrt::Microsoft::ReactNative; + +namespace winrt::RCTPdf::implementation { + void ReactPackageProvider::CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept { + packageBuilder.AddViewManager(L"RCTPdfViewManager", []() { return winrt::make(); }); + } +} diff --git a/windows/RCTPdf/ReactPackageProvider.h b/windows/RCTPdf/ReactPackageProvider.h new file mode 100644 index 00000000..0ce5b9c5 --- /dev/null +++ b/windows/RCTPdf/ReactPackageProvider.h @@ -0,0 +1,16 @@ +#pragma once +#include "ReactPackageProvider.g.h" + +using namespace winrt::Microsoft::ReactNative; + +namespace winrt::RCTPdf::implementation { + struct ReactPackageProvider : ReactPackageProviderT { + ReactPackageProvider() = default; + void CreatePackage(IReactPackageBuilder const &packageBuilder) noexcept; + }; +} + +namespace winrt::RCTPdf::factory_implementation { + struct ReactPackageProvider : ReactPackageProviderT {}; +} + diff --git a/windows/RCTPdf/ReactPackageProvider.idl b/windows/RCTPdf/ReactPackageProvider.idl new file mode 100644 index 00000000..8f2b9f54 --- /dev/null +++ b/windows/RCTPdf/ReactPackageProvider.idl @@ -0,0 +1,9 @@ +namespace RCTPdf +{ + [webhosthidden] + [default_interface] + runtimeclass ReactPackageProvider : Microsoft.ReactNative.IReactPackageProvider + { + ReactPackageProvider(); + }; +} diff --git a/windows/RCTPdf/packages.config b/windows/RCTPdf/packages.config new file mode 100644 index 00000000..1447e714 --- /dev/null +++ b/windows/RCTPdf/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/windows/RCTPdf/pch.cpp b/windows/RCTPdf/pch.cpp new file mode 100644 index 00000000..bcb5590b --- /dev/null +++ b/windows/RCTPdf/pch.cpp @@ -0,0 +1 @@ +#include "pch.h" diff --git a/windows/RCTPdf/pch.h b/windows/RCTPdf/pch.h new file mode 100644 index 00000000..ebe005ec --- /dev/null +++ b/windows/RCTPdf/pch.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include diff --git a/windows/README.md b/windows/README.md new file mode 100644 index 00000000..8bc2611b --- /dev/null +++ b/windows/README.md @@ -0,0 +1,23 @@ +# react-native-pdf Windows Implementation + +Since the module uses react-native-progress-view, it also needs to be referenced in the App: +- Open your solution in Visual Studio 2019 (eg. `windows\yourapp.sln`) +- Right-click Solution icon in Solution Explorer > Add > Existing Project... +- Add `node_modules\@react-native-community\progress-view\windows\progress-view\progress-view.vcxproj` +- If running RNW 0.62: add `node_modules\react-native-pdf\windows\RCTPdf\RCTPdf.vcxproj` +- Right-click main application project > Add > Reference... + - Select `progress-view` and in Solution Projects + - If running 0.62, also select `RCTPdf` +- In app `pch.h` add `#include "winrt/progress-view.h"` and `#include "winrt/RCTPdf.h"` +- In `App.cpp` add `PackageProviders().Append(winrt::progress-view::ReactPackageProvider());` before `InitializeComponent();` +- If running RNW 0.62, also add `PackageProviders().Append(winrt::RCTPdf::ReactPackageProvider());` + + +## Bundling PDFs with the app +To add a `test.pdf` like in the example add: +``` + + true + +``` +in the app `.vcxproj` file, before ``. From 31beb58ed8daf62c9cf8f039f67ff10ec1ef495f Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Mon, 7 Dec 2020 13:32:39 +0100 Subject: [PATCH 02/10] Add enablePaging option --- README.md | 2 +- windows/RCTPdf/RCTPdfControl.cpp | 44 +++++++++++++++++++++++--------- windows/RCTPdf/RCTPdfControl.h | 2 ++ 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 94e0d7b7..cd569f86 100644 --- a/README.md +++ b/README.md @@ -313,7 +313,7 @@ const styles = StyleSheet.create({ | activityIndicator | Component | | when loading show it as an indicator, you can use your component| ✔ | ✔ | ✖ | <3.0 | | activityIndicatorProps | object | {color:'#009900', progressTintColor:'#009900'} | activityIndicator props | ✔ | ✔ | ✖ | 3.1 | | enableAntialiasing | bool | true | improve rendering a little bit on low-res screens, but maybe course some problem on Android 4.4, so add a switch | ✖ | ✔ | ✖ | <3.0 | -| enablePaging | bool | false | only show one page in screen | ✔ | ✔ | ✖ | 5.0.1 | +| enablePaging | bool | false | only show one page in screen | ✔ | ✔ | ✔ | 5.0.1 | | enableRTL | bool | false | scroll page as "page3, page2, page1" | ✔ | ✖ | ✔ | 5.0.1 | | enableAnnotationRendering | bool | true | enable rendering annotation, notice:iOS only support initial setting,not support realtime changing | ✔ | ✔ | ✖ | 5.0.3 | | trustAllCerts | bool | true | Allow connections to servers with self-signed certification | ✔ | ✔ | ✖ | 6.0.? | diff --git a/windows/RCTPdf/RCTPdfControl.cpp b/windows/RCTPdf/RCTPdfControl.cpp index 9a8b164b..d5e671d1 100644 --- a/windows/RCTPdf/RCTPdfControl.cpp +++ b/windows/RCTPdf/RCTPdfControl.cpp @@ -111,7 +111,7 @@ namespace winrt::RCTPdf::implementation nativeProps.Insert(L"spacing", ViewManagerPropertyType::Number); nativeProps.Insert(L"password", ViewManagerPropertyType::String); nativeProps.Insert(L"background", ViewManagerPropertyType::Color); - // TODO: nativeProps.Insert(L"enablePaging", ViewManagerPropertyType::Boolean); + nativeProps.Insert(L"enablePaging", ViewManagerPropertyType::Boolean); nativeProps.Insert(L"enableRTL", ViewManagerPropertyType::Boolean); nativeProps.Insert(L"singlePage", ViewManagerPropertyType::Boolean); @@ -130,6 +130,7 @@ namespace winrt::RCTPdf::implementation std::optional spacing; std::optional reverse; std::optional singlePage; + std::optional enablePaging; for (auto const& pair : propertyMap) { auto const& propertyName = pair.first; auto const& propertyValue = pair.second; @@ -154,6 +155,9 @@ namespace winrt::RCTPdf::implementation else if (propertyName == "horizontal" && propertyValue != nullptr) { horizontal = propertyValue.AsBoolean(); } + else if (propertyName == "enablePaging" && propertyValue != nullptr) { + enablePaging = propertyValue.AsBoolean(); + } else if (propertyName == "fitWidth" && propertyValue != nullptr) { fitWidth = propertyValue.AsBoolean(); } @@ -184,6 +188,7 @@ namespace winrt::RCTPdf::implementation if (pdfURI && *pdfURI != m_pdfURI || pdfPassword && *pdfPassword != m_pdfPassword || (reverse && *reverse != m_reverse) || + (enablePaging && *enablePaging != m_enablePaging) || (singlePage && (m_pages.empty() || *singlePage && m_pages.size() != 1 || !*singlePage && m_pages.size() == 1)) ) { lock.unlock(); std::unique_lock write_lock(m_rwlock); @@ -194,6 +199,7 @@ namespace winrt::RCTPdf::implementation m_minScale = minScale.value_or(m_defaultMinZoom); m_maxScale = maxScale.value_or(m_defaultMaxZoom); m_horizontal = horizontal.value_or(false); + m_enablePaging = enablePaging.value_or(false); int useFitPolicy = 2; if (fitWidth) useFitPolicy = 0; @@ -378,10 +384,20 @@ namespace winrt::RCTPdf::implementation if (page < 0 || page >= (int)m_pages.size()) { return; } - auto neededOffset = m_horizontal ? m_pages[page].scaledLeftOffset : m_pages[page].scaledTopOffset; - double horizontalOffset = m_horizontal ? neededOffset : PagesContainer().HorizontalOffset(); - double verticalOffset = m_horizontal ? PagesContainer().VerticalOffset() : neededOffset; - ChangeScroll(horizontalOffset, verticalOffset); + if (m_enablePaging) { + [&](int page) -> winrt::fire_and_forget { + auto lifetime = get_strong(); + co_await m_pages[page].render(); + }(page); + Pages().Items().ReplaceAll({ &m_pages[page].image, &m_pages[page].image + 1 }); + //Pages().Items().Clear(); + //Pages().Items().Append(m_pages[page].image); + } else { + auto neededOffset = m_horizontal ? m_pages[page].scaledLeftOffset : m_pages[page].scaledTopOffset; + double horizontalOffset = m_horizontal ? neededOffset : PagesContainer().HorizontalOffset(); + double verticalOffset = m_horizontal ? PagesContainer().VerticalOffset() : neededOffset; + ChangeScroll(horizontalOffset, verticalOffset); + } SignalPageChange(page + 1, m_pages.size()); } @@ -442,13 +458,17 @@ namespace winrt::RCTPdf::implementation pageImage.HorizontalAlignment(HorizontalAlignment::Center); m_pages.emplace_back(pageImage, page, m_scale, 0); } - if (m_reverse) { - for (int page = m_pages.size() - 1; page >= 0; --page) - items.Append(m_pages[page].image); - } - else { - for (int page = 0; page < (int)m_pages.size(); ++page) - items.Append(m_pages[page].image); + if (m_enablePaging) { + items.Append(m_pages[m_currentPage].image); + } else { + if (m_reverse) { + for (int page = m_pages.size() - 1; page >= 0; --page) + items.Append(m_pages[page].image); + } + else { + for (int page = 0; page < (int)m_pages.size(); ++page) + items.Append(m_pages[page].image); + } } UpdatePagesInfoMarginOrScale(); lock.unlock(); diff --git a/windows/RCTPdf/RCTPdfControl.h b/windows/RCTPdf/RCTPdfControl.h index 6926998a..b271da64 100644 --- a/windows/RCTPdf/RCTPdfControl.h +++ b/windows/RCTPdf/RCTPdfControl.h @@ -74,6 +74,8 @@ namespace winrt::RCTPdf::implementation bool m_horizontal = false; // Render the pages in reverse order bool m_reverse = false; + // Is in "enablePaging" mode + bool m_enablePaging = false; // When we rescale or change the margins, we can jump to the new position in the view // only after the ScrollViewer has updated. We store the target offsets here, and go From f2109f3d606f84c94fae5308d426beaab78a1ef9 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Mon, 7 Dec 2020 14:02:26 +0100 Subject: [PATCH 03/10] Add onPageSingleTap --- README.md | 2 +- windows/RCTPdf/RCTPdfControl.cpp | 41 +++++++++++++++++++++++++++++++ windows/RCTPdf/RCTPdfControl.h | 2 ++ windows/RCTPdf/RCTPdfControl.xaml | 1 + 4 files changed, 45 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index cd569f86..9501e454 100644 --- a/README.md +++ b/README.md @@ -322,7 +322,7 @@ const styles = StyleSheet.create({ | onLoadComplete | function(numberOfPages, path, {width, height}, tableContents) | null | callback when pdf load completed, return total page count, pdf local/cache path, {width,height} and table of contents | ✔ | ✔ | ✔ but without tableContents | <3.0 | | onPageChanged | function(page,numberOfPages) | null | callback when page changed ,return current page and total page count | ✔ | ✔ | ✔ | <3.0 | | onError | function(error) | null | callback when error happened | ✔ | ✔ | ✔ | <3.0 | -| onPageSingleTap | function(page) | null | callback when page was single tapped | ✔ | ✔ | ✖ | 3.0 | +| onPageSingleTap | function(page) | null | callback when page was single tapped | ✔ | ✔ | ✔ | 3.0 | | onScaleChanged | function(scale) | null | callback when scale page | ✔ | ✔ | ✔ | 3.0 | | onPressLink | function(uri) | null | callback when link tapped | ✔ | ✔ | ✔ | 6.0.0 | diff --git a/windows/RCTPdf/RCTPdfControl.cpp b/windows/RCTPdf/RCTPdfControl.cpp index d5e671d1..532788e0 100644 --- a/windows/RCTPdf/RCTPdfControl.cpp +++ b/windows/RCTPdf/RCTPdfControl.cpp @@ -324,6 +324,31 @@ namespace winrt::RCTPdf::implementation } } + void RCTPdfControl::PagesContainer_Tapped(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::Input::TappedRoutedEventArgs const& args) { + auto position = args.GetPosition(*this); + std::shared_lock lock(m_rwlock); + int scaledDoubleMargin = (int)(m_scale * m_margins * 2); + int page = 0; + int xPosition = (int)(position.X + PagesContainer().HorizontalOffset()); + int yPosition = (int)(position.Y + PagesContainer().VerticalOffset()); + for (; page < (int)m_pages.size(); ++page) { + if (m_horizontal) { + if (xPosition >= m_pages[page].scaledLeftOffset && + xPosition <= m_pages[page].scaledLeftOffset + m_pages[page].scaledWidth + scaledDoubleMargin) + break; + } else { + if (yPosition >= m_pages[page].scaledTopOffset && + yPosition <= m_pages[page].scaledTopOffset + m_pages[page].scaledHeight + scaledDoubleMargin) + break; + } + } + if (page == (int)m_pages.size()) { + page = m_currentPage; + } + SignalPageTapped(page, (int)position.X, (int)position.Y); + } + + void RCTPdfControl::PagesContainer_DoubleTapped(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::Input::DoubleTappedRoutedEventArgs const&) { std::shared_lock lock(m_rwlock); @@ -603,4 +628,20 @@ namespace winrt::RCTPdf::implementation eventDataWriter.WriteObjectEnd(); }); } + void RCTPdfControl::SignalPageTapped(int page, int x, int y) { + const std::string message = "pageSingleTap|" + + std::to_string(page + 1) + "|" + + std::to_string(x) + "|" + + std::to_string(y); + m_reactContext.DispatchEvent( + *this, + L"topChange", + [&](winrt::Microsoft::ReactNative::IJSValueWriter const& eventDataWriter) noexcept { + eventDataWriter.WriteObjectBegin(); + { + WriteProperty(eventDataWriter, L"message", winrt::to_hstring(message)); + } + eventDataWriter.WriteObjectEnd(); + }); + } } diff --git a/windows/RCTPdf/RCTPdfControl.h b/windows/RCTPdf/RCTPdfControl.h index b271da64..9a135ec1 100644 --- a/windows/RCTPdf/RCTPdfControl.h +++ b/windows/RCTPdf/RCTPdfControl.h @@ -52,6 +52,7 @@ namespace winrt::RCTPdf::implementation void PagesContainer_PointerWheelChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::PointerRoutedEventArgs const& e); void Pages_SizeChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::SizeChangedEventArgs const& e); winrt::fire_and_forget PagesContainer_ViewChanged(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Controls::ScrollViewerViewChangedEventArgs const& e); + void PagesContainer_Tapped(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::TappedRoutedEventArgs const& e); void PagesContainer_DoubleTapped(winrt::Windows::Foundation::IInspectable const& sender, winrt::Windows::UI::Xaml::Input::DoubleTappedRoutedEventArgs const& e); private: Microsoft::ReactNative::IReactContext m_reactContext{ nullptr }; @@ -100,6 +101,7 @@ namespace winrt::RCTPdf::implementation void SignalLoadComplete(int totalPages, int width, int height); void SignalPageChange(int page, int totalPages); void SignalScaleChanged(double scale); + void SignalPageTapped(int page, int x, int y); // Zoom in/out scale multiplier static constexpr double m_zoomMultiplier = 1.2; diff --git a/windows/RCTPdf/RCTPdfControl.xaml b/windows/RCTPdf/RCTPdfControl.xaml index 4a7a3ac6..edffab25 100644 --- a/windows/RCTPdf/RCTPdfControl.xaml +++ b/windows/RCTPdf/RCTPdfControl.xaml @@ -17,6 +17,7 @@ AllowFocusWhenDisabled="True" UseSystemFocusVisuals="False" PointerWheelChanged="PagesContainer_PointerWheelChanged" + Tapped="PagesContainer_Tapped" DoubleTapped="PagesContainer_DoubleTapped" ViewChanged="PagesContainer_ViewChanged" > From a650eced26149aabb4965552854e04c29205e132 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Mon, 7 Dec 2020 22:05:39 +0100 Subject: [PATCH 04/10] fixup: warnings --- windows/RCTPdf/RCTPdfControl.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/windows/RCTPdf/RCTPdfControl.cpp b/windows/RCTPdf/RCTPdfControl.cpp index 532788e0..ae3c8229 100644 --- a/windows/RCTPdf/RCTPdfControl.cpp +++ b/windows/RCTPdf/RCTPdfControl.cpp @@ -333,12 +333,12 @@ namespace winrt::RCTPdf::implementation int yPosition = (int)(position.Y + PagesContainer().VerticalOffset()); for (; page < (int)m_pages.size(); ++page) { if (m_horizontal) { - if (xPosition >= m_pages[page].scaledLeftOffset && - xPosition <= m_pages[page].scaledLeftOffset + m_pages[page].scaledWidth + scaledDoubleMargin) + if (xPosition >= (int)m_pages[page].scaledLeftOffset && + xPosition <= (int)(m_pages[page].scaledLeftOffset + m_pages[page].scaledWidth + scaledDoubleMargin)) break; } else { - if (yPosition >= m_pages[page].scaledTopOffset && - yPosition <= m_pages[page].scaledTopOffset + m_pages[page].scaledHeight + scaledDoubleMargin) + if (yPosition >= (int)m_pages[page].scaledTopOffset && + yPosition <= (int)(m_pages[page].scaledTopOffset + m_pages[page].scaledHeight + scaledDoubleMargin)) break; } } From 7805c2b5429827a912e36b0ec0ceaa939debbcb6 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Mon, 7 Dec 2020 22:07:15 +0100 Subject: [PATCH 05/10] fixup: windows uri example --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9501e454..c3495cde 100644 --- a/README.md +++ b/README.md @@ -346,7 +346,7 @@ const styles = StyleSheet.create({ | `{uri:"bundle-assets://xxx.pdf"}` | load pdf from assets, you must add pdf to project by xcode. this does not support folder. | ✔ | ✖ | ✖ | | `{uri:"data:application/pdf;base64,JVBERi0xLjcKJc..."}` | load pdf from base64 string | ✔ | ✔ | ✖ | | `{uri:"file:///absolute/path/to/xxx.pdf"}` | load pdf from local file system | ✔ | ✔ | ✖ | -| `{uri: 'ms-appx:///xxx.pdf'}} | load pdf bundled with UWP app | ✖ | ✖ | ✔ | +| `{uri:"ms-appx:///xxx.pdf"}}` | load pdf bundled with UWP app | ✖ | ✖ | ✔ | ### Methods From 305326e28264681fcdbf32adb688633b99388174 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Mon, 7 Dec 2020 22:07:37 +0100 Subject: [PATCH 06/10] Implement style prop --- README.md | 2 +- windows/RCTPdf/RCTPdfControl.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c3495cde..1fa1a029 100644 --- a/README.md +++ b/README.md @@ -309,7 +309,7 @@ const styles = StyleSheet.create({ | fitPolicy | number | 2 | 0:fit width, 1:fit height, 2:fit both(default)| ✔ | ✔ | ✔ | 3.0 | | spacing | number | 10 | the breaker size between pages| ✔ | ✔ | ✔ | <3.0 | | password | string | "" | pdf password, if password error, will call OnError() with message "Password required or incorrect password." | ✔ | ✔ | ✔ | <3.0 | -| style | object | {backgroundColor:"#eee"} | support normal view style, you can use this to set border/spacing color... | ✔ | ✔ | ✖ | <3.0 | +| style | object | {backgroundColor:"#eee"} | support normal view style, you can use this to set border/spacing color... | ✔ | ✔ | ✔ | <3.0 | | activityIndicator | Component | | when loading show it as an indicator, you can use your component| ✔ | ✔ | ✖ | <3.0 | | activityIndicatorProps | object | {color:'#009900', progressTintColor:'#009900'} | activityIndicator props | ✔ | ✔ | ✖ | 3.1 | | enableAntialiasing | bool | true | improve rendering a little bit on low-res screens, but maybe course some problem on Android 4.4, so add a switch | ✖ | ✔ | ✖ | <3.0 | diff --git a/windows/RCTPdf/RCTPdfControl.cpp b/windows/RCTPdf/RCTPdfControl.cpp index ae3c8229..c55996d4 100644 --- a/windows/RCTPdf/RCTPdfControl.cpp +++ b/windows/RCTPdf/RCTPdfControl.cpp @@ -173,7 +173,7 @@ namespace winrt::RCTPdf::implementation else if (propertyName == "singlePage" && propertyValue != nullptr) { singlePage = propertyValue.AsBoolean(); } - else if (propertyName == "background" && propertyValue != nullptr) { + else if (propertyName == "backgroundColor" && propertyValue != nullptr) { auto color = propertyValue.AsInt32(); winrt::Windows::UI::Color brushColor; brushColor.A = (color >> 24) & 0xff; From 33ca9def1d923bdfa9ddc734726cd5de8df94098 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Mon, 7 Dec 2020 22:10:18 +0100 Subject: [PATCH 07/10] fixup: mark onPressLink as not supported on Windows --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1fa1a029..c9e49f62 100644 --- a/README.md +++ b/README.md @@ -324,7 +324,7 @@ const styles = StyleSheet.create({ | onError | function(error) | null | callback when error happened | ✔ | ✔ | ✔ | <3.0 | | onPageSingleTap | function(page) | null | callback when page was single tapped | ✔ | ✔ | ✔ | 3.0 | | onScaleChanged | function(scale) | null | callback when scale page | ✔ | ✔ | ✔ | 3.0 | -| onPressLink | function(uri) | null | callback when link tapped | ✔ | ✔ | ✔ | 6.0.0 | +| onPressLink | function(uri) | null | callback when link tapped | ✔ | ✔ | ✖ | 6.0.0 | #### parameters of source From 0e59bf51fd20beb822f77a4f9a716dfae068a775 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Mon, 7 Dec 2020 22:39:17 +0100 Subject: [PATCH 08/10] Enable broadFileSystemAccess capability in the example app --- example/windows/PDFExample/Package.appxmanifest | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/example/windows/PDFExample/Package.appxmanifest b/example/windows/PDFExample/Package.appxmanifest index 16dbe241..65067f9a 100644 --- a/example/windows/PDFExample/Package.appxmanifest +++ b/example/windows/PDFExample/Package.appxmanifest @@ -4,7 +4,8 @@ xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" - IgnorableNamespaces="uap mp"> + xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities" + IgnorableNamespaces="uap mp rescap"> + \ No newline at end of file From 1ad43ab1d3c6b2f22c9b64a81f3f08ba7486fd6a Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Mon, 7 Dec 2020 22:58:19 +0100 Subject: [PATCH 09/10] Add file:// URI support --- README.md | 2 +- windows/RCTPdf/RCTPdfControl.cpp | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index c9e49f62..6ae32ab4 100644 --- a/README.md +++ b/README.md @@ -345,7 +345,7 @@ const styles = StyleSheet.create({ | `{uri:"bundle-assets://path/to/xxx.pdf"}` | load pdf from assets, the file should be at android/app/src/main/assets/path/to/xxx.pdf | ✖ | ✔ | ✖ | | `{uri:"bundle-assets://xxx.pdf"}` | load pdf from assets, you must add pdf to project by xcode. this does not support folder. | ✔ | ✖ | ✖ | | `{uri:"data:application/pdf;base64,JVBERi0xLjcKJc..."}` | load pdf from base64 string | ✔ | ✔ | ✖ | -| `{uri:"file:///absolute/path/to/xxx.pdf"}` | load pdf from local file system | ✔ | ✔ | ✖ | +| `{uri:"file:///absolute/path/to/xxx.pdf"}` | load pdf from local file system | ✔ | ✔ | ✔ | | `{uri:"ms-appx:///xxx.pdf"}}` | load pdf bundled with UWP app | ✖ | ✖ | ✔ | diff --git a/windows/RCTPdf/RCTPdfControl.cpp b/windows/RCTPdf/RCTPdfControl.cpp index c55996d4..572ee8d4 100644 --- a/windows/RCTPdf/RCTPdfControl.cpp +++ b/windows/RCTPdf/RCTPdfControl.cpp @@ -428,10 +428,18 @@ namespace winrt::RCTPdf::implementation winrt::fire_and_forget RCTPdfControl::LoadPDF(std::unique_lock lock, int fitPolicy, bool singlePage) { auto lifetime = get_strong(); - auto uri = Uri(winrt::to_hstring(m_pdfURI)); + auto pdfURI = m_pdfURI; + auto uri = Uri(winrt::to_hstring(pdfURI)); + auto scheme = uri.SchemeName(); + if (scheme == L"file") { + // backslashes only on Windows + std::replace(begin(pdfURI), end(pdfURI), '/', '\\'); + } PdfDocument document = nullptr; try { - auto file = co_await StorageFile::GetFileFromApplicationUriAsync(uri); + auto file = scheme == L"file" + ? co_await StorageFile::GetFileFromPathAsync(winrt::to_hstring(pdfURI)) + : co_await StorageFile::GetFileFromApplicationUriAsync(uri); document = co_await PdfDocument::LoadFromFileAsync(file, winrt::to_hstring(m_pdfPassword)); } catch (winrt::hresult_error const& ex) { @@ -447,6 +455,10 @@ namespace winrt::RCTPdf::implementation co_return; } } + if (!document) { + SignalError("Could not load PDF."); + co_return; + } auto items = Pages().Items(); items.Clear(); m_pages.clear(); From 6eafbadee07ed487b63490ce75c6197e39eb99ea Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Mon, 7 Dec 2020 23:16:27 +0100 Subject: [PATCH 10/10] Make arrow keys scroll the PDF after clicking --- windows/RCTPdf/RCTPdfControl.cpp | 9 ++++++--- windows/RCTPdf/RCTPdfControl.xaml | 3 ++- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/windows/RCTPdf/RCTPdfControl.cpp b/windows/RCTPdf/RCTPdfControl.cpp index 572ee8d4..e3a00d09 100644 --- a/windows/RCTPdf/RCTPdfControl.cpp +++ b/windows/RCTPdf/RCTPdfControl.cpp @@ -346,14 +346,18 @@ namespace winrt::RCTPdf::implementation page = m_currentPage; } SignalPageTapped(page, (int)position.X, (int)position.Y); + PagesContainer().Focus(FocusState::Pointer); + args.Handled(true); } - void RCTPdfControl::PagesContainer_DoubleTapped(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::Input::DoubleTappedRoutedEventArgs const&) + void RCTPdfControl::PagesContainer_DoubleTapped(winrt::Windows::Foundation::IInspectable const&, winrt::Windows::UI::Xaml::Input::DoubleTappedRoutedEventArgs const& args) { std::shared_lock lock(m_rwlock); double newScale = (std::min)(m_scale * m_zoomMultiplier, m_maxScale); Rescale(newScale, m_margins, true); + PagesContainer().Focus(FocusState::Pointer); + args.Handled(true); } void RCTPdfControl::ChangeScroll(double targetHorizontalOffset, double targetVerticalOffset) { @@ -415,8 +419,6 @@ namespace winrt::RCTPdf::implementation co_await m_pages[page].render(); }(page); Pages().Items().ReplaceAll({ &m_pages[page].image, &m_pages[page].image + 1 }); - //Pages().Items().Clear(); - //Pages().Items().Append(m_pages[page].image); } else { auto neededOffset = m_horizontal ? m_pages[page].scaledLeftOffset : m_pages[page].scaledTopOffset; double horizontalOffset = m_horizontal ? neededOffset : PagesContainer().HorizontalOffset(); @@ -493,6 +495,7 @@ namespace winrt::RCTPdf::implementation auto dims = page.Size(); Image pageImage; pageImage.HorizontalAlignment(HorizontalAlignment::Center); + pageImage.AllowFocusOnInteraction(false); m_pages.emplace_back(pageImage, page, m_scale, 0); } if (m_enablePaging) { diff --git a/windows/RCTPdf/RCTPdfControl.xaml b/windows/RCTPdf/RCTPdfControl.xaml index edffab25..b5466138 100644 --- a/windows/RCTPdf/RCTPdfControl.xaml +++ b/windows/RCTPdf/RCTPdfControl.xaml @@ -22,7 +22,8 @@ ViewChanged="PagesContainer_ViewChanged" > + SizeChanged="Pages_SizeChanged" + AllowFocusOnInteraction="False">