Skip to content

fix(barcode-scanner): resolve scan() after cleanup in windowed mode on iOS#3349

Open
afadil wants to merge 4 commits intotauri-apps:v2from
afadil:fix/barcode-scanner-windowed-ios-resolve
Open

fix(barcode-scanner): resolve scan() after cleanup in windowed mode on iOS#3349
afadil wants to merge 4 commits intotauri-apps:v2from
afadil:fix/barcode-scanner-windowed-ios-resolve

Conversation

@afadil
Copy link
Copy Markdown

@afadil afadil commented Mar 16, 2026

Fixes #3348

Summary

  • Reorder operations in metadataOutput so that camera cleanup and webview restoration run before invoke.resolve(), not after
  • In the original code, resolve() is called first, then destroy() immediately restores webView.isOpaque = true on the same main queue — this prevents the IPC response from reaching JavaScript in windowed mode
  • By resolving after cleanup, the webview is in the same opaque state where resolve() works in non-windowed mode

Test plan

  • scan({ windowed: true }) on iOS resolves correctly after scanning a QR code
  • scan({ windowed: false }) on iOS still works as before
  • cancel() still works correctly during an active scan
  • No duplicate detections (rapid metadataOutput calls are guarded by isScanning = false)

afadil added 3 commits March 15, 2026 16:03
…e on iOS

When scanning in windowed mode (`windowed: true`) on iOS, the
`metadataOutput` delegate calls `invoke?.resolve(jsObject)` followed
immediately by `destroy()`. The `destroy()` method restores
`webView.isOpaque = true` and resets `webView.backgroundColor`,
which interferes with the pending IPC callback delivery. As a result,
the JavaScript promise returned by `scan()` never resolves, even
though the native side successfully detects and returns the barcode
content.

This commit delays the `destroy()` call by 300ms using
`DispatchQueue.main.asyncAfter`, giving the IPC response enough time
to reach the JavaScript layer before the webview properties are
restored.

Fixes windowed mode scanning on iOS where scan() promise hangs
indefinitely after a successful barcode detection.
Set isScanning = false immediately after resolve() to prevent
metadataOutput from firing multiple times during the 300ms window
before destroy() runs.
…n iOS

Reorder operations in metadataOutput so that dismantleCamera() and
webview restoration run before invoke.resolve(). Previously, resolve()
was called first and destroy() immediately after, which restored
webView.isOpaque before the IPC response reached JavaScript — causing
the scan() promise to never settle in windowed mode.
@github-actions
Copy link
Copy Markdown
Contributor

Package Changes Through 044e2c3

There are 14 changes which include sql with minor, sql-js with minor, deep-link with patch, deep-link-js with patch, fs with minor, fs-js with minor, http with patch, http-js with patch, updater with patch, updater-js with patch, nfc with patch, nfc-js with patch, dialog with minor, dialog-js with minor

Planned Package Versions

The following package releases are the planned based on the context of changes in this pull request.

package current next
api-example 2.0.41 2.0.42
api-example-js 2.0.37 2.0.38
deep-link-example-js 2.2.10 2.2.11
deep-link 2.4.7 2.4.8
deep-link-js 2.4.7 2.4.8
fs 2.4.5 2.5.0
fs-js 2.4.5 2.5.0
dialog 2.6.0 2.7.0
dialog-js 2.6.0 2.7.0
http 2.5.7 2.5.8
http-js 2.5.7 2.5.8
nfc 2.3.4 2.3.5
nfc-js 2.3.4 2.3.5
persisted-scope 2.3.5 2.3.6
single-instance 2.4.0 2.4.1
sql 2.3.2 2.4.0
sql-js 2.3.2 2.4.0
updater 2.10.0 2.10.1
updater-js 2.10.0 2.10.1

Add another change file through the GitHub UI by following this link.


Read about change files or the docs at github.com/jbolda/covector

@afadil afadil requested a review from a team as a code owner March 25, 2026 20:07
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.

[barcode-scanner] iOS: scan() promise never resolves in windowed mode

1 participant