-
Notifications
You must be signed in to change notification settings - Fork 2
Feat: force dismiss captive signing #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -543,6 +543,16 @@ internal final class DocuSignManager: NSObject { | |
| } | ||
| _ = pendingResolved // silence unused-warning; kept for future telemetry | ||
|
|
||
| // DSMManager APIs (clearAllWebCookies, logout) must run on the main thread. | ||
| // Expo async functions are dispatched on AsyncFunctionQueue (non-main), so | ||
| // we must hop to main before touching any DSMManager API. | ||
| guard Thread.isMainThread else { | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The guard sits after the state mutation, so the Hop to main at the top of the function. Better still, put the guard inside |
||
| DispatchQueue.main.async { [weak self] in | ||
| self?.endSigningSession(completion: completion) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| } | ||
| return | ||
| } | ||
|
|
||
| clearWebCookiesAsync { [weak self] in | ||
| guard let self = self else { | ||
| completion() | ||
|
|
@@ -571,8 +581,10 @@ internal final class DocuSignManager: NSObject { | |
| /// Safe to call when the SDK was never initialized: returns immediately | ||
| /// without touching DSMManager. | ||
| func reset(completion: @escaping () -> Void) { | ||
| var hadPending = false | ||
| stateQueue.sync { | ||
| if let pending = pendingCompletion { | ||
| hadPending = true | ||
| let outcome = SigningOutcome( | ||
| status: "cancelled", | ||
| envelopeId: currentEnvelopeId ?? "", | ||
|
|
@@ -585,6 +597,23 @@ internal final class DocuSignManager: NSObject { | |
| } | ||
| } | ||
|
|
||
| // Force-dismiss the captive signing modal if one is on screen. reset() is | ||
| // called on session teardown (e.g. END_CONSULTATION) which can arrive while | ||
| // the DocuSign WebView is still presented; the SDK only dismisses its own UI | ||
| // on user Finish/Cancel, so we dismiss the presented modal here. Gated on | ||
| // hadPending so an unrelated modal is never torn down. | ||
| if hadPending { | ||
| DispatchQueue.main.async { | ||
| let root = UIApplication.shared.connectedScenes | ||
| .compactMap { $0 as? UIWindowScene } | ||
| .flatMap { $0.windows } | ||
| .first(where: { $0.isKeyWindow })?.rootViewController | ||
| if root?.presentedViewController != nil { | ||
| root?.dismiss(animated: true) | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The dismissal is not sequenced with the teardown or with the promise. There is no completion handler here, so Small thing on the same lines: |
||
| } | ||
| } | ||
| } | ||
|
Comment on lines
+605
to
+615
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This dismisses every modal above the root view controller, including ones the host app owns.
The SDK hands you the controller you actually want. Both |
||
|
|
||
| let needsTeardown = stateQueue.sync { _isInitialized || _hasLoggedIn } | ||
| guard needsTeardown else { | ||
| completion() | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dead code in the function you are already touching.
var pendingResolvedon 529 is assigned and never read, and this line exists only to silence the warning. Drop both.