mirror of
https://github.com/permissionlesstech/bitchat.git
synced 2026-07-25 01:05:19 +00:00
PeerID 28/n: ChatViewModel.getShortIDForNoiseKey (#836)
This commit is contained in:
@@ -171,7 +171,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
if spid.isGeoChat || spid.isGeoDM {
|
if spid.isGeoChat || spid.isGeoDM {
|
||||||
let full = (nostrKeyMapping[spid] ?? spid.bare).lowercased()
|
let full = (nostrKeyMapping[spid] ?? spid.bare).lowercased()
|
||||||
return "nostr:" + full
|
return "nostr:" + full
|
||||||
} else if spid.id.count == 16, let full = getNoiseKeyForShortID(spid)?.lowercased() {
|
} else if spid.id.count == 16, let full = getNoiseKeyForShortID(spid)?.id.lowercased() {
|
||||||
return "noise:" + full
|
return "noise:" + full
|
||||||
} else {
|
} else {
|
||||||
return "mesh:" + spid.id.lowercased()
|
return "mesh:" + spid.id.lowercased()
|
||||||
@@ -328,16 +328,16 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
private var peerIDToPublicKeyFingerprint: [PeerID: String] = [:]
|
private var peerIDToPublicKeyFingerprint: [PeerID: String] = [:]
|
||||||
private var selectedPrivateChatFingerprint: String? = nil
|
private var selectedPrivateChatFingerprint: String? = nil
|
||||||
// Map stable short peer IDs (16-hex) to full Noise public key hex (64-hex) for session continuity
|
// Map stable short peer IDs (16-hex) to full Noise public key hex (64-hex) for session continuity
|
||||||
private var shortIDToNoiseKey: [PeerID: String] = [:]
|
private var shortIDToNoiseKey: [PeerID: PeerID] = [:]
|
||||||
|
|
||||||
// Resolve full Noise key for a peer's short ID (used by UI header rendering)
|
// Resolve full Noise key for a peer's short ID (used by UI header rendering)
|
||||||
@MainActor
|
@MainActor
|
||||||
private func getNoiseKeyForShortID(_ shortPeerID: PeerID) -> String? {
|
private func getNoiseKeyForShortID(_ shortPeerID: PeerID) -> PeerID? {
|
||||||
if let mapped = shortIDToNoiseKey[shortPeerID] { return mapped }
|
if let mapped = shortIDToNoiseKey[shortPeerID] { return mapped }
|
||||||
// Fallback: derive from active Noise session if available
|
// Fallback: derive from active Noise session if available
|
||||||
if shortPeerID.id.count == 16,
|
if shortPeerID.id.count == 16,
|
||||||
let key = meshService.getNoiseService().getPeerPublicKeyData(shortPeerID) {
|
let key = meshService.getNoiseService().getPeerPublicKeyData(shortPeerID) {
|
||||||
let stable = key.hexEncodedString()
|
let stable = PeerID(hexData: key)
|
||||||
shortIDToNoiseKey[shortPeerID] = stable
|
shortIDToNoiseKey[shortPeerID] = stable
|
||||||
return stable
|
return stable
|
||||||
}
|
}
|
||||||
@@ -346,16 +346,17 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
|
|
||||||
// Resolve short mesh ID (16-hex) from a full Noise public key hex (64-hex)
|
// Resolve short mesh ID (16-hex) from a full Noise public key hex (64-hex)
|
||||||
@MainActor
|
@MainActor
|
||||||
func getShortIDForNoiseKey(_ fullNoiseKeyHex: String) -> PeerID? {
|
func getShortIDForNoiseKey(_ fullNoiseKeyHex: PeerID) -> PeerID {
|
||||||
|
guard fullNoiseKeyHex.id.count == 64 else { return fullNoiseKeyHex }
|
||||||
// Check known peers for a noise key match
|
// Check known peers for a noise key match
|
||||||
if let match = allPeers.first(where: { $0.noisePublicKey.hexEncodedString() == fullNoiseKeyHex }) {
|
if let match = allPeers.first(where: { PeerID(hexData: $0.noisePublicKey) == fullNoiseKeyHex }) {
|
||||||
return match.peerID
|
return match.peerID
|
||||||
}
|
}
|
||||||
// Also search cache mapping
|
// Also search cache mapping
|
||||||
if let pair = shortIDToNoiseKey.first(where: { $0.value == fullNoiseKeyHex }) {
|
if let pair = shortIDToNoiseKey.first(where: { $0.value == fullNoiseKeyHex }) {
|
||||||
return pair.key
|
return pair.key
|
||||||
}
|
}
|
||||||
return nil
|
return fullNoiseKeyHex
|
||||||
}
|
}
|
||||||
private var peerIndex: [PeerID: BitchatPeer] = [:]
|
private var peerIndex: [PeerID: BitchatPeer] = [:]
|
||||||
|
|
||||||
@@ -4423,7 +4424,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
|
|
||||||
@MainActor
|
@MainActor
|
||||||
private func meshSeed(for peerID: PeerID) -> String {
|
private func meshSeed(for peerID: PeerID) -> String {
|
||||||
if let full = getNoiseKeyForShortID(peerID)?.lowercased() {
|
if let full = getNoiseKeyForShortID(peerID)?.id.lowercased() {
|
||||||
return "noise:" + full
|
return "noise:" + full
|
||||||
}
|
}
|
||||||
return peerID.id.lowercased()
|
return peerID.id.lowercased()
|
||||||
@@ -4899,9 +4900,9 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
// Cache shortID -> full Noise key mapping as soon as session authenticates
|
// Cache shortID -> full Noise key mapping as soon as session authenticates
|
||||||
if self.shortIDToNoiseKey[peerID] == nil,
|
if self.shortIDToNoiseKey[peerID] == nil,
|
||||||
let keyData = self.meshService.getNoiseService().getPeerPublicKeyData(peerID) {
|
let keyData = self.meshService.getNoiseService().getPeerPublicKeyData(peerID) {
|
||||||
let stable = keyData.hexEncodedString()
|
let stable = PeerID(hexData: keyData)
|
||||||
self.shortIDToNoiseKey[peerID] = stable
|
self.shortIDToNoiseKey[peerID] = stable
|
||||||
SecureLogger.debug("🗺️ Mapped short peerID to Noise key for header continuity: \(peerID) -> \(stable.prefix(8))…", category: .session)
|
SecureLogger.debug("🗺️ Mapped short peerID to Noise key for header continuity: \(peerID) -> \(stable.id.prefix(8))…", category: .session)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If a QR verification is pending but not sent yet, send it now that session is authenticated
|
// If a QR verification is pending but not sent yet, send it now that session is authenticated
|
||||||
@@ -5166,7 +5167,7 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
|
|
||||||
// Cache mapping to full Noise key for session continuity on disconnect
|
// Cache mapping to full Noise key for session continuity on disconnect
|
||||||
if let peer = unifiedPeerService.getPeer(by: peerID) {
|
if let peer = unifiedPeerService.getPeer(by: peerID) {
|
||||||
let noiseKeyHex = peer.noisePublicKey.hexEncodedString()
|
let noiseKeyHex = PeerID(hexData: peer.noisePublicKey)
|
||||||
shortIDToNoiseKey[peerID] = noiseKeyHex
|
shortIDToNoiseKey[peerID] = noiseKeyHex
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5182,15 +5183,14 @@ final class ChatViewModel: ObservableObject, BitchatDelegate {
|
|||||||
identityManager.removeEphemeralSession(peerID: peerID)
|
identityManager.removeEphemeralSession(peerID: peerID)
|
||||||
|
|
||||||
// If the open PM is tied to this short peer ID, switch UI context to the full Noise key (offline favorite)
|
// If the open PM is tied to this short peer ID, switch UI context to the full Noise key (offline favorite)
|
||||||
var derivedStableKeyHex: String? = shortIDToNoiseKey[peerID]
|
var derivedStableKeyHex = shortIDToNoiseKey[peerID]
|
||||||
if derivedStableKeyHex == nil,
|
if derivedStableKeyHex == nil,
|
||||||
let key = meshService.getNoiseService().getPeerPublicKeyData(peerID) {
|
let key = meshService.getNoiseService().getPeerPublicKeyData(peerID) {
|
||||||
derivedStableKeyHex = key.hexEncodedString()
|
derivedStableKeyHex = PeerID(hexData: key)
|
||||||
shortIDToNoiseKey[peerID] = derivedStableKeyHex
|
shortIDToNoiseKey[peerID] = derivedStableKeyHex
|
||||||
}
|
}
|
||||||
|
|
||||||
if let current = selectedPrivateChatPeer, current == peerID,
|
if let current = selectedPrivateChatPeer, current == peerID, let stableKeyHex = derivedStableKeyHex {
|
||||||
let stableKeyHex = PeerID(str: derivedStableKeyHex) {
|
|
||||||
// Migrate messages view context to stable key so header shows favorite + Nostr globe
|
// Migrate messages view context to stable key so header shows favorite + Nostr globe
|
||||||
if let messages = privateChats[peerID] {
|
if let messages = privateChats[peerID] {
|
||||||
if privateChats[stableKeyHex] == nil { privateChats[stableKeyHex] = [] }
|
if privateChats[stableKeyHex] == nil { privateChats[stableKeyHex] = [] }
|
||||||
|
|||||||
@@ -1213,12 +1213,7 @@ struct ContentView: View {
|
|||||||
.foregroundColor(textColor)
|
.foregroundColor(textColor)
|
||||||
|
|
||||||
if !privatePeerID.isGeoDM {
|
if !privatePeerID.isGeoDM {
|
||||||
let statusPeerID: PeerID = {
|
let statusPeerID = viewModel.getShortIDForNoiseKey(privatePeerID)
|
||||||
if privatePeerID.id.count == 64, let short = viewModel.getShortIDForNoiseKey(privatePeerID.id) {
|
|
||||||
return short
|
|
||||||
}
|
|
||||||
return context.headerPeerID
|
|
||||||
}()
|
|
||||||
let encryptionStatus = viewModel.getEncryptionStatus(for: statusPeerID)
|
let encryptionStatus = viewModel.getEncryptionStatus(for: statusPeerID)
|
||||||
if let icon = encryptionStatus.icon {
|
if let icon = encryptionStatus.icon {
|
||||||
Image(systemName: icon)
|
Image(systemName: icon)
|
||||||
@@ -1252,13 +1247,7 @@ struct ContentView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func makePrivateHeaderContext(for privatePeerID: PeerID) -> PrivateHeaderContext {
|
private func makePrivateHeaderContext(for privatePeerID: PeerID) -> PrivateHeaderContext {
|
||||||
let headerPeerID: PeerID = {
|
let headerPeerID = viewModel.getShortIDForNoiseKey(privatePeerID)
|
||||||
if privatePeerID.id.count == 64, let short = viewModel.getShortIDForNoiseKey(privatePeerID.id) {
|
|
||||||
return short
|
|
||||||
}
|
|
||||||
return privatePeerID
|
|
||||||
}()
|
|
||||||
|
|
||||||
let peer = viewModel.getPeer(byID: headerPeerID)
|
let peer = viewModel.getPeer(byID: headerPeerID)
|
||||||
|
|
||||||
let displayName: String = {
|
let displayName: String = {
|
||||||
|
|||||||
@@ -65,10 +65,7 @@ struct FingerprintView: View {
|
|||||||
|
|
||||||
VStack(alignment: .leading, spacing: 16) {
|
VStack(alignment: .leading, spacing: 16) {
|
||||||
// Prefer short mesh ID for session/encryption status
|
// Prefer short mesh ID for session/encryption status
|
||||||
let statusPeerID: PeerID = {
|
let statusPeerID = viewModel.getShortIDForNoiseKey(peerID)
|
||||||
if peerID.id.count == 64, let short = viewModel.getShortIDForNoiseKey(peerID.id) { return short }
|
|
||||||
return peerID
|
|
||||||
}()
|
|
||||||
// Resolve a friendly name
|
// Resolve a friendly name
|
||||||
let peerNickname: String = {
|
let peerNickname: String = {
|
||||||
if let p = viewModel.getPeer(byID: statusPeerID) { return p.displayName }
|
if let p = viewModel.getPeer(byID: statusPeerID) { return p.displayName }
|
||||||
|
|||||||
Reference in New Issue
Block a user