diff --git a/docz/docs/03-demos/03-desktop.md b/docz/docs/03-demos/03-desktop.md index a00342e..7857d26 100644 --- a/docz/docs/03-demos/03-desktop.md +++ b/docz/docs/03-demos/03-desktop.md @@ -2,6 +2,9 @@ title: Desktop Applications --- +import Tabs from '@theme/Tabs'; +import TabItem from '@theme/TabItem'; + Web technologies like JavaScript and HTML have been adapted to the traditional app space. Typically these frameworks bundle a JavaScript engine as well as a windowing framework. SheetJS is compatible with many app frameworks. @@ -1017,14 +1020,44 @@ React Native Windows use [Turbo Modules](https://reactnative.dev/docs/the-new-ar
Complete Example (click to show) +:::note + +React Native Windows supports writing native code in C++ or C#. This demo has +been tested against both application types. + +::: + 0) Follow the ["Getting Started" guide](https://microsoft.github.io/react-native-windows/docs/getting-started) -1) Create a new project using React Native `0.69` with C# app language: +1) Create a new project using React Native `0.69`: ```powershell npx react-native init SheetJSWin --template react-native@^0.69.0 cd .\SheetJSWin\ +``` + +Create the Windows part of the application: + + + + +```powershell npx react-native-windows-init --no-telemetry --overwrite --language=cs +``` + + + + +```powershell +npx react-native-windows-init --no-telemetry --overwrite +``` + + + + +Install library: + +```powershell npm install --save https://cdn.sheetjs.com/xlsx-latest/xlsx-latest.tgz ``` @@ -1034,6 +1067,9 @@ To ensure that the app works, launch the app: npx react-native run-windows --no-telemetry ``` + + + 2) Create the file `windows\SheetJSWin\DocumentPicker.cs` with the following: ```csharp title="windows\SheetJSWin\DocumentPicker.cs" @@ -1085,6 +1121,71 @@ the `ItemGroup` that contains `ReactPackageProvider.cs`: ``` + + + +2) Create the file `windows\SheetJSWin\DocumentPicker.h` with the following: + +```cpp title="windows\SheetJSWin\DocumentPicker.h" +#pragma once + +#include "pch.h" +#include +#include +#include "JSValue.h" +#include "NativeModules.h" + +using namespace winrt::Microsoft::ReactNative; +using namespace winrt::Windows::Foundation; +using namespace winrt::Windows::Storage; +using namespace winrt::Windows::Storage::Pickers; +using namespace winrt::Windows::Security::Cryptography; + +namespace SheetJSWin { + REACT_MODULE(DocumentPicker); + struct DocumentPicker { + REACT_INIT(Initialize); + void Initialize(const ReactContext& reactContext) noexcept { + context = reactContext; + } + + REACT_METHOD(PickAndRead); + void PickAndRead(ReactPromise promise) noexcept { + auto prom = promise; + context.UIDispatcher().Post([prom = std::move(prom)]()->winrt::fire_and_forget { + auto p = prom; + winrt::Windows::Storage::Pickers::FileOpenPicker picker; + picker.SuggestedStartLocation(PickerLocationId::DocumentsLibrary); + picker.FileTypeFilter().Append(L".xlsx"); + picker.FileTypeFilter().Append(L".xls"); + + StorageFile file = co_await picker.PickSingleFileAsync(); + if(file == nullptr) { p.Reject("File not Found"); co_return; } + + auto buf = co_await FileIO::ReadBufferAsync(file); + p.Resolve(CryptographicBuffer::EncodeToBase64String(buf)); + co_return; + }); + } + + private: + ReactContext context{nullptr}; + }; +} +``` + +3) Add the highlighted line to `windows\SheetJSWin\ReactPackageProvider.cpp`: + +```cpp title="windows\SheetJSWin\ReactPackageProvider.cpp" +#include "ReactPackageProvider.h" +// highlight-next-line +#include "DocumentPicker.h" +#include "NativeModules.h" +``` + + + + Now the native module will be added to the app. 4) Remove `App.js` and save the following to `App.tsx`: @@ -1150,7 +1251,10 @@ Only the main UI thread can show file pickers. This is similar to Web Worker DOM access limitations in the Web platform. This example defines a `PickAndRead` function that will show the file picker, -read the file contents, and return a Base64 string: +read the file contents, and return a Base64 string. + + + ```csharp namespace SheetJSWin { @@ -1162,11 +1266,7 @@ namespace SheetJSWin { public void Initialize(ReactContext ctx) { context = ctx; } [ReactMethod("PickAndRead")] - public async void PickAndRead( - /* "out" param is a Promise that resolves to string or rejects */ - // highlight-next-line - IReactPromise result - ) { + public async void PickAndRead(IReactPromise result) { /* perform file picker action in the UI thread */ // highlight-next-line context.Handle.UIDispatcher.Post(async() => { try { @@ -1183,6 +1283,7 @@ namespace SheetJSWin { /* read data and return base64 string */ var buf = await FileIO.ReadBufferAsync(file); + // highlight-next-line result.Resolve(CryptographicBuffer.EncodeToBase64String(buf)); } catch(Exception e) { result.Reject(new ReactError { Message = e.Message }); }}); } @@ -1190,6 +1291,57 @@ namespace SheetJSWin { } ``` + + + +```cpp +namespace SheetJSWin +{ + REACT_MODULE(DocumentPicker); + struct DocumentPicker + { + /* The context must be stored when the module is initialized */ + REACT_INIT(Initialize); + void Initialize(const ReactContext& reactContext) noexcept { + context = reactContext; + } + + REACT_METHOD(PickAndRead); + void PickAndRead(ReactPromise promise) noexcept { + auto prom = promise; + /* perform file picker action in the UI thread */ + // highlight-next-line + context.UIDispatcher().Post([prom = std::move(prom)]()->winrt::fire_and_forget { + auto p = prom; // promise -> prom -> p dance avoids promise destruction + + /* create file picker */ + winrt::Windows::Storage::Pickers::FileOpenPicker picker; + picker.SuggestedStartLocation(PickerLocationId::DocumentsLibrary); + picker.FileTypeFilter().Append(L".xlsx"); + picker.FileTypeFilter().Append(L".xls"); + + /* show file picker */ + // highlight-next-line + StorageFile file = co_await picker.PickSingleFileAsync(); + if(file == nullptr) { p.Reject("File not Found"); co_return; } + + /* read data and return base64 string */ + auto buf = co_await FileIO::ReadBufferAsync(file); + // highlight-next-line + p.Resolve(CryptographicBuffer::EncodeToBase64String(buf)); + co_return; + }); + } + + private: + ReactContext context{nullptr}; + }; +} +``` + + + + This module can be referenced from the Turbo Module Registry: ```js