woocommerce-ios icon indicating copy to clipboard operation
woocommerce-ios copied to clipboard

[Backend Receipts] Infer best printing paper size from web view page size

Open iamgabrielma opened this issue 1 year ago • 1 comments

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

  1. On an eligible store for backend receipts (using WooCommerce 8.6.0-dev or 8.7.0-dev versions. You can use https://indiemelon.mystagingwebsite.com/ if needed)
  2. Go to Orders > Create a new order > Collect payment with any method
  3. Tap on See receipt (pull to refresh or re-navigate to the order if needed)
  4. 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)")

iamgabrielma avatar Feb 13 '24 02:02 iamgabrielma

WooCommerce iOS📲 You can test the changes from this Pull Request in WooCommerce iOS by scanning the QR code below to install the corresponding build.

App NameWooCommerce iOS WooCommerce iOS
Build Numberpr11976-d137a71
Version17.6
Bundle IDcom.automattic.alpha.woocommerce
Commitd137a713cb284b6117be02dadf42c26f2e16dadb
App Center BuildWooCommerce - Prototype Builds #8417
Automatticians: You can use our internal self-serve MC tool to give yourself access to App Center if needed.

wpmobilebot avatar Feb 13 '24 02:02 wpmobilebot

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

Screenshot 2024-03-11 at 16 13 07

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?)

Screenshot 2024-03-11 at 16 18 43

iamgabrielma avatar Mar 11 '24 10:03 iamgabrielma

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

printout-length

joshheald avatar Mar 11 '24 18:03 joshheald

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
Simulator Screenshot - iPhone 15 - 2024-03-12 at 09 05 22 Simulator Screenshot - iPhone 15 - 2024-03-12 at 09 05 52

iamgabrielma avatar Mar 12 '24 03:03 iamgabrielma

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) CleanShot 2024-03-12 at 09 35 26@2x

Second: CleanShot 2024-03-12 at 09 36 24@2x

Third: CleanShot 2024-03-12 at 09 36 43@2x

Final one, happens after confirming print on the iOS print controller: CleanShot 2024-03-12 at 09 37 51@2x

Cut length for method

ReceiptViewController.printInteractionController(_:cutLengthFor:) is never called...

Outcome: no change 😞

print screen

https://github.com/woocommerce/woocommerce-ios/assets/2472348/2d700222-db5f-4502-887a-2aa08ac848ea

joshheald avatar Mar 12 '24 09:03 joshheald

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.

iamgabrielma avatar Mar 14 '24 01:03 iamgabrielma

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:

malinajirka avatar Mar 15 '24 08:03 malinajirka

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.

iamgabrielma avatar Mar 18 '24 03:03 iamgabrielma