feat(apple): redesign pairing onboarding - #1
Merged
Conversation
Deep-link and cold-start joins run with destination == nil, so the existing error/joining state only rendered inside the scanner/manual sheets and was invisible for links opened via onOpenURL or pendingJoinPayload. Add an inline progress/error status to the base JoinView shown whenever no sheet is on screen, disable the action buttons while a join is in flight, and stop present() from resetting error state while a join is still running.
The onCode closure's `guard !joining` could never block a second callback: UIViewControllerRepresentable.makeCoordinator runs once, so Coordinator captured this closure (and the joining value baked into it) only on the sheet's first render. Reentrancy is actually enforced synchronously by Coordinator's `fired` flag plus beginJoin's own `guard !joining`, which runs in the same actor turn as this callback. Drop the dead guard and document why it's safe.
firstMatch(of:) only ever looked at one shape match per transcript candidate, so a rejected false-positive on a candidate permanently hid any real code recognized later in that same candidate. Switch to matches(of:) and walk all matches, skipping ones already rejected.
.textInputAutocapitalization(.characters) on the manual code field can uppercase a fully-typed sitrep://join link (e.g. SITREP://JOIN?...), but canSubmit and resolveJoin compared scheme/host case-sensitively via URLComponents, so such input could never validate or resolve. Lowercase only the scheme/host comparison; leave the rest of the string, and the extracted query values, in their original case.
ScannerJoinView and ManualJoinView already set interactiveDismissDisabled(joining) to block swipe-to-dismiss during a join, but their toolbar close buttons stayed tappable, letting the user dismiss the sheet mid-join through the button instead.
performJoin's blanket catch treated every failure — timeouts, offline, 5xx — the same as a server-rejected code: it showed "code invalid or expired" and permanently blacklisted the code via rejectAndResume, deadlocking a perfectly valid code against a flaky connection. Only an explicit APIError.badStatus in the 4xx range now blacklists the code; everything else (transport errors, timeouts, 5xx) shows a network-check message and resumes scanning via the new ScannerControl.resume()/Coordinator.resume(), which re-arms the scanner without adding the code to `rejected`.
ScannerJoinView only checked DataScannerViewController.isSupported, so a denied/restricted camera permission fell through to a black camera layer with no explanation or way out, and startScanning() failures were silently swallowed with try?. Check AVCaptureDevice.authorizationStatus(for: .video) before showing the scanner: request access when .notDetermined, and show an explicit "open Settings" screen instead of the camera view when denied or restricted (refreshed on scenePhase becoming active, so returning from Settings revives the flow without reopening the sheet). Route startScanning() through a Coordinator.start() that reports failures via a new onScanningError callback instead of using try?, rendering a readable error state rather than a dead camera preview.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Validation
Risk