Repository navigation
feat!: add prewarm lifecycle APIs in v5 - #122
Conversation
| return; | ||
| } | ||
|
|
||
| if (e.nativeEvent.data === 'script-error') { |
There was a problem hiding this comment.
Only the literal 'script-error' marks a load failure. Other pre-ready failures go through the generic error branch instead: the loader .catch posts error.message / 'error', and onloadCallback posts e.name when render throws. Because readyRef is still false there, executeRequestedRef stays true and loadFailedRef stays false, and the loading timer has already been cleared above.
After that:
execute()returns early atif (executeRequestedRef.current && !loadFailedRef.current)reset()clears the flag, but the nextexecute()is neither ready nor failed, so it does nothing
With prewarm the component stays mounted, so the captcha is stuck until it is remounted. Could any error received before READY be treated as a load failure (set loadFailedRef and wire e.reset = retryApiLoad)?
There was a problem hiding this comment.
Fixed in ea1dcd8: initialization failures now recover through execute() or event.reset() without stalling; long error messages cannot become tokens.
|
|
||
| if (prewarm) { | ||
| return ( | ||
| <View |
There was a problem hiding this comment.
With prewarm, the full-screen Modal becomes an absoluteFill View. That only covers ConfirmHcaptcha's parent container, not the window. If the component sits in a nested View, under a navigator header, or next to sibling screens, the challenge and backdrop can be clipped or drawn underneath other UI. Without prewarm, Modal always covered the whole screen.
If this is intended, it should be documented in UPGRADING.md and the README (where to mount it). Alternatively, could the hidden/prewarming state stay a View while the visible state is shown in a Modal?
There was a problem hiding this comment.
Already addressed: README and upgrade guide document mounting after navigation in a full-screen root View and the parent/Modal limitations. Switching View/Modal would remount the warmed WebView.
| injectVerifyData(true); | ||
| // Event hooks can be retained across renders while a token is held. | ||
| const reset = useCallback(() => resetRef.current(), []); | ||
| resetRef.current = () => { |
There was a problem hiding this comment.
In prewarm mode, event.reset() can start a challenge nobody can see. Example: the app gets a token and calls hide(). Later 'expired' fires and the app calls event.reset(), as the README suggests. This calls setExecuteRequested(true) and injectVerifyData(true), but ConfirmHcaptcha's state.show is still false, so the challenge opens in the container at opacity 0 with pointerEvents="none". Without prewarm, the WebView was unmounted after hide(), so the same call did nothing.
Should ConfirmHcaptcha show itself again when a reset is requested while hidden? Or should the reset only reset the widget, not run it, while hidden?
There was a problem hiding this comment.
Fixed in ea1dcd8: event.reset() restores the hidden overlay when retrying; passive mode stays hidden.
| setExecuteRequested(false); | ||
| } | ||
| setIsLoading(false); | ||
| onMessageRef.current({ nativeEvent: { data: 'error', description: 'loading timeout' } }); |
There was a problem hiding this comment.
With prewarm, this timeout (and any script-error) reaches the app's onMessage while the component is mounting in the background, before the user asked for verification. If a prewarmed ConfirmHcaptcha mounts on app start while offline or on a slow network, the app gets { data: 'error', description: 'loading timeout' } about 15s later. Typical handlers show an error toast or call hide(), so the user sees a captcha error they never triggered.
Could prewarm load failures be held back until show()/execute() is called, and then either reported or retried?
There was a problem hiding this comment.
Fixed in ea1dcd8: idle preload failures/timeouts stay silent; show()/execute() retries them. Active-request failures still reach onMessage.
Multi-step auth flows pay WebView and SDK initialization costs when verification starts. Add opt-in
prewarmso apps initialize at startup, callexecute()on the credentials screen, and submit the token with the form.prewarmdefaults tofalse;execute()is equivalent toshow().Release as 5.0.0, with contract changes and upgrade steps. Legacy top-level
rqdata/phone props retain serialization and SDK reloads. UseverifyParamsfor changing data while preserving the warmed SDK.Changes
destroy()to wrapper and inline refs. Silently cancel requests and loading/token timers, detach journey consumers, and unmount the native WebView. Repeated calls are safe. Prop changes do not recreate it; the nextshow()/execute()creates a fresh WebView. Retained event reset hooks become inert. Explicit destruction also cancels legacy token timers from prior default-mode hide cycles.markUsed()remains scoped to its token.Modal.StyleSheet.absoluteFillAPI. Three regression cases remove the deprecated alias; each fails before the fix and passes afterward.Validation
Example.App.jsremains unchanged. Its native smoke tests cover actual challenge launch/dismiss/reopen and an auto-pass-key variant with token display and backend verification. See__e2e__/example.smoke.mdfor the fixture design.Exhaustiveness applies to the declared finite grammar and selected batching domain. Native tests use public integration keys and controlled SDK fixtures; they do not prove arbitrary OS/network scheduling, enterprise payload acceptance, physical-device performance, or leak freedom. Native views are unmounted, but OS/WebView process caches may prevent an immediate RSS decrease.