Telegram-style date pills в чат-листе — sticky headers с push-переходом между секциями
This commit is contained in:
@@ -154,7 +154,13 @@ private extension ChatRowView {
|
||||
if isTyping && !dialog.isSavedMessages {
|
||||
return "typing..."
|
||||
}
|
||||
if dialog.lastMessage.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
|
||||
let raw = dialog.lastMessage.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
if raw.isEmpty {
|
||||
return "No messages yet"
|
||||
}
|
||||
// Safety net: never show encrypted ciphertext (ivBase64:ctBase64) to user.
|
||||
// This catches stale data persisted before isGarbageText was improved.
|
||||
if Self.looksLikeCiphertext(raw) {
|
||||
return "No messages yet"
|
||||
}
|
||||
if let cached = Self.messageTextCache[dialog.lastMessage] {
|
||||
@@ -170,6 +176,27 @@ private extension ChatRowView {
|
||||
Self.messageTextCache[dialog.lastMessage] = result
|
||||
return result
|
||||
}
|
||||
|
||||
/// Detects encrypted payload formats that should never be shown in UI.
|
||||
private static func looksLikeCiphertext(_ text: String) -> Bool {
|
||||
// CHNK: chunked format
|
||||
if text.hasPrefix("CHNK:") { return true }
|
||||
// ivBase64:ctBase64 or hex-encoded XChaCha20 ciphertext
|
||||
let parts = text.components(separatedBy: ":")
|
||||
if parts.count == 2 {
|
||||
let base64Chars = CharacterSet.alphanumerics.union(CharacterSet(charactersIn: "+/="))
|
||||
let bothBase64 = parts.allSatisfy { part in
|
||||
part.count >= 16 && part.unicodeScalars.allSatisfy { base64Chars.contains($0) }
|
||||
}
|
||||
if bothBase64 { return true }
|
||||
}
|
||||
// Pure hex string (≥40 chars, only hex digits) — XChaCha20 wire format
|
||||
if text.count >= 40 {
|
||||
let hexChars = CharacterSet(charactersIn: "0123456789abcdefABCDEF")
|
||||
if text.unicodeScalars.allSatisfy({ hexChars.contains($0) }) { return true }
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Trailing Column
|
||||
|
||||
Reference in New Issue
Block a user