Telegram-style date pills в чат-листе — sticky headers с push-переходом между секциями

This commit is contained in:
2026-03-31 02:48:28 +05:00
parent 3fc15c14ff
commit 6b55baacd8
10 changed files with 408 additions and 42 deletions

View File

@@ -14,9 +14,9 @@ final class NotificationService: UNNotificationServiceExtension {
private static let badgeKey = "app_badge_count"
/// Android parity: multiple key names for sender public key extraction.
/// Server currently sends `from` field in data-only push.
/// Server sends `dialog` field (was `from`). Both kept for backward compat.
private static let senderKeyNames = [
"from", "sender_public_key", "from_public_key", "fromPublicKey",
"dialog", "sender_public_key", "from_public_key", "fromPublicKey",
"public_key", "publicKey"
]
private static let senderNameKeyNames = [
@@ -86,7 +86,7 @@ final class NotificationService: UNNotificationServiceExtension {
content.sound = .default
content.categoryIdentifier = "call"
let callerKey = content.userInfo["from"] as? String
let callerKey = content.userInfo["dialog"] as? String
?? Self.extractSenderKey(from: content.userInfo)
let contactNames = shared?.dictionary(forKey: "contact_display_names") as? [String: String] ?? [:]
let callerName = contactNames[callerKey]
@@ -116,8 +116,8 @@ final class NotificationService: UNNotificationServiceExtension {
// 1. Add sound for vibration server APNs payload has no sound field.
content.sound = .default
// 2. Extract sender key server sends `from` field.
let senderKey = content.userInfo["from"] as? String
// 2. Extract sender key server sends `dialog` field (was `from`).
let senderKey = content.userInfo["dialog"] as? String
?? Self.extractSenderKey(from: content.userInfo)
// 3. Filter muted chats BEFORE badge increment muted chats must not inflate badge.
@@ -151,9 +151,9 @@ final class NotificationService: UNNotificationServiceExtension {
?? Self.firstNonBlank(content.userInfo, keys: Self.senderNameKeyNames)
if let resolvedName, !resolvedName.isEmpty {
updatedInfo["sender_name"] = resolvedName
if content.title.isEmpty {
content.title = resolvedName
}
// Always prefer local name server sends title at push time,
// but user may have a custom contact name in App Group cache.
content.title = resolvedName
}
content.userInfo = updatedInfo