mirror of
https://github.com/awizemann/scarf.git
synced 2026-05-10 10:36:35 +00:00
fix(ios-notifications): feature-gate Approve/Deny stub actions
Push Notifications capability is disabled in the iOS target, so the APNS code path can't fire today — but the `SCARF_PENDING_PERMISSION` category was registered unconditionally, exposing the stub-only `APPROVE_PERMISSION` / `DENY_PERMISSION` action handlers as a route iOS could surface action buttons on if a notification ever slipped through. Add `NotificationRouter.apnsEnabled` (=`false`) and gate `registerCategories()` behind it. While `false`, the category is explicitly cleared so iOS has no path to route a tap to the stubs. The gate is the single switch — flipping it requires the capability + sender + real handler implementations to all land together. Verified: iOS build succeeds. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,23 @@ import ScarfIOS
|
|||||||
final class NotificationRouter: NSObject, UNUserNotificationCenterDelegate {
|
final class NotificationRouter: NSObject, UNUserNotificationCenterDelegate {
|
||||||
static let shared = NotificationRouter()
|
static let shared = NotificationRouter()
|
||||||
|
|
||||||
|
/// Master gate for the APNs / push pipeline. While `false`:
|
||||||
|
///
|
||||||
|
/// - The `SCARF_PENDING_PERMISSION` category (Approve / Deny actions)
|
||||||
|
/// is NOT registered, so even if a notification with that
|
||||||
|
/// `categoryIdentifier` slipped through somehow, iOS would render
|
||||||
|
/// it without action buttons rather than route the tap to the
|
||||||
|
/// stub-only `APPROVE_PERMISSION` / `DENY_PERMISSION` handlers.
|
||||||
|
/// - `registerForRemoteNotifications()` stays uncalled.
|
||||||
|
///
|
||||||
|
/// Flip to `true` only when (a) the Push Notifications capability is
|
||||||
|
/// enabled in the Xcode target, (b) Hermes ships a push sender, and
|
||||||
|
/// (c) `APPROVE_PERMISSION` / `DENY_PERMISSION` cases below have real
|
||||||
|
/// implementations (not just `logger.info` stubs). This gate is the
|
||||||
|
/// single switch — flipping it in isolation should not cause the
|
||||||
|
/// stub handlers to silently swallow real user intent.
|
||||||
|
static let apnsEnabled = false
|
||||||
|
|
||||||
private let logger = Logger(subsystem: "com.scarf", category: "NotificationRouter")
|
private let logger = Logger(subsystem: "com.scarf", category: "NotificationRouter")
|
||||||
|
|
||||||
/// Coordinator reference set by ScarfGoTabRoot on appear so the
|
/// Coordinator reference set by ScarfGoTabRoot on appear so the
|
||||||
@@ -95,7 +112,19 @@ final class NotificationRouter: NSObject, UNUserNotificationCenterDelegate {
|
|||||||
/// Install the notification category that exposes Approve / Deny
|
/// Install the notification category that exposes Approve / Deny
|
||||||
/// action buttons on the lock screen. Safe to call multiple times
|
/// action buttons on the lock screen. Safe to call multiple times
|
||||||
/// — registerCategories replaces.
|
/// — registerCategories replaces.
|
||||||
|
///
|
||||||
|
/// **Gated on `apnsEnabled`.** Until Hermes ships a real push sender
|
||||||
|
/// and the `APPROVE_PERMISSION` / `DENY_PERMISSION` handlers have
|
||||||
|
/// real implementations, register the empty set so iOS has no
|
||||||
|
/// category by which to route action-tapped notifications to the
|
||||||
|
/// stub handlers. When `apnsEnabled` flips to `true`, the category
|
||||||
|
/// is installed and the handlers are simultaneously expected to be
|
||||||
|
/// real.
|
||||||
func registerCategories() {
|
func registerCategories() {
|
||||||
|
guard Self.apnsEnabled else {
|
||||||
|
UNUserNotificationCenter.current().setNotificationCategories([])
|
||||||
|
return
|
||||||
|
}
|
||||||
let approve = UNNotificationAction(
|
let approve = UNNotificationAction(
|
||||||
identifier: "APPROVE_PERMISSION",
|
identifier: "APPROVE_PERMISSION",
|
||||||
title: "Approve",
|
title: "Approve",
|
||||||
|
|||||||
Reference in New Issue
Block a user