Refactors cleanup (#372)

* cleanup peermanager

* cleanup geohash code

* direct connections fix

* pow display

* track disconnects too

* display pow only if enabled

* display pow only if enabled

* direct connection tracking
This commit is contained in:
callebtc
2025-09-02 22:09:44 +02:00
committed by GitHub
parent bbf5918896
commit 8b3dc71dc6
13 changed files with 181 additions and 147 deletions
@@ -248,8 +248,8 @@ fun AboutSheet(
Slider(
value = powDifficulty.toFloat(),
onValueChange = { PoWPreferenceManager.setPowDifficulty(it.toInt()) },
valueRange = 0f..20f,
steps = 21, // 20 discrete values (0-20)
valueRange = 0f..32f,
steps = 33, // 33 discrete values (0-32)
colors = SliderDefaults.colors(
thumbColor = if (isDark) Color(0xFF32D74B) else Color(0xFF248A3D),
activeTrackColor = if (isDark) Color(0xFF32D74B) else Color(0xFF248A3D)
@@ -103,6 +103,10 @@ class ChatState {
private val _peerRSSI = MutableLiveData<Map<String, Int>>(emptyMap())
val peerRSSI: LiveData<Map<String, Int>> = _peerRSSI
// Direct connection status per peer (for live UI updates)
private val _peerDirect = MutableLiveData<Map<String, Boolean>>(emptyMap())
val peerDirect: LiveData<Map<String, Boolean>> = _peerDirect
// peerIDToPublicKeyFingerprint REMOVED - fingerprints now handled centrally in PeerManager
@@ -276,6 +280,10 @@ class ChatState {
fun setPeerRSSI(rssi: Map<String, Int>) {
_peerRSSI.value = rssi
}
fun setPeerDirect(direct: Map<String, Boolean>) {
_peerDirect.value = direct
}
fun setShowAppInfo(show: Boolean) {
_showAppInfo.value = show
@@ -7,6 +7,9 @@ import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.sp
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Shield
import androidx.compose.ui.graphics.vector.ImageVector
import com.bitchat.android.model.BitchatMessage
import com.bitchat.android.mesh.BluetoothMeshService
import androidx.compose.material3.ColorScheme
@@ -124,11 +127,11 @@ fun formatMessageAsAnnotatedString(
))
builder.append(" [${timeFormatter.format(message.timestamp)}]")
// If message has valid PoW difficulty, append bits immediately after timestamp with minimal spacing
//message.powDifficulty?.let { bits ->
// if (bits > 0) {
// builder.append(" ${bits}b")
// }
//}
message.powDifficulty?.let { bits ->
if (bits > 0) {
builder.append("${bits}b")
}
}
builder.pop()
} else {
@@ -106,6 +106,7 @@ class ChatViewModel(
val peerFingerprints: LiveData<Map<String, String>> = state.peerFingerprints
val peerNicknames: LiveData<Map<String, String>> = state.peerNicknames
val peerRSSI: LiveData<Map<String, Int>> = state.peerRSSI
val peerDirect: LiveData<Map<String, Boolean>> = state.peerDirect
val showAppInfo: LiveData<Boolean> = state.showAppInfo
val selectedLocationChannel: LiveData<com.bitchat.android.geohash.ChannelID?> = state.selectedLocationChannel
val isTeleported: LiveData<Boolean> = state.isTeleported
@@ -437,6 +438,14 @@ class ChatViewModel(
val rssiValues = meshService.getPeerRSSI()
state.setPeerRSSI(rssiValues)
// Update directness per peer (driven by PeerManager state)
try {
val directMap = state.getConnectedPeersValue().associateWith { pid ->
meshService.getPeerInfo(pid)?.isDirectConnection == true
}
state.setPeerDirect(directMap)
} catch (_: Exception) { }
}
// MARK: - Debug and Troubleshooting
@@ -128,67 +128,3 @@ enum class PoWIndicatorStyle {
COMPACT, // Small icon + difficulty number
DETAILED // Icon + status text + time estimate
}
/**
* Shows mining progress with animated indicator
*/
@Composable
fun PoWMiningIndicator(
modifier: Modifier = Modifier,
difficulty: Int,
iterations: Int? = null
) {
val colorScheme = MaterialTheme.colorScheme
Surface(
modifier = modifier,
color = Color(0xFFFF9500).copy(alpha = 0.1f),
shape = androidx.compose.foundation.shape.RoundedCornerShape(8.dp)
) {
Row(
modifier = Modifier.padding(horizontal = 12.dp, vertical = 8.dp),
horizontalArrangement = Arrangement.spacedBy(8.dp),
verticalAlignment = Alignment.CenterVertically
) {
// Animated security icon
val rotation by rememberInfiniteTransition(label = "mining-rotation").animateFloat(
initialValue = 0f,
targetValue = 360f,
animationSpec = infiniteRepeatable(
animation = tween(1000, easing = LinearEasing),
repeatMode = RepeatMode.Restart
),
label = "mining-icon-rotation"
)
Icon(
imageVector = Icons.Filled.Security,
contentDescription = "Mining Proof of Work",
tint = Color(0xFFFF9500),
modifier = Modifier
.size(16.dp)
.graphicsLayer { rotationZ = rotation }
)
Column(
verticalArrangement = Arrangement.spacedBy(2.dp)
) {
Text(
text = "mining proof of work...",
fontSize = 12.sp,
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Medium,
color = Color(0xFFFF9500)
)
Text(
text = "difficulty: ${difficulty}bit (~${NostrProofOfWork.estimateMiningTime(difficulty)})" +
if (iterations != null) "${iterations} attempts" else "",
fontSize = 10.sp,
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = 0.7f)
)
}
}
}
}
@@ -384,10 +384,12 @@ fun PeopleSection(
val (bName, _) = com.bitchat.android.ui.splitSuffix(displayName)
val showHash = (baseNameCounts[bName] ?: 0) > 1
val directMap by viewModel.peerDirect.observeAsState(emptyMap())
val isDirectLive = directMap[peerID] ?: try { viewModel.meshService.getPeerInfo(peerID)?.isDirectConnection == true } catch (_: Exception) { false }
PeerItem(
peerID = peerID,
displayName = displayName,
signalStrength = convertRSSIToSignalStrength(peerRSSI[peerID]),
isDirect = isDirectLive,
isSelected = peerID == selectedPrivatePeer,
isFavorite = isFavorite,
hasUnreadDM = combinedHasUnread,
@@ -421,7 +423,7 @@ fun PeopleSection(
PeerItem(
peerID = favPeerID,
displayName = dn,
signalStrength = 0,
isDirect = false,
isSelected = (mappedConnectedPeerID ?: favPeerID) == selectedPrivatePeer,
isFavorite = true,
hasUnreadDM = hasUnreadPrivateMessages.contains(favPeerID),
@@ -458,15 +460,15 @@ fun PeopleSection(
val (bName, _) = com.bitchat.android.ui.splitSuffix(dn)
val showHash = (baseNameCounts[bName] ?: 0) > 1
PeerItem(
peerID = convKey,
displayName = dn,
signalStrength = 0,
isSelected = convKey == selectedPrivatePeer,
isFavorite = false,
hasUnreadDM = hasUnreadPrivateMessages.contains(convKey),
colorScheme = colorScheme,
viewModel = viewModel,
PeerItem(
peerID = convKey,
displayName = dn,
isDirect = false,
isSelected = convKey == selectedPrivatePeer,
isFavorite = false,
hasUnreadDM = hasUnreadPrivateMessages.contains(convKey),
colorScheme = colorScheme,
viewModel = viewModel,
onItemClick = { onPrivateChatStart(convKey) },
onToggleFavorite = { viewModel.toggleFavorite(convKey) },
unreadCount = privateChats[convKey]?.count { msg ->
@@ -483,7 +485,7 @@ fun PeopleSection(
private fun PeerItem(
peerID: String,
displayName: String,
signalStrength: Int,
isDirect: Boolean,
isSelected: Boolean,
isFavorite: Boolean,
hasUnreadDM: Boolean,
@@ -527,7 +529,7 @@ private fun PeerItem(
tint = Color(0xFFFF9500) // iOS orange
)
} else {
// Signal strength indicators
// Connection indicator icons
if (showNostrGlobe) {
// Purple globe to indicate Nostr availability
Icon(
@@ -537,9 +539,11 @@ private fun PeerItem(
tint = Color(0xFF9C27B0) // Purple
)
} else {
SignalStrengthIndicator(
signalStrength = signalStrength,
colorScheme = colorScheme
Icon(
imageVector = if (isDirect) Icons.Outlined.SettingsInputAntenna else Icons.Filled.Route,
contentDescription = if (isDirect) "Direct Bluetooth" else "Routed",
modifier = Modifier.size(16.dp),
tint = colorScheme.onSurface.copy(alpha = 0.8f)
)
}
}