Skip to content

fix: provide fallback for recurrentAuthorizationStatus to prevent Settings page from blocking#1338

Open
kiyoakii wants to merge 1 commit intoovertake:masterfrom
kiyoakii:fix/settings-empty-notification-signal
Open

fix: provide fallback for recurrentAuthorizationStatus to prevent Settings page from blocking#1338
kiyoakii wants to merge 1 commit intoovertake:masterfrom
kiyoakii:fix/settings-empty-notification-signal

Conversation

@kiyoakii
Copy link

@kiyoakii kiyoakii commented Feb 18, 2026

Problem

If UNUserNotificationCenter.getNotificationSettings(completionHandler:) fails to call its completion handler for any reason (daemon unavailable, notification permission not yet requested, corrupted notification database state), the entire Settings page becomes permanently blank with no error indication.

Cause

AccountViewController renders the Settings list through a 13-signal combineLatest (line 1076). Signal 7 (of 13), recurrentAuthorizationStatus, chains through keyWindowUpdater into getNotificationSettings. If the completion handler never fires, this signal never emits, and combineLatest blocks all other 12 ready signals from rendering.

The search bar in Settings works fine because SearchSettingsController uses an independent pipeline without this dependency.

Fix

Add .single(.authorized) as an immediate default before the keyWindowUpdater chain, so Settings renders immediately. If getNotificationSettings eventually responds, the UI updates with the real status. If it never responds, Settings still works normally; in that edge case, the Notifications row may briefly lack its red warning icon for users who have denied permission, until the real status arrives. If it never arrives, the icon simply won't show.

Why only this signal?

The other 12 signals in the combineLatest already have initial values or are backed by local data (cached preferences, database queries, etc.) that emit synchronously. recurrentAuthorizationStatus is the only one that depends entirely on an async system API call with no fallback. Ideally all signals feeding into a UI-critical combineLatest should have defaults, but this PR targets the one confirmed to cause issues in practice.

Verification

This bug affected my machine for months, persisting across app reinstalls, macOS upgrades, and complete data wipes. The Settings page was blank but search within Settings worked normally, which pointed to a data pipeline issue rather than a rendering bug.

Diagnosed via runtime injection (dlopen + ObjC method swizzling) into a running Telegram process:

  • Used macOS heap tool to find the Atomic<SignalCombineState> tracking this combineLatest, confirmed 12/13 signals emitted, index 7 missing
  • Swizzled getNotificationSettingsWithCompletionHandler: on UNUserNotificationCenter, confirmed the completion handler was never called
  • Injected a mock UNNotificationSettings with .authorized status as a workaround, Settings populated immediately

The root cause on my machine was usernotificationsd stuck in a crash loop (LastExitStatus = -9), making all notification APIs unresponsive. After manually restarting the daemon and granting notification permission, the issue was resolved. However, this fix ensures Settings remains functional regardless of the notification subsystem's health.

@CLAassistant
Copy link

CLAassistant commented Feb 18, 2026

CLA assistant check
All committers have signed the CLA.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

2 participants