Adds O(1) method for peer nickname retrieval (#450)

* Adds O(1) method for peerNickname retrieval

* Uses peerNickname method where possible
This commit is contained in:
Mateusz Matoszko
2025-08-17 21:29:15 +02:00
committed by GitHub
parent 4f1ac30f12
commit 7836daa6d3
10 changed files with 31 additions and 18 deletions
+7
View File
@@ -337,6 +337,13 @@ final class BLEService: NSObject {
return collectionsQueue.sync { peers[shortID]?.isConnected ?? false } return collectionsQueue.sync { peers[shortID]?.isConnected ?? false }
} }
func peerNickname(peerID: String) -> String? {
collectionsQueue.sync {
guard let peer = peers[peerID], peer.isConnected else { return nil }
return peer.nickname
}
}
func getPeerNicknames() -> [String: String] { func getPeerNicknames() -> [String: String] {
return collectionsQueue.sync { return collectionsQueue.sync {
Dictionary(uniqueKeysWithValues: peers.compactMap { (id, info) in Dictionary(uniqueKeysWithValues: peers.compactMap { (id, info) in
+1 -1
View File
@@ -119,7 +119,7 @@ class CommandProcessor {
if chatViewModel?.selectedPrivateChatPeer != nil { if chatViewModel?.selectedPrivateChatPeer != nil {
// In private chat // In private chat
if let peerNickname = meshService?.getPeerNicknames()[targetPeerID] { if let peerNickname = meshService?.peerNickname(peerID: targetPeerID) {
let personalMessage = "* \(emoji) \(myNickname) \(action) you\(suffix) *" let personalMessage = "* \(emoji) \(myNickname) \(action) you\(suffix) *"
meshService?.sendPrivateMessage(personalMessage, to: targetPeerID, meshService?.sendPrivateMessage(personalMessage, to: targetPeerID,
recipientNickname: peerNickname, recipientNickname: peerNickname,
+1
View File
@@ -31,6 +31,7 @@ final class NostrTransport: Transport {
func emergencyDisconnectAll() { /* no-op */ } func emergencyDisconnectAll() { /* no-op */ }
func isPeerConnected(_ peerID: String) -> Bool { false } func isPeerConnected(_ peerID: String) -> Bool { false }
func peerNickname(peerID: String) -> String? { nil }
func getPeerNicknames() -> [String : String] { [:] } func getPeerNicknames() -> [String : String] { [:] }
func getFingerprint(for peerID: String) -> String? { nil } func getFingerprint(for peerID: String) -> String? { nil }
+1 -1
View File
@@ -53,7 +53,7 @@ class PrivateChatManager: ObservableObject {
/// Send a private message /// Send a private message
func sendMessage(_ content: String, to peerID: String) { func sendMessage(_ content: String, to peerID: String) {
guard let meshService = meshService, guard let meshService = meshService,
let peerNickname = meshService.getPeerNicknames()[peerID] else { let peerNickname = meshService.peerNickname(peerID: peerID) else {
return return
} }
+1
View File
@@ -29,6 +29,7 @@ protocol Transport: AnyObject {
// Connectivity and peers // Connectivity and peers
func isPeerConnected(_ peerID: String) -> Bool func isPeerConnected(_ peerID: String) -> Bool
func peerNickname(peerID: String) -> String?
func getPeerNicknames() -> [String: String] func getPeerNicknames() -> [String: String]
// Protocol utilities // Protocol utilities
+1 -1
View File
@@ -279,7 +279,7 @@ class UnifiedPeerService: ObservableObject, TransportPeerEventsDelegate {
if actualNickname.isEmpty { if actualNickname.isEmpty {
// Try to get from mesh service's current peer list // Try to get from mesh service's current peer list
if let meshPeerNickname = meshService.getPeerNicknames()[peerID] { if let meshPeerNickname = meshService.peerNickname(peerID: peerID) {
actualNickname = meshPeerNickname actualNickname = meshPeerNickname
SecureLogger.log("🔍 Got nickname from mesh service: '\(actualNickname)'", SecureLogger.log("🔍 Got nickname from mesh service: '\(actualNickname)'",
category: SecureLogger.session, level: .debug) category: SecureLogger.session, level: .debug)
+10 -10
View File
@@ -527,7 +527,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
} }
// Get the peer's nickname to check for temporary Nostr peer IDs // Get the peer's nickname to check for temporary Nostr peer IDs
let peerNickname = meshService.getPeerNicknames()[peerID]?.lowercased() ?? "" let peerNickname = meshService.peerNickname(peerID: peerID)?.lowercased() ?? ""
// Check if any temporary Nostr peer IDs have unread messages from this nickname // Check if any temporary Nostr peer IDs have unread messages from this nickname
for unreadPeerID in unreadPrivateMessages { for unreadPeerID in unreadPrivateMessages {
@@ -833,7 +833,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
// Check if blocked // Check if blocked
if unifiedPeerService.isBlocked(peerID) { if unifiedPeerService.isBlocked(peerID) {
let nickname = meshService.getPeerNicknames()[peerID] ?? "user" let nickname = meshService.peerNickname(peerID: peerID) ?? "user"
addSystemMessage("cannot send message to \(nickname): user is blocked.") addSystemMessage("cannot send message to \(nickname): user is blocked.")
return return
} }
@@ -846,7 +846,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
let hasNostrKey = favoriteStatus?.peerNostrPublicKey != nil let hasNostrKey = favoriteStatus?.peerNostrPublicKey != nil
// Get nickname from various sources // Get nickname from various sources
var recipientNickname = meshService.getPeerNicknames()[peerID] var recipientNickname = meshService.peerNickname(peerID: peerID)
if recipientNickname == nil && favoriteStatus != nil { if recipientNickname == nil && favoriteStatus != nil {
recipientNickname = favoriteStatus?.peerNickname recipientNickname = favoriteStatus?.peerNickname
} }
@@ -938,7 +938,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
return return
} }
let peerNickname = meshService.getPeerNicknames()[peerID] ?? "unknown" let peerNickname = meshService.peerNickname(peerID: peerID) ?? "unknown"
// Check if the peer is blocked // Check if the peer is blocked
if unifiedPeerService.isBlocked(peerID) { if unifiedPeerService.isBlocked(peerID) {
@@ -1280,7 +1280,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
// Find peer nickname // Find peer nickname
let peerNickname: String let peerNickname: String
if let nickname = meshService.getPeerNicknames()[peerID] { if let nickname = meshService.peerNickname(peerID: peerID) {
peerNickname = nickname peerNickname = nickname
} else if let favorite = FavoritesPersistenceService.shared.getFavoriteStatus(for: peerPublicKey) { } else if let favorite = FavoritesPersistenceService.shared.getFavoriteStatus(for: peerPublicKey) {
peerNickname = favorite.peerNickname peerNickname = favorite.peerNickname
@@ -1333,7 +1333,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
if let peerID = selectedPrivateChatPeer { if let peerID = selectedPrivateChatPeer {
// In private chat - send to the other person // In private chat - send to the other person
if let peerNickname = meshService.getPeerNicknames()[peerID] { if let peerNickname = meshService.peerNickname(peerID: peerID) {
// Only send screenshot notification if we have an established session // Only send screenshot notification if we have an established session
// This prevents triggering handshake requests for screenshot notifications // This prevents triggering handshake requests for screenshot notifications
let sessionState = meshService.getNoiseSessionState(for: peerID) let sessionState = meshService.getNoiseSessionState(for: peerID)
@@ -1355,7 +1355,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
isRelay: false, isRelay: false,
originalSender: nil, originalSender: nil,
isPrivate: true, isPrivate: true,
recipientNickname: meshService.getPeerNicknames()[peerID], recipientNickname: meshService.peerNickname(peerID: peerID),
senderPeerID: meshService.myPeerID senderPeerID: meshService.myPeerID
) )
var chats = privateChats var chats = privateChats
@@ -1413,7 +1413,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
var actualPeerID = peerID var actualPeerID = peerID
// Check if this peer ID exists in current nicknames // Check if this peer ID exists in current nicknames
if meshService.getPeerNicknames()[peerID] == nil { if meshService.peerNickname(peerID: peerID) == nil {
// Peer not found with this ID, try to find by fingerprint or nickname // Peer not found with this ID, try to find by fingerprint or nickname
if let oldNoiseKey = Data(hexString: peerID), if let oldNoiseKey = Data(hexString: peerID),
let favoriteStatus = FavoritesPersistenceService.shared.getFavoriteStatus(for: oldNoiseKey) { let favoriteStatus = FavoritesPersistenceService.shared.getFavoriteStatus(for: oldNoiseKey) {
@@ -1435,7 +1435,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
if originalTransport == "nostr" { if originalTransport == "nostr" {
// Skip read receipts for Nostr messages - unnecessary complexity // Skip read receipts for Nostr messages - unnecessary complexity
// The radical simplification plan says to accept occasional loss // The radical simplification plan says to accept occasional loss
} else if meshService.getPeerNicknames()[actualPeerID] != nil { } else if meshService.peerNickname(peerID: actualPeerID) != nil {
// Use mesh for connected peers (default behavior) // Use mesh for connected peers (default behavior)
messageRouter.sendReadReceipt(receipt, to: actualPeerID) messageRouter.sendReadReceipt(receipt, to: actualPeerID)
} else { } else {
@@ -3620,7 +3620,7 @@ class ChatViewModel: ObservableObject, BitchatDelegate {
if let noiseKey = Data(hexString: recipientID), if let noiseKey = Data(hexString: recipientID),
let favoriteStatus = FavoritesPersistenceService.shared.getFavoriteStatus(for: noiseKey), let favoriteStatus = FavoritesPersistenceService.shared.getFavoriteStatus(for: noiseKey),
favoriteStatus.peerNostrPublicKey != nil, favoriteStatus.peerNostrPublicKey != nil,
self.meshService.getPeerNicknames()[recipientID] == nil { self.meshService.peerNickname(peerID: recipientID) == nil {
originalTransport = "nostr" originalTransport = "nostr"
} }
+1 -1
View File
@@ -970,7 +970,7 @@ struct ContentView: View {
// Resolve peer object for header context (may be offline favorite) // Resolve peer object for header context (may be offline favorite)
let peer = viewModel.getPeer(byID: headerPeerID) let peer = viewModel.getPeer(byID: headerPeerID)
let privatePeerNick = peer?.displayName ?? let privatePeerNick = peer?.displayName ??
viewModel.meshService.getPeerNicknames()[headerPeerID] ?? viewModel.meshService.peerNickname(peerID: headerPeerID) ??
FavoritesPersistenceService.shared.getFavoriteStatus(for: Data(hexString: headerPeerID) ?? Data())?.peerNickname ?? FavoritesPersistenceService.shared.getFavoriteStatus(for: Data(hexString: headerPeerID) ?? Data())?.peerNickname ??
// getFavoriteStatusByNostrKey not implemented // getFavoriteStatusByNostrKey not implemented
// FavoritesPersistenceService.shared.getFavoriteStatusByNostrKey(privatePeerID)?.peerNickname ?? // FavoritesPersistenceService.shared.getFavoriteStatusByNostrKey(privatePeerID)?.peerNickname ??
+1 -1
View File
@@ -41,7 +41,7 @@ struct FingerprintView: View {
VStack(alignment: .leading, spacing: 16) { VStack(alignment: .leading, spacing: 16) {
// Peer info // Peer info
let peerNickname = viewModel.meshService.getPeerNicknames()[peerID] ?? "Unknown" let peerNickname = viewModel.meshService.peerNickname(peerID: peerID) ?? "Unknown"
let encryptionStatus = viewModel.getEncryptionStatus(for: peerID) let encryptionStatus = viewModel.getEncryptionStatus(for: peerID)
HStack { HStack {
+4
View File
@@ -64,6 +64,10 @@ class MockBLEService: NSObject {
return connectedPeers.contains(peerID) return connectedPeers.contains(peerID)
} }
func peerNickname(peerID: String) -> String? {
"MockPeer_\(peerID)"
}
func getPeerNicknames() -> [String: String] { func getPeerNicknames() -> [String: String] {
var nicknames: [String: String] = [:] var nicknames: [String: String] = [:]
for peer in connectedPeers { for peer in connectedPeers {