mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-08-08 06:56:10 +00:00
fix: show verified seal next to sender names in chat (#1506)
Surface fingerprint verification in the message timeline so a verified contact is distinguishable from an impersonator without opening the fingerprint sheet. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
4ef5558d7b
commit
e7f4ef0912
@ -41,7 +41,9 @@ final class ChatMessageFormatter {
|
||||
}()
|
||||
|
||||
let isDark = colorScheme == .dark
|
||||
if let cachedText = message.getCachedFormattedText(isDark: isDark, isSelf: isSelf, variant: theme.formatCacheVariant) {
|
||||
let isVerifiedSender = !isSelf && isVerifiedSender(of: message)
|
||||
let cacheVariant = theme.formatCacheVariant + (isVerifiedSender ? "-vf" : "")
|
||||
if let cachedText = message.getCachedFormattedText(isDark: isDark, isSelf: isSelf, variant: cacheVariant) {
|
||||
return cachedText
|
||||
}
|
||||
|
||||
@ -66,6 +68,9 @@ final class ChatMessageFormatter {
|
||||
suffixStyle.foregroundColor = baseColor.opacity(0.6)
|
||||
result.append(AttributedString(suffix).mergingAttributes(suffixStyle))
|
||||
}
|
||||
if isVerifiedSender {
|
||||
appendVerifiedSeal(to: &result, baseColor: baseColor, design: design)
|
||||
}
|
||||
result.append(AttributedString("> ").mergingAttributes(senderStyle))
|
||||
|
||||
let content = message.content
|
||||
@ -335,7 +340,7 @@ final class ChatMessageFormatter {
|
||||
result.append(timestamp.mergingAttributes(timestampStyle))
|
||||
}
|
||||
|
||||
message.setCachedFormattedText(result, isDark: isDark, isSelf: isSelf, variant: theme.formatCacheVariant)
|
||||
message.setCachedFormattedText(result, isDark: isDark, isSelf: isSelf, variant: cacheVariant)
|
||||
return result
|
||||
}
|
||||
|
||||
@ -356,6 +361,7 @@ final class ChatMessageFormatter {
|
||||
|
||||
let isDark = colorScheme == .dark
|
||||
let baseColor: Color = isSelf ? .orange : peerColor(for: message, isDark: isDark)
|
||||
let isVerifiedSender = !isSelf && isVerifiedSender(of: message)
|
||||
|
||||
if message.sender == "system" {
|
||||
var style = AttributeContainer()
|
||||
@ -381,6 +387,9 @@ final class ChatMessageFormatter {
|
||||
suffixStyle.foregroundColor = baseColor.opacity(0.6)
|
||||
result.append(AttributedString(suffix).mergingAttributes(suffixStyle))
|
||||
}
|
||||
if isVerifiedSender {
|
||||
appendVerifiedSeal(to: &result, baseColor: baseColor, design: design)
|
||||
}
|
||||
result.append(AttributedString("> ").mergingAttributes(senderStyle))
|
||||
return result
|
||||
}
|
||||
@ -427,6 +436,29 @@ final class ChatMessageFormatter {
|
||||
}
|
||||
|
||||
private extension ChatMessageFormatter {
|
||||
/// Whether the message sender has a fingerprint the user has verified.
|
||||
/// Used for the in-chat seal next to `<@name>` so verification is visible
|
||||
/// without opening the fingerprint sheet (#1439).
|
||||
func isVerifiedSender(of message: BitchatMessage) -> Bool {
|
||||
guard let peerID = message.senderPeerID,
|
||||
let fingerprint = viewModel.getFingerprint(for: peerID) else {
|
||||
return false
|
||||
}
|
||||
return viewModel.peerIdentityStore.isVerified(fingerprint)
|
||||
}
|
||||
|
||||
func appendVerifiedSeal(
|
||||
to result: inout AttributedString,
|
||||
baseColor: Color,
|
||||
design: Font.Design
|
||||
) {
|
||||
var sealStyle = AttributeContainer()
|
||||
// Match the peer-list verified seal: filled checkmark in the sender tint.
|
||||
sealStyle.foregroundColor = baseColor
|
||||
sealStyle.font = .bitchatSystem(size: 11, weight: .semibold, design: design)
|
||||
result.append(AttributedString(" ✓").mergingAttributes(sealStyle))
|
||||
}
|
||||
|
||||
func peerColor(for message: BitchatMessage, isDark: Bool) -> Color {
|
||||
if let spid = message.senderPeerID {
|
||||
if spid.isGeoChat || spid.isGeoDM {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user