UI: bold entire message text for self in mesh, DM, and geohash; adjust caching to include self flag

This commit is contained in:
jack
2025-08-21 02:51:14 +02:00
parent 222854c60a
commit c63350a4d3
2 changed files with 33 additions and 12 deletions
+4 -4
View File
@@ -410,12 +410,12 @@ class BitchatMessage: Codable {
// Cached formatted text (not included in Codable) // Cached formatted text (not included in Codable)
private var _cachedFormattedText: [String: AttributedString] = [:] private var _cachedFormattedText: [String: AttributedString] = [:]
func getCachedFormattedText(isDark: Bool) -> AttributedString? { func getCachedFormattedText(isDark: Bool, isSelf: Bool) -> AttributedString? {
return _cachedFormattedText["\(isDark)"] return _cachedFormattedText["\(isDark)-\(isSelf)"]
} }
func setCachedFormattedText(_ text: AttributedString, isDark: Bool) { func setCachedFormattedText(_ text: AttributedString, isDark: Bool, isSelf: Bool) {
_cachedFormattedText["\(isDark)"] = text _cachedFormattedText["\(isDark)-\(isSelf)"] = text
} }
// Codable implementation // Codable implementation
+29 -8
View File
@@ -2631,9 +2631,26 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
} }
func formatMessageAsText(_ message: BitchatMessage, colorScheme: ColorScheme) -> AttributedString { func formatMessageAsText(_ message: BitchatMessage, colorScheme: ColorScheme) -> AttributedString {
// Check cache first // Determine if this message was sent by self (mesh, geo, or DM)
let isSelf: Bool = {
if let spid = message.senderPeerID {
#if os(iOS)
if case .location(let ch) = activeChannel, spid.hasPrefix("nostr:") {
if let myGeo = try? NostrIdentityBridge.deriveIdentity(forGeohash: ch.geohash) {
return spid == "nostr:\(myGeo.publicKeyHex.prefix(8))"
}
}
#endif
return spid == meshService.myPeerID
}
// Fallback by nickname
if message.sender == nickname { return true }
if message.sender.hasPrefix(nickname + "#") { return true }
return false
}()
// Check cache first (key includes dark mode + self flag)
let isDark = colorScheme == .dark let isDark = colorScheme == .dark
if let cachedText = message.getCachedFormattedText(isDark: isDark) { if let cachedText = message.getCachedFormattedText(isDark: isDark, isSelf: isSelf) {
return cachedText return cachedText
} }
@@ -2649,7 +2666,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
// Use consistent color for all senders // Use consistent color for all senders
senderStyle.foregroundColor = primaryColor senderStyle.foregroundColor = primaryColor
// Bold the user's own nickname // Bold the user's own nickname
let fontWeight: Font.Weight = message.sender == nickname ? .bold : .medium let fontWeight: Font.Weight = isSelf ? .bold : .medium
senderStyle.font = .system(size: 14, weight: fontWeight, design: .monospaced) senderStyle.font = .system(size: 14, weight: fontWeight, design: .monospaced)
// Prefix "<@" // Prefix "<@"
@@ -2711,7 +2728,9 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
if !beforeText.isEmpty { if !beforeText.isEmpty {
var beforeStyle = AttributeContainer() var beforeStyle = AttributeContainer()
beforeStyle.foregroundColor = primaryColor beforeStyle.foregroundColor = primaryColor
beforeStyle.font = .system(size: 14, design: .monospaced) beforeStyle.font = isSelf
? .system(size: 14, weight: .bold, design: .monospaced)
: .system(size: 14, design: .monospaced)
if isMentioned { if isMentioned {
beforeStyle.font = beforeStyle.font?.bold() beforeStyle.font = beforeStyle.font?.bold()
} }
@@ -2724,7 +2743,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
// Split optional '#abcd' suffix and color suffix light grey // Split optional '#abcd' suffix and color suffix light grey
let (mBase, mSuffix) = splitSuffix(from: matchText.replacingOccurrences(of: "@", with: "")) let (mBase, mSuffix) = splitSuffix(from: matchText.replacingOccurrences(of: "@", with: ""))
var mentionStyle = AttributeContainer() var mentionStyle = AttributeContainer()
mentionStyle.font = .system(size: 14, weight: .semibold, design: .monospaced) mentionStyle.font = .system(size: 14, weight: isSelf ? .bold : .semibold, design: .monospaced)
mentionStyle.foregroundColor = Color.orange mentionStyle.foregroundColor = Color.orange
// Emit '@' // Emit '@'
result.append(AttributedString("@").mergingAttributes(mentionStyle)) result.append(AttributedString("@").mergingAttributes(mentionStyle))
@@ -2738,7 +2757,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
} }
} else { } else {
var matchStyle = AttributeContainer() var matchStyle = AttributeContainer()
matchStyle.font = .system(size: 14, weight: .semibold, design: .monospaced) matchStyle.font = .system(size: 14, weight: isSelf ? .bold : .semibold, design: .monospaced)
if type == "hashtag" { if type == "hashtag" {
matchStyle.foregroundColor = Color.blue matchStyle.foregroundColor = Color.blue
matchStyle.underlineStyle = .single matchStyle.underlineStyle = .single
@@ -2757,7 +2776,9 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
let remainingText = String(content[lastEnd...]) let remainingText = String(content[lastEnd...])
var remainingStyle = AttributeContainer() var remainingStyle = AttributeContainer()
remainingStyle.foregroundColor = primaryColor remainingStyle.foregroundColor = primaryColor
remainingStyle.font = .system(size: 14, design: .monospaced) remainingStyle.font = isSelf
? .system(size: 14, weight: .bold, design: .monospaced)
: .system(size: 14, design: .monospaced)
if isMentioned { if isMentioned {
remainingStyle.font = remainingStyle.font?.bold() remainingStyle.font = remainingStyle.font?.bold()
} }
@@ -2787,7 +2808,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
} }
// Cache the formatted text // Cache the formatted text
message.setCachedFormattedText(result, isDark: isDark) message.setCachedFormattedText(result, isDark: isDark, isSelf: isSelf)
return result return result
} }