mirror of
https://github.com/permissionlesstech/bitchat-android.git
synced 2026-07-25 20:05:21 +00:00
new files
This commit is contained in:
@@ -636,7 +636,7 @@ private fun PeerItem(
|
||||
else -> "Routed"
|
||||
},
|
||||
modifier = Modifier.size(16.dp),
|
||||
tint = if (isWifiAware) Color(0xFF9C27B0) else colorScheme.onSurface.copy(alpha = 0.6f)
|
||||
tint = colorScheme.onSurface.copy(alpha = 0.6f)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -673,7 +673,7 @@ private fun PeerItem(
|
||||
imageVector = Icons.Filled.Wifi,
|
||||
contentDescription = "Direct Wi-Fi Aware",
|
||||
modifier = Modifier.size(13.dp),
|
||||
tint = Color(0xFF9C27B0).copy(alpha = 0.8f)
|
||||
tint = colorScheme.onSurface.copy(alpha = 0.8f)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,10 @@ import com.bitchat.android.core.ui.component.sheet.BitchatSheetTopBar
|
||||
import com.bitchat.android.core.ui.component.sheet.BitchatSheetTitle
|
||||
|
||||
@Composable
|
||||
fun MeshTopologySection(localPeerID: String? = null) {
|
||||
fun MeshTopologySection(
|
||||
localPeerID: String? = null,
|
||||
blePeerIDs: Set<String> = emptySet(),
|
||||
) {
|
||||
val colorScheme = MaterialTheme.colorScheme
|
||||
val graphService = remember { MeshGraphService.getInstance() }
|
||||
val snapshot by graphService.graphState.collectAsState()
|
||||
@@ -65,6 +68,7 @@ fun MeshTopologySection(localPeerID: String? = null) {
|
||||
nodes = nodes,
|
||||
edges = edges,
|
||||
wifiAwarePeerIDs = wifiAwarePeerIDs,
|
||||
blePeerIDs = blePeerIDs,
|
||||
localPeerID = localPeerID,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
@@ -225,7 +229,13 @@ fun DebugSettingsSheet(
|
||||
|
||||
// Mesh topology visualization (moved below verbose logging)
|
||||
item {
|
||||
MeshTopologySection(localPeerID = meshService.myPeerID)
|
||||
val blePeerIDs = remember(connectedDevices) {
|
||||
connectedDevices.mapNotNull { it.peerID }.toSet()
|
||||
}
|
||||
MeshTopologySection(
|
||||
localPeerID = meshService.myPeerID,
|
||||
blePeerIDs = blePeerIDs,
|
||||
)
|
||||
}
|
||||
|
||||
// GATT controls
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.offset
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Wifi
|
||||
import androidx.compose.material.icons.outlined.Bluetooth
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
@@ -37,6 +38,44 @@ private const val DAMPING = 0.85f
|
||||
private const val MAX_VELOCITY = 30f
|
||||
private const val PULSE_DECAY = 0.05f
|
||||
private const val ROUTE_DECAY = 0.02f
|
||||
private val EDGE_ICON_OFFSET = 14.dp
|
||||
|
||||
private enum class EdgeTransport { WIFI, BLE }
|
||||
|
||||
private data class EdgeMarker(val x: Float, val y: Float, val transport: EdgeTransport)
|
||||
|
||||
private fun shouldMarkDirectEdge(
|
||||
edge: MeshGraphService.GraphEdge,
|
||||
transportPeerIDs: Set<String>,
|
||||
localID: String?
|
||||
): Boolean {
|
||||
if (transportPeerIDs.isEmpty()) return false
|
||||
return if (localID != null) {
|
||||
(edge.a == localID && edge.b in transportPeerIDs) ||
|
||||
(edge.b == localID && edge.a in transportPeerIDs)
|
||||
} else {
|
||||
edge.a in transportPeerIDs || edge.b in transportPeerIDs
|
||||
}
|
||||
}
|
||||
|
||||
private fun edgeMarkerPosition(
|
||||
x1: Float,
|
||||
y1: Float,
|
||||
x2: Float,
|
||||
y2: Float,
|
||||
offsetPx: Float,
|
||||
sideSign: Float
|
||||
): Pair<Float, Float> {
|
||||
val midX = (x1 + x2) / 2f
|
||||
val midY = (y1 + y2) / 2f
|
||||
val dx = x2 - x1
|
||||
val dy = y2 - y1
|
||||
val len = sqrt(dx * dx + dy * dy)
|
||||
if (len < 0.1f) return midX to midY
|
||||
val px = -dy / len * offsetPx * sideSign
|
||||
val py = dx / len * offsetPx * sideSign
|
||||
return (midX + px) to (midY + py)
|
||||
}
|
||||
|
||||
private class GraphNodeState(
|
||||
val id: String,
|
||||
@@ -219,6 +258,7 @@ fun ForceDirectedMeshGraph(
|
||||
nodes: List<MeshGraphService.GraphNode>,
|
||||
edges: List<MeshGraphService.GraphEdge>,
|
||||
wifiAwarePeerIDs: Set<String> = emptySet(),
|
||||
blePeerIDs: Set<String> = emptySet(),
|
||||
localPeerID: String? = null,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
@@ -417,38 +457,46 @@ fun ForceDirectedMeshGraph(
|
||||
val iconSize = 16.dp
|
||||
val iconSizePx = with(density) { iconSize.toPx() }
|
||||
val halfIconSizePx = iconSizePx / 2f
|
||||
val iconOffsetPx = with(density) { EDGE_ICON_OFFSET.toPx() }
|
||||
val localID = localPeerID
|
||||
val shouldMarkWifiEdge: (MeshGraphService.GraphEdge) -> Boolean = { edge ->
|
||||
if (localID != null) {
|
||||
(edge.a == localID && edge.b in wifiAwarePeerIDs) ||
|
||||
(edge.b == localID && edge.a in wifiAwarePeerIDs)
|
||||
} else {
|
||||
edge.a in wifiAwarePeerIDs || edge.b in wifiAwarePeerIDs
|
||||
}
|
||||
}
|
||||
|
||||
val wifiEdgeMidpoints = tick.let {
|
||||
simulation.edges.mapNotNull { edge ->
|
||||
val edgeMarkers = tick.let {
|
||||
simulation.edges.flatMap { edge ->
|
||||
val n1 = simulation.nodes[edge.a]
|
||||
val n2 = simulation.nodes[edge.b]
|
||||
if (n1 != null && n2 != null && shouldMarkWifiEdge(edge)) {
|
||||
((n1.x + n2.x) / 2f) to ((n1.y + n2.y) / 2f)
|
||||
} else {
|
||||
null
|
||||
if (n1 == null || n2 == null) return@flatMap emptyList()
|
||||
|
||||
val isWifi = shouldMarkDirectEdge(edge, wifiAwarePeerIDs, localID)
|
||||
val isBle = shouldMarkDirectEdge(edge, blePeerIDs, localID)
|
||||
if (!isWifi && !isBle) return@flatMap emptyList()
|
||||
|
||||
val markers = mutableListOf<EdgeMarker>()
|
||||
if (isWifi) {
|
||||
val (x, y) = edgeMarkerPosition(n1.x, n1.y, n2.x, n2.y, iconOffsetPx, sideSign = 1f)
|
||||
markers.add(EdgeMarker(x, y, EdgeTransport.WIFI))
|
||||
}
|
||||
if (isBle) {
|
||||
val side = if (isWifi) -1f else 1f
|
||||
val (x, y) = edgeMarkerPosition(n1.x, n1.y, n2.x, n2.y, iconOffsetPx, sideSign = side)
|
||||
markers.add(EdgeMarker(x, y, EdgeTransport.BLE))
|
||||
}
|
||||
markers
|
||||
}
|
||||
}
|
||||
|
||||
wifiEdgeMidpoints.forEach { (midX, midY) ->
|
||||
edgeMarkers.forEach { marker ->
|
||||
Icon(
|
||||
imageVector = Icons.Filled.Wifi,
|
||||
imageVector = when (marker.transport) {
|
||||
EdgeTransport.WIFI -> Icons.Filled.Wifi
|
||||
EdgeTransport.BLE -> Icons.Outlined.Bluetooth
|
||||
},
|
||||
contentDescription = null,
|
||||
tint = Color(0xFF9C27B0).copy(alpha = 0.82f),
|
||||
tint = colorScheme.onSurface.copy(alpha = 0.82f),
|
||||
modifier = Modifier
|
||||
.offset {
|
||||
IntOffset(
|
||||
x = (midX - halfIconSizePx).roundToInt(),
|
||||
y = (midY - halfIconSizePx).roundToInt()
|
||||
x = (marker.x - halfIconSizePx).roundToInt(),
|
||||
y = (marker.y - halfIconSizePx).roundToInt()
|
||||
)
|
||||
}
|
||||
.size(iconSize)
|
||||
|
||||
Reference in New Issue
Block a user