Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Windows support #121

Merged
merged 9 commits into from
Nov 24, 2020
Merged

Conversation

jaimecbernardo
Copy link
Contributor

Adds support for react-native-windows.
Implements PDF printing.
Updates the example for react-native 0.63 and adds the windows platform to it.
Updates the docs.
Adds a test to the sample and uses it for automatic CI for Windows.

Adds support for printing PDFs in react-native-windows.
Updates the documentation.
Also makes the reference to react-native-print relative, so that the
current version of the code can be tested.
Comment on lines 40 to 46
const std::string Name = "RNPrint";

// Default name for the print job.
inline static const std::string defaultJobName = "Document";

// Name for the XAML Canvas to add preview folders to.
inline static const std::string RNPrintCanvasName = "RNPrintCanvas";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these can be constexpr instead

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will change them to char[] as well, so that they can be constexpr.

Copy link
Contributor

@asklar asklar Oct 14, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

std::string can be constexpr with c++20, or you can use string_view in C++17. In general try avoiding C style character strings/arrays

winrt::event_token printToken;

REACT_INIT(RNPrint_Init)
void RNPrint_Init(ReactContext const& context) noexcept
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: spacing

windows/RNPrint/RNPrint.h Outdated Show resolved Hide resolved
}

// Generates a XAML page asynchronously.
concurrency::task<std::optional<xaml::UIElement> > GeneratePageAsync(PdfDocument pdfDocument, int pageNumber, PrintPageDescription pageDescription)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: you shouldn't need the space between > > anymore, I think? :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

muscle memory from times past :)

Comment on lines 125 to 128
float leftMargin = pageDescription.ImageableRect.X;
float topMargin = pageDescription.ImageableRect.Y;
float printableWidth = pageDescription.ImageableRect.Width;
float printableHeight = pageDescription.ImageableRect.Height;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make these const

Comment on lines 165 to 166
std::optional<xaml::UIElement> result = page;
return result;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return std::optionalxaml::UIElement(page);

or even more easily return page

[=](auto const& sender, GetPreviewPageEventArgs const& args) -> void
{
auto printDocArg = sender.as<PrintDocument>();
int pageNumber = args.PageNumber();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const


xaml::FrameworkElement root{ nullptr };

auto window = xaml::Window::Current();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this means this module won't work from xaml islands (which might be an ok compromise).
Another way to do this would be to fall back to use XamlUIService.XamlRoot if Window::Current is null

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will include the suggested workaround.
Is there a sample that uses xaml islands with react-native-windows that I could take a look into?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jaimecbernardo thanks! we don't have any modules that do so today since they mostly seem to work and not require access to something like Window::Current, but we do have code in the react-native-windows repo today that deals with this. See usages of XamlUIService.XamlRoot() and search for "isxamlisland" or something like that, we have a helper in the repo for it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PrintDocument printDoc = nullptr;
IPrintDocumentSource printDocSource;
int numberOfPages = 0;
std::map<int, std::optional<xaml::UIElement>> pageCollection; // references to the xaml pages
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it doesn't seem like you need this to be a map, you can just use std::vector

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These can be generated out of order and a map also would support a future feature to allow page range printing.
I think a map works better here.
Using a map also follows the Windows Universal Samples code for the Printing API more closely.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree that they can be generated out of order, but you are capturing the index i in the lambda, so maybe you can use that? not a big concern here, just looking to simplify since std::map is big and clunky

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also the part of the when_all later on which wants to send it to the printer in the right order.
Since we are generating a XAML element for each member in the collection, the std::map overhead shouldn't have much impact in comparison.
The collection also isn't expected to end up having many members, since it's one per page.

Comment on lines 362 to 363
if (options.find("html") != options.end())
printOptions.html = options["html"].AsString();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

avoid brace-less if statements whenever possible (here and other places)

@@ -0,0 +1,402 @@
#pragma once
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file is getting pretty large :) (github wouldn't show me the diff)
Can you break it up into a header and a source?

{
cleanUp();
std::stringstream errorCode;
errorCode << "0x" << std::hex << action.ErrorCode() << std::endl;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

undo the std::hex at the end?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean the std::endl?

I've used this code as a reference:
https://github.com/microsoft/react-native-windows-samples/blob/c1fe1ad0395d905c790b97edde76155efa9cced9/samples/NativeModuleSample/cppwinrt/windows/NativeModuleSample/AsyncMethodExamples.h#L68

But now that I think about it, that std::endl might not make sense.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a bug in the RNW code too :) basically std::hex changes state of the cout object, so any ints that come afterwards will be formatted as hex. AFAICT, endl only inserts a newline and doesn't reset the formatting options, so if someone prints a number to cout before anyone does << std::hex, it will show up in decimal, but if someone does it after this code runs, it will print as hex. Therefore it is unpredictable and we should reset to the default at the end of the line (<< std::dec << std::endl instead of std::endl)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you. SGTM :)

@jaimecbernardo
Copy link
Contributor Author

Hi @asklar.
Thank you for the feedback! 😄
I've added a couple of commits to address them.

@stmoy
Copy link

stmoy commented Nov 17, 2020

👋 Hi @christopherdro! @jaimecbernardo @asklar and myself are part of the team at Microsoft working on React Native for Windows. What do we need to do to get this PR pulled in?

@christopherdro
Copy link
Owner

Thank you for the PR everyone! I’ll have some free time next week during thanksgiving break to take a closer look.

On Windows, `react-native-print` needs an element in the visual tree to add the printable pages to.
It will look for a XAML `Canvas` named `RNPrintCanvas` and use it.
This needs to be added to the XAML tree of the screens where `react-native-print` is used.

Copy link
Contributor

@asklar asklar Nov 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jonthysell I wonder if we should bake logic into autolinking so that modules can check that certain conditions are met before they get autolinked, e.g. that there is this element. Or at least give a chance for modules to print out warnings / instructions of this kind.
Filed microsoft/react-native-windows#6553

Copy link
Contributor

@asklar asklar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

windows/RNPrint/RNPrint.cpp Outdated Show resolved Hide resolved
Co-authored-by: Alexander Sklar <asklar@microsoft.com>
@christopherdro christopherdro merged commit efa09ee into christopherdro:master Nov 24, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants