woocommerce-ios
woocommerce-ios copied to clipboard
[Backend Receipts] Infer best printing paper size from web view page size
Closes: #11870
Description
This PR attempts to address the problem of wasted paper on backend receipts based on printer configuration settings.
During testing we've seen that the default parameters we get from the printer might not be the best for receipt printing, and there's an excess of paper being used with the default settings.
Changes
In order to minimize this problem we intercept and modify the UIPrintInteractionControllerDelegate.printInteractionController(_:choosePaper:)
delegate method to, rather than using the default paper size given by the system, return a paper size inferred from the webview's page size that holds the receipt.
If we cannot infer this size, we will just return the default paper provided by the system.
Testing instructions
- On an eligible store for backend receipts (using WooCommerce
8.6.0-dev
or8.7.0-dev
versions. You can use https://indiemelon.mystagingwebsite.com/ if needed) - Go to Orders > Create a new order > Collect payment with any method
- Tap on
See receipt
(pull to refresh or re-navigate to the order if needed) - Tap print and print the receipt on a physical printer
Ideally we should be able to infer a paper size based on the web view where the receipt has been rendered, which will return less wasted paper. If we cannot infer this, we'll see the "Unable to retrieve inferred paper size from the web view. Using default paper provided by the system." message in the console.
It can also be helpful to add some debugging print statements to the printInteractionController(_ printInteractionController: UIPrintInteractionController, choosePaper paperList: [UIPrintPaper]
delegate method to see the differences in estimated paper size by the system:
print("Estimated paper size: \(String(describing: paperSize))")
print("Best paper size: \(updatedPaper.paperSize)")
📲 You can test the changes from this Pull Request in WooCommerce iOS by scanning the QR code below to install the corresponding build.
App Name | ![]() |
|
Build Number | pr11976-d137a71 | |
Version | 17.6 | |
Bundle ID | com.automattic.alpha.woocommerce | |
Commit | d137a713cb284b6117be02dadf42c26f2e16dadb | |
App Center Build | WooCommerce - Prototype Builds #8417 |
Thanks for testing @joshheald , with the print simulator I'm unable to replicate this case, as no matter which roll I select, it always wants to use a 36" one, that said each test shows the topMargin
and bottomMargin
as 0
Since this could come from using a real printer, I'm setting the margins specifically as they were in the legacy renderer on https://github.com/woocommerce/woocommerce-ios/pull/11976/commits/e251cd05551a38175590d69159b9b5684782e326, and see if that fixes the additional 600 you're seeing in each end.
Along with this, I've also made an additional change on https://github.com/woocommerce/woocommerce-ios/pull/11976/commits/b12de76a5a6f5eb6a26ddcc3da621f76f5db6a65 following the original implementation, by forcing a maximum for both width and height. From my testing it would seem that this should work better, as before, when I selected the 36" roll the rendering would fit the page but was spread out to occupy the full width, now the rendering is constrained to the typical roll size (perhaps since we're setting the bottom inset now we could remove the height constraint, so it can be as long a it needs?)
Unfortunately, no improvement 😢
I kind of feel like it's the printer that's at fault? It's so difficult to connect to – the only way I've managed that is by having the printer be the Wifi access point, and then connecting the phone to that. It should be able to join the general wifi network, or connect via Bluetooth... but AFAICT, you need to connect it to a computer and use a separate app, or use a fleet config deployment tool to do that. Merchants just aren't going to do those things, so it needs to work in the only way that it can connect out of the box.
But perhaps we need to find a different printer to recommend instead? I did a print of the old style receipt (still using this branch) and it has the same issue.
https://github.com/woocommerce/woocommerce-ios/assets/2472348/f064524c-ec87-4e3d-b3fc-b120d0a237f6
PD: Please feel free to check this out after hack week!
I kind of feel like it's the printer that's at fault? I did a print of the old style receipt (still using this branch) and it has the same issue.
That's interesting, the printing configuration for the old and new style are completely separate, so if both have the same problem then it could be that's the printer indeed. By digging into the older PRs that implemented this, I found that in https://github.com/woocommerce/woocommerce-ios/pull/5562 the RJ-4250WB model seems to have some peculiarities and the cutLengthFor
delegate method had to be implemented as well to resolve the problem of "too much paper being used".
If this fix attempt doesn't resolve it, perhaps we can try another printer (I recall Jirka has a different model) and see if there' any difference.
When attempting to implement this method I found some things that were unexpected:
The cutLengthFor
delegate is called before choosePaper
delegate, so at this point we don't really have a "best paper" since we haven't selected it yet. This causes that if we just go ahead and print, the first print attempt is not correct, while from the second print attempt onwards looks better since uses the previously selected best paper. This also can be replicated by switching printers, once we switch to a different printer, and then switch back to the one we intend to use, the printing preview displays correctly.
Both printFormatter and printPageRenderer are also nil at that point, so moving the delegate a bit earlier in the cycle rather than when we tap on "print" at least allows for the printFormatter to be set, which doesn't solve much, but seems better.
After some experimentation I believe to have resolved it with the latest commits https://github.com/woocommerce/woocommerce-ios/pull/11976/commits/8dd8771e59a629b6b87a3f846ddcc8967b94ca5f and https://github.com/woocommerce/woocommerce-ios/pull/11976/commits/d137a713cb284b6117be02dadf42c26f2e16dadb (but I can't be sure without the hardware 😞 ). We can see this in the printing preview, as well as in the debugger:
// 1. Using the 36" roll printer, without cutLengthFor delegate, paper height on 1st print
inferPaperSize height: 2592.0
// 2. Using the 36" roll printer, without cutLengthFor delegate, paper height in subsequent prints
inferPaperSize height: 841.8897637795276
// Using the 36" roll printer, using cutLengthFor delegate, on all prints
inferPaperSize height: 841.8897637795276
The previews show as well that while we're still in the same page width-wise, we're not using the full available length. There's still some additional space there, but looks like an improvement compared with before:
Before | After |
---|---|
Choose paper – gets something sensible, the same result every time
All the calls to ReceiptViewController.printInteractionController(_:choosePaper:)
make it to the final return, and get the same paper type:
First paper type (after opening print controller)
Second:
Third:
Final one, happens after confirming print on the iOS print controller:
Cut length for method
ReceiptViewController.printInteractionController(_:cutLengthFor:)
is never called...
Outcome: no change 😞
https://github.com/woocommerce/woocommerce-ios/assets/2472348/2d700222-db5f-4502-887a-2aa08ac848ea
Thanks again for testing Josh, appreciatted 🙇
TBH I'm a bit lost on how to follow through, the response of the printer seems to be different that the responses I get when using the simulated printer (that said, the simulated printer doesn't allow me to use the specific paper we want either). There are also questions like why the cutLengthFor
delegate wouldn't even be called when it's called every single time using the simulated one, and this bit it's what should be fixing the extra-length issue you're seeing. My only clue is that Apple docs say that this method is only called on printers that support such feature, so perhaps yours don't have this option?
Some printers can cut a roll of print paper at a particular length. If you implement this method in your delegate, then it may be called during a print job.
@malinajirka when you have the time, would you mind to try a printout with your printer using this branch? I'm curious to understand if it's the specific printer, something wider, and if looks better or worst than your previous attempt.
Thank you both for continue investigating this - printing on iOS seems to be quite a pain.
I've tested this on my printer (it's the exact same model as Josh has) - the results are definitely not optimal, but significantly better than before. It wastes some paper but not a meter of it as before. These are the two results I got depending on the print-settings:
That looks much better indeed, thanks for testing Jirka 🙇
@joshheald what are your thoughts about merging this bit into trunk? I'm torn because I see in your testing doesn't work as expected, but on the other side, Jirka's test shows a meaningful improvement. Overall I'd say that the changes might improve the existing experience, and at this point, if we'd like to prioritize further work on this I think I should at least get a printer and be able to test myself without relying on reviews.