diff --git a/networksurvey/build.gradle b/networksurvey/build.gradle index ea936154..860e132a 100644 --- a/networksurvey/build.gradle +++ b/networksurvey/build.gradle @@ -131,7 +131,7 @@ dependencies { implementation 'com.craxiom:mqtt-library:0.7.3' - implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.constraintlayout:constraintlayout:2.2.0' implementation 'androidx.recyclerview:recyclerview:1.3.2' implementation 'app.futured.donut:donut:2.2.3' @@ -143,7 +143,7 @@ dependencies { implementation 'com.google.zxing:core:3.5.3' implementation "com.google.dagger:dagger:$hilt_version" - implementation 'androidx.compose.ui:ui-viewbinding:1.7.4' + implementation 'androidx.compose.ui:ui-viewbinding:1.7.5' kapt "com.google.dagger:dagger-compiler:$hilt_version" implementation "com.google.dagger:hilt-android:$hilt_version" kapt "com.google.dagger:hilt-compiler:$hilt_version" @@ -156,7 +156,7 @@ dependencies { implementation 'com.squareup.retrofit2:converter-gson:2.11.0' // Compose - def composeBom = platform('androidx.compose:compose-bom:2024.10.00') + def composeBom = platform('androidx.compose:compose-bom:2024.10.01') implementation(composeBom) androidTestImplementation(composeBom) @@ -170,16 +170,16 @@ dependencies { implementation "androidx.compose.ui:ui-tooling-preview" implementation "androidx.lifecycle:lifecycle-viewmodel-compose" implementation "androidx.lifecycle:lifecycle-runtime-compose" - implementation 'androidx.compose.ui:ui-tooling:1.7.4' - implementation "com.google.accompanist:accompanist-themeadapter-material:0.28.0" + implementation 'androidx.compose.ui:ui-tooling:1.7.5' + implementation "com.google.accompanist:accompanist-themeadapter-material:0.36.0" // Only include firebase in the google play build - regularImplementation platform('com.google.firebase:firebase-bom:33.5.0') + regularImplementation platform('com.google.firebase:firebase-bom:33.5.1') regularImplementation 'com.google.firebase:firebase-analytics' regularImplementation 'com.google.firebase:firebase-crashlytics' testImplementation 'junit:junit:4.13.2' - implementation 'androidx.annotation:annotation:1.9.0' + implementation 'androidx.annotation:annotation:1.9.1' // Uncomment if you want to hunt for memory leaks //debugImplementation 'com.squareup.leakcanary:leakcanary-android:3.0-alpha-1' diff --git a/networksurvey/src/main/java/com/craxiom/networksurvey/fragments/TowerMapFragment.kt b/networksurvey/src/main/java/com/craxiom/networksurvey/fragments/TowerMapFragment.kt index 4a22456b..2d142771 100644 --- a/networksurvey/src/main/java/com/craxiom/networksurvey/fragments/TowerMapFragment.kt +++ b/networksurvey/src/main/java/com/craxiom/networksurvey/fragments/TowerMapFragment.kt @@ -11,8 +11,10 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.appcompat.app.AlertDialog +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.ui.platform.ComposeView import androidx.compose.ui.platform.ViewCompositionStrategy +import androidx.compose.ui.unit.dp import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.viewmodel.compose.viewModel import androidx.localbroadcastmanager.content.LocalBroadcastManager @@ -37,6 +39,7 @@ import java.util.Collections class TowerMapFragment : AServiceDataFragment(), ICellularSurveyRecordListener { private var viewModel: TowerMapViewModel? = null private lateinit var composeView: ComposeView + private var paddingValues: PaddingValues = PaddingValues(2.dp, 2.dp, 2.dp, 2.dp) private var servingCell: ServingCellInfo? = null private var locationListener: LocationListener? = null private var simBroadcastReceiver = object : BroadcastReceiver( @@ -148,6 +151,10 @@ class TowerMapFragment : AServiceDataFragment(), ICellularSurveyRecordListener { viewModel?.onCellularBatchResults(cellularGroup, subscriptionId) } + fun setPaddingInsets(paddingInsets: PaddingValues) { + paddingValues = paddingInsets + } + /** * Checks if the user has accepted the privacy implications of using the tower map feature. If they have not, * then a dialog is shown to them explaining the privacy implications. @@ -208,6 +215,7 @@ class TowerMapFragment : AServiceDataFragment(), ICellularSurveyRecordListener { private fun setupComposeView(servingCell: ServingCellInfo?) { composeView.setContent { viewModel = viewModel() + viewModel!!.setPaddingInsets(paddingValues) if (servingCell?.servingCell != null && servingCell.servingCell.cellularProtocol != CellularProtocol.NONE) { viewModel!!.setSelectedRadioType(servingCell.servingCell.cellularProtocol.name) } diff --git a/networksurvey/src/main/java/com/craxiom/networksurvey/ui/cellular/TowerMapScreen.kt b/networksurvey/src/main/java/com/craxiom/networksurvey/ui/cellular/TowerMapScreen.kt index 9b40b215..26306e7d 100644 --- a/networksurvey/src/main/java/com/craxiom/networksurvey/ui/cellular/TowerMapScreen.kt +++ b/networksurvey/src/main/java/com/craxiom/networksurvey/ui/cellular/TowerMapScreen.kt @@ -8,6 +8,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -33,6 +34,7 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.compose.ui.viewinterop.AndroidView import androidx.core.graphics.drawable.toBitmap @@ -98,6 +100,8 @@ private const val MAX_TOWERS_ON_MAP = 5000 @Composable internal fun TowerMapScreen(viewModel: TowerMapViewModel = viewModel()) { + val paddingInsets by viewModel.paddingInsets.collectAsStateWithLifecycle() + val isLoadingInProgress by viewModel.isLoadingInProgress.collectAsStateWithLifecycle() val isZoomedOutTooFar by viewModel.isZoomedOutTooFar.collectAsStateWithLifecycle() val radio by viewModel.selectedRadioType.collectAsStateWithLifecycle() @@ -119,6 +123,7 @@ internal fun TowerMapScreen(viewModel: TowerMapViewModel = viewModel()) { var expanded by remember { mutableStateOf(false) } var isFollowing by remember { mutableStateOf(false) } + val statusBarHeight = paddingInsets.calculateTopPadding() Surface( modifier = Modifier.fillMaxSize(), color = MaterialTheme.colorScheme.background @@ -131,10 +136,12 @@ internal fun TowerMapScreen(viewModel: TowerMapViewModel = viewModel()) { } }) + TopAppBarOverlay(statusBarHeight) + Box( modifier = Modifier .align(Alignment.TopEnd) - .padding(16.dp) + .padding(top = statusBarHeight + 2.dp, end = 16.dp) ) { // Button to show the DropdownMenu @@ -169,7 +176,7 @@ internal fun TowerMapScreen(viewModel: TowerMapViewModel = viewModel()) { Box( modifier = Modifier .align(Alignment.BottomEnd) - .padding(16.dp) + .padding(vertical = paddingInsets.calculateBottomPadding(), horizontal = 16.dp) ) { Column { Surface( @@ -220,7 +227,7 @@ internal fun TowerMapScreen(viewModel: TowerMapViewModel = viewModel()) { Column( modifier = Modifier .align(Alignment.BottomStart) - .padding(16.dp) + .padding(vertical = paddingInsets.calculateBottomPadding(), horizontal = 16.dp) ) { if (servingCells.size > 1) { // Only show the drop down if there is more than one option @@ -290,7 +297,7 @@ internal fun TowerMapScreen(viewModel: TowerMapViewModel = viewModel()) { contentAlignment = Alignment.TopCenter, modifier = Modifier .fillMaxSize() - .padding(8.dp) + .padding(top = statusBarHeight) ) { CircularProgressIndicator() } @@ -313,6 +320,7 @@ internal fun OsmdroidMapView( viewModel.towerOverlayGroup.setMaxClusteringZoomLevel(14) mapView.setTileSource(TileSourceFactory.MAPNIK) + mapView.zoomController.display.setMarginPadding(.75f, .5f) mapView.zoomController.setVisibility(CustomZoomButtonsController.Visibility.ALWAYS) mapView.setMultiTouchControls(true) @@ -355,6 +363,17 @@ internal fun OsmdroidMapView( ) } +@Composable +fun TopAppBarOverlay(height: Dp) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(height) + .background(Color.Black.copy(alpha = 0.25f)) + ) { + } +} + @Composable fun SimCardDropdown( servingCells: HashMap, diff --git a/networksurvey/src/main/java/com/craxiom/networksurvey/ui/cellular/model/TowerMapViewModel.kt b/networksurvey/src/main/java/com/craxiom/networksurvey/ui/cellular/model/TowerMapViewModel.kt index 9ebfa3ea..862167f5 100644 --- a/networksurvey/src/main/java/com/craxiom/networksurvey/ui/cellular/model/TowerMapViewModel.kt +++ b/networksurvey/src/main/java/com/craxiom/networksurvey/ui/cellular/model/TowerMapViewModel.kt @@ -2,6 +2,8 @@ package com.craxiom.networksurvey.ui.cellular.model import android.graphics.DashPathEffect import android.location.Location +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.ui.unit.dp import com.craxiom.networksurvey.model.CellularProtocol import com.craxiom.networksurvey.model.CellularRecordWrapper import com.craxiom.networksurvey.ui.ASignalChartViewModel @@ -24,6 +26,9 @@ import java.util.Objects */ internal class TowerMapViewModel : ASignalChartViewModel() { + private var _paddingInsets = MutableStateFlow(PaddingValues(0.dp, 0.dp, 0.dp, 0.dp)) + val paddingInsets = _paddingInsets.asStateFlow() + private var _servingCells = MutableStateFlow>(HashMap()) // val servingCells = _servingCells.asStateFlow() @@ -67,6 +72,10 @@ internal class TowerMapViewModel : ASignalChartViewModel() { private val _currentLocation = MutableStateFlow(null) + fun setPaddingInsets(paddingValues: PaddingValues) { + _paddingInsets.value = paddingValues + } + fun setNoTowersFound(noTowersFound: Boolean) { _noTowersFound.value = noTowersFound } diff --git a/networksurvey/src/main/java/com/craxiom/networksurvey/ui/main/AppNavigation.kt b/networksurvey/src/main/java/com/craxiom/networksurvey/ui/main/AppNavigation.kt index a77b10f9..34c18f8d 100644 --- a/networksurvey/src/main/java/com/craxiom/networksurvey/ui/main/AppNavigation.kt +++ b/networksurvey/src/main/java/com/craxiom/networksurvey/ui/main/AppNavigation.kt @@ -25,6 +25,7 @@ import com.craxiom.networksurvey.databinding.ContainerWifiSpectrumFragmentBindin import com.craxiom.networksurvey.fragments.BLUETOOTH_DATA_KEY import com.craxiom.networksurvey.fragments.BluetoothDetailsFragment import com.craxiom.networksurvey.fragments.MqttFragment +import com.craxiom.networksurvey.fragments.TowerMapFragment import com.craxiom.networksurvey.fragments.WifiDetailsFragment import com.craxiom.networksurvey.fragments.WifiSpectrumFragment import com.craxiom.networksurvey.fragments.model.MqttConnectionSettings @@ -185,9 +186,10 @@ fun QrCodeShareInCompose(paddingValues: PaddingValues) { @Composable fun TowerMapInCompose(paddingValues: PaddingValues) { AndroidViewBinding( - ContainerTowerMapFragmentBinding::inflate, - //modifier = Modifier.padding(paddingValues = paddingValues) + ContainerTowerMapFragmentBinding::inflate ) { + val fragment = towerMapFragmentContainerView.getFragment() + fragment.setPaddingInsets(paddingValues) } }