-
Notifications
You must be signed in to change notification settings - Fork 39
gui: deny execution of hold&ask events immediately if unavailable #749
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’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
📝 WalkthroughWalkthroughAdds a guarded reply invocation in SNTBinaryMessageWindowView: introduces a Changes
Sequence Diagram(s)(omitted) Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes 🚥 Pre-merge checks | ✅ 2✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Comment |
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.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Source/gui/SNTBinaryMessageWindowView.swift (1)
290-300: Avoid repeated replyCallback invocations from SwiftUI body.SwiftUI recomputes
bodyfrequently; callingreplyCallback?(false)here can fire multiple times and can also race with user clicks on Dismiss/Open, resulting in duplicate replies. Gate the auto-deny to a single execution and consider closing/disable UI after auto-deny.🔧 Proposed fix (single-shot auto-deny)
@@ `@State` public var preventFutureNotifications = false `@State` public var preventFutureNotificationPeriod: TimeInterval = NotificationSilencePeriods[0] + `@State` private var didAutoDeny = false @@ if event?.holdAndAsk ?? false { let (canAuthz, err) = CanAuthorizeWithTouchID() if !canAuthz { - if let errMsg = err { - Text(errMsg.localizedDescription).foregroundColor(.red) - } - - // If this is a holdAndAsk event but TouchID is not available, - // call the reply block immediately with false. - let _ = replyCallback?(false) + Group { + if let errMsg = err { + Text(errMsg.localizedDescription).foregroundColor(.red) + } + } + .task { + guard !didAutoDeny else { return } + didAutoDeny = true + replyCallback?(false) + window?.close() // Optional: prevents further user actions after reply + } } }
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.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Source/gui/SNTBinaryMessageWindowView.swift (1)
371-385: Inconsistent callback invocation bypasses the guard.The guard clause at lines 373-375 directly invokes
replyCallbackinstead of usingcallReplyCallback. This bypasses the duplicate-call protection and doesn't setrepliedToCallback, which could lead to the callback being invoked twice if another code path runs afterward.🐛 Proposed fix
func standAloneButton() { guard let e = self.event else { - if let cb = self.replyCallback { - cb(false) - } + callReplyCallback(false) return } SNTAuthorizationHelper.authorizeExecution(for: e) { success in callReplyCallback(success) DispatchQueue.main.sync { window?.close() } } }
🤖 Fix all issues with AI agents
In `@Source/gui/SNTBinaryMessageWindowView.swift`:
- Around line 257-263: callReplyCallback currently ignores its response
parameter and always invokes replyCallback(false); change it to pass the actual
response value and keep the early-return guard and repliedToCallback update.
Specifically, in function callReplyCallback(_ response: Bool) replace the
invocation of replyCallback with replyCallback(response) and ensure
repliedToCallback is set to true after invoking replyCallback; reference
symbols: callReplyCallback, replyCallback, repliedToCallback, response.
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.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
Source/gui/SNTBinaryMessageWindowView.swift (1)
372-383: Ensure reply callback and@Statemutation run on the main thread.
callReplyCallbackmutates@State repliedToCallback(line 253, 262).SNTAuthorizationHelper.authorizeExecutioninternally usesLAContext.evaluatePolicy, which calls its completion handler off the main thread. This causescallReplyCallbackto mutate@Statefrom a background thread, triggering "Publishing changes from background threads" warnings. Additionally,DispatchQueue.main.sync(line 382) called from an off-main completion risks deadlock. The nil-event guard (lines 371-375) also bypasses main dispatch, creating inconsistent behavior.Use
DispatchQueue.main.asyncto dispatch once to main and callcallReplyCallbackand window close there. Apply this pattern consistently to both the nil-event guard and the authorization completion paths.Suggested fix
func standAloneButton() { guard let e = self.event else { - if let cb = self.replyCallback { - cb(false) - } + DispatchQueue.main.async { + callReplyCallback(false) + window?.close() + } return } SNTAuthorizationHelper.authorizeExecution(for: e) { success in - callReplyCallback(success) - DispatchQueue.main.sync { - window?.close() - } + DispatchQueue.main.async { + callReplyCallback(success) + window?.close() + } } }
🧹 Nitpick comments (1)
Source/gui/SNTBinaryMessageWindowView.swift (1)
253-263: Prevent re‑entrancy by flipping the guard before invoking the callback.If
replyCallbackre-enters (directly or indirectly), the flag is stillfalseand the callback can fire twice. SetrepliedToCallback = truebefore invoking the callback.♻️ Proposed fix
func callReplyCallback(_ response: Bool) { guard !repliedToCallback else { return } - if let cb = replyCallback { - cb(response) - } - repliedToCallback = true + repliedToCallback = true + replyCallback?(response) }
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
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.
Actionable comments posted: 1
🤖 Fix all issues with AI agents
In `@Source/gui/SNTBinaryMessageWindowView.swift`:
- Around line 371-379: The guard path in standAloneButton currently invokes
replyCallback directly (cb(false)) which bypasses the double-call guard; change
this to use the existing callReplyCallback(...) helper so repliedToCallback is
set and duplicate invocations are prevented. In standAloneButton, when event is
nil and replyCallback exists, dispatch to main and call callReplyCallback(false)
(or the equivalent helper) instead of calling cb(false) directly; ensure you
reference replyCallback, callReplyCallback, and repliedToCallback so the helper
marks repliedToCallback = true and nulls out replyCallback consistently.
Prior to this change, if a hold & ask execution triggered a Santa dialog but biometry is not available (and the
EnableStandalonePasswordFallbackkey is not set to true) the execution would remain held until the dialog was dismissed. With this change, the execution will be denied immediately.