* fix: Import cloud-backed PKPASS files off the main thread
Fixes#2464
* Address review: move all import parsing off the main thread, restore failure toasts
- Route image/PDF/pkpass/espass imports through one background importFile
- Restore errorReadingFile / errorReadingImage / noBarcodeFound toasts via a
main-looper-marshalling showToast helper
- Replace fixed-timeout awaits in the activity tests with a waitFor predicate
* Start the import coroutine on the main dispatcher, hop to IO for the read
launch(Dispatchers.IO) starts the coroutine on a background thread immediately,
so a paused Robolectric main looper never drives it and the activity tests time
out. Launch on the lifecycle scope's default (main) dispatcher and wrap only the
blocking read in withContext(Dispatchers.IO).
* Fix the two failing import tests
Two separate bugs, both in the tests I added:
- new Intent(ACTION_VIEW, uri).setType(...) clears the data URI (setType and
setData clear each other), so the activity received a null Uri and the read
never started. Use setDataAndType.
- The intermediate-state assertions (no started activity / RESULT_CANCELED)
are not observable: waiting on the main looper drains it, and Robolectric
drains it again during .visible(), so the import has already run to
completion by the time the test regains control. Assert the off-main-thread
read directly instead, which is the property these tests exist to prove.
* fix: make showToast reusable with a caller-supplied duration
Take the toast length as a parameter instead of hardcoding LENGTH_LONG, so
the helper can serve short toasts too, and document why it exists: it shows
the toast directly when already on the main looper and otherwise posts it
there, which is what the off-main-thread import path needs.
Reorders the modifiers to the file's `static private` convention.
All existing call sites pass LENGTH_LONG, so behavior is unchanged.
---------
Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
This improves the sizing of the notification icons and uses a generic
sync icon for the Bluetooth server running (so users don't get used to
ignoring the Catima icon).
Generated throudh Android Studio New -> Image Asset -> Notification
Icons -> Path: .design/master_monochrome.svg -> Trim: Yes -> Padding: 0%
* Improve ShortcuHelper.updateShortcuts to take all actions into account
* Remove now useless calls to removeShortcut
* Add doc to explain the usage of maxShortcut
* Fix typo in doc of maxShortcuts
This will not catch one edge case: use exporting a backup in Catima
2.41.0 - 2.41.2, then uninstall Catima, then installing Catima 2.41.3
and then importing the database. But this seems rare enough to be
acceptable.
This fixes old pkpass files imported before Catima 2.41.0 to be forced
to "Automatic", which may guess UTF-8. New pkpass files will have the
encoding read from the file and newly scanned barcodes will use
Automatic.
This does have the unfortunate side effect of everyone who already
scanned a QR code with UTF-8 data since Catima 2.41.0 to have it forced
to ISO-8859-1, but it will fix Deutschlandtickets imported before 2.41.0
which is a rather large amount of the Catima userbase.
If zxing is not explicitly told a barcode is UTF-8, it may render it
incorrectly. Which caused
https://github.com/CatimaLoyalty/Android/issues/2555.
However, when an encode hint is set, it will cause zxing to set an ECI
hint inside the barcode, which some scanners may trip over and cause
scanning failures, leading to
https://github.com/CatimaLoyalty/Android/issues/2921.
This change only passes the encoding in automatic mode if zxing
explicitly guesses it to be UTF-8, and otherwise doesn't pass anything,
to keep the ECI empty. This might need to be expanded for other types
like SJIS, but as nobody ever reported such a bug let's assume it's not
necessary for now.
This simplifies the codebase and new Compose implementation. If this
feature is really wanted by the community, it could possibly be
reimplemented in a much more flexible way (choosing the exact colour)
after all UIs are migrated to Compose, as Compose can generate a theme
based on just a primary colour.