fix: correct incorrect rendering and status of map marker points

This commit is contained in:
undef-i
2025-08-03 16:29:06 +08:00
parent 59e9987d7f
commit 4278de2a8d
35 changed files with 201 additions and 115 deletions

4
.gitignore vendored
View File

@@ -13,10 +13,10 @@ captures
.externalNativeBuild
.cxx
local.properties
local.properties
*.ps1
.*.bat
*.jks
*.keystore
*.base64
docs
docs
gradle.properties

0
Task Normal file
View File

View File

@@ -13,8 +13,8 @@ android {
applicationId = "org.noxylva.lbjconsole"
minSdk = 29
targetSdk = 35
versionCode = 9
versionName = "0.1.0"
versionCode = 10
versionName = "0.1.1"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
@@ -60,6 +60,7 @@ android {
}
lint {
disable += "NullSafeMutableLiveData"
warning += "MissingPermission"
}
}

View File

@@ -14,6 +14,7 @@
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>

View File

@@ -62,6 +62,7 @@ import org.noxylva.lbjconsole.ui.screens.HistoryScreen
import org.noxylva.lbjconsole.ui.screens.MapScreen
import org.noxylva.lbjconsole.ui.screens.SettingsScreen
import org.noxylva.lbjconsole.ui.screens.CardMapView
import org.noxylva.lbjconsole.ui.theme.LBJConsoleTheme
import org.noxylva.lbjconsole.util.LocoInfoUtil
@@ -108,6 +109,7 @@ class MainActivity : ComponentActivity() {
private var historyExpandedStates by mutableStateOf<Map<String, Boolean>>(emptyMap())
private var historyScrollPosition by mutableStateOf(0)
private var historyScrollOffset by mutableStateOf(0)
private var historyCardMapStates by mutableStateOf<Map<String, CardMapView>>(emptyMap())
private var mapCenterPosition by mutableStateOf<Pair<Double, Double>?>(null)
private var mapZoomLevel by mutableStateOf(10.0)
private var mapRailwayLayerVisible by mutableStateOf(true)
@@ -365,12 +367,14 @@ class MainActivity : ComponentActivity() {
historyEditMode = historyEditMode,
historySelectedRecords = historySelectedRecords,
historyExpandedStates = historyExpandedStates,
historyMapViewStates = historyCardMapStates,
historyScrollPosition = historyScrollPosition,
historyScrollOffset = historyScrollOffset,
onHistoryStateChange = { editMode, selectedRecords, expandedStates, scrollPosition, scrollOffset ->
onHistoryStateChange = { editMode, selectedRecords, expandedStates, mapStates, scrollPosition, scrollOffset ->
historyEditMode = editMode
historySelectedRecords = selectedRecords
historyExpandedStates = expandedStates
historyCardMapStates = mapStates
historyScrollPosition = scrollPosition
historyScrollOffset = scrollOffset
saveSettings()
@@ -932,9 +936,10 @@ fun MainContent(
historyEditMode: Boolean,
historySelectedRecords: Set<String>,
historyExpandedStates: Map<String, Boolean>,
historyMapViewStates: Map<String, CardMapView>,
historyScrollPosition: Int,
historyScrollOffset: Int,
onHistoryStateChange: (Boolean, Set<String>, Map<String, Boolean>, Int, Int) -> Unit,
onHistoryStateChange: (Boolean, Set<String>, Map<String, Boolean>, Map<String, CardMapView>, Int, Int) -> Unit,
settingsScrollPosition: Int,
@@ -1040,7 +1045,7 @@ fun MainContent(
},
navigationIcon = {
IconButton(onClick = {
onHistoryStateChange(false, emptySet(), historyExpandedStates, historyScrollPosition, historyScrollOffset)
onHistoryStateChange(false, emptySet(), historyExpandedStates, historyMapViewStates, historyScrollPosition, historyScrollOffset)
}) {
Icon(
imageVector = Icons.Default.Close,
@@ -1086,7 +1091,7 @@ fun MainContent(
}
onDeleteRecords(recordsToDelete.toList())
onHistoryStateChange(false, emptySet(), historyExpandedStates, historyScrollPosition, historyScrollOffset)
onHistoryStateChange(false, emptySet(), historyExpandedStates, historyMapViewStates, historyScrollPosition, historyScrollOffset)
}
}
) {
@@ -1151,6 +1156,7 @@ fun MainContent(
editMode = historyEditMode,
selectedRecords = historySelectedRecords,
expandedStates = historyExpandedStates,
mapViewStates = historyMapViewStates,
scrollPosition = historyScrollPosition,
scrollOffset = historyScrollOffset,
onStateChange = onHistoryStateChange

View File

@@ -43,8 +43,14 @@ import org.noxylva.lbjconsole.model.MergeSettings
import org.noxylva.lbjconsole.model.GroupBy
import org.noxylva.lbjconsole.util.LocoInfoUtil
import org.noxylva.lbjconsole.util.TrainTypeUtil
import org.osmdroid.util.BoundingBox
import org.osmdroid.util.GeoPoint
import java.text.SimpleDateFormat
import java.util.*
import androidx.compose.ui.platform.LocalContext
data class CardMapView(val center: GeoPoint, val zoom: Double)
@OptIn(ExperimentalFoundationApi::class)
@Composable
@@ -328,6 +334,7 @@ fun TrainRecordItem(
controller.setZoom(10.0)
controller.setCenter(coordinates)
this.isTilesScaledToDpi = true
tilesScaleFactor = context.resources.displayMetrics.density * 0.2f
this.setUseDataConnection(true)
try {
@@ -409,6 +416,8 @@ fun MergedTrainRecordItem(
mergeSettings: MergeSettings? = null,
isInEditMode: Boolean = false,
selectedRecords: List<TrainRecord> = emptyList(),
mapViewState: CardMapView?,
onMapViewStateChange: (CardMapView) -> Unit,
onToggleSelection: (TrainRecord) -> Unit = {},
onLongClick: (TrainRecord) -> Unit = {},
modifier: Modifier = Modifier
@@ -659,93 +668,152 @@ fun MergedTrainRecordItem(
exit = shrinkVertically(animationSpec = spring(dampingRatio = Spring.DampingRatioNoBouncy, stiffness = Spring.StiffnessMediumLow)) + fadeOut(animationSpec = spring(dampingRatio = Spring.DampingRatioNoBouncy, stiffness = Spring.StiffnessMediumLow))
) {
Column {
val coordinates = remember { latestRecord.getCoordinates() }
val allValidCoordinates = remember {
mergedRecord.records
.mapNotNull { it.getCoordinates() }
.filter { it.latitude != 0.0 || it.longitude != 0.0 }
}
if (allValidCoordinates.isNotEmpty()) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(220.dp)
.padding(vertical = 4.dp)
.clip(RoundedCornerShape(8.dp)),
contentAlignment = Alignment.Center
) {
AndroidView(
modifier = Modifier.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) {},
factory = { context ->
MapView(context).apply {
setTileSource(TileSourceFactory.MAPNIK)
setMultiTouchControls(true)
zoomController.setVisibility(org.osmdroid.views.CustomZoomButtonsController.Visibility.NEVER)
isHorizontalMapRepetitionEnabled = false
isVerticalMapRepetitionEnabled = false
setHasTransientState(true)
setOnTouchListener { v, event ->
v.parent?.requestDisallowInterceptTouchEvent(true)
false
}
this.isTilesScaledToDpi = true
tilesScaleFactor = context.resources.displayMetrics.density * 0.2f
this.setUseDataConnection(true)
addMapListener(object : org.osmdroid.events.MapListener {
override fun onScroll(event: org.osmdroid.events.ScrollEvent?): Boolean {
val center = mapCenter
val zoom = zoomLevelDouble
onMapViewStateChange(CardMapView(center as GeoPoint, zoom))
return true
}
if (coordinates != null) {
Box(
modifier = Modifier
.fillMaxWidth()
.height(220.dp)
.padding(vertical = 4.dp)
.clip(RoundedCornerShape(8.dp)),
contentAlignment = Alignment.Center
) {
AndroidView(
modifier = Modifier.clickable(
indication = null,
interactionSource = remember { MutableInteractionSource() }
) {},
factory = { context ->
MapView(context).apply {
setTileSource(TileSourceFactory.MAPNIK)
setMultiTouchControls(true)
zoomController.setVisibility(org.osmdroid.views.CustomZoomButtonsController.Visibility.NEVER)
isHorizontalMapRepetitionEnabled = false
isVerticalMapRepetitionEnabled = false
setHasTransientState(true)
setOnTouchListener { v, event ->
v.parent?.requestDisallowInterceptTouchEvent(true)
false
}
controller.setZoom(10.0)
controller.setCenter(coordinates)
this.isTilesScaledToDpi = true
this.setUseDataConnection(true)
override fun onZoom(event: org.osmdroid.events.ZoomEvent?): Boolean {
val center = mapCenter
val zoom = zoomLevelDouble
onMapViewStateChange(CardMapView(center as GeoPoint, zoom))
return true
}
})
try {
val railwayTileSource = XYTileSource(
"OpenRailwayMap", 8, 16, 256, ".png",
arrayOf(
"https://a.tiles.openrailwayMap.org/standard/",
"https://b.tiles.openrailwaymap.org/standard/",
"https://c.tiles.openrailwaymap.org/standard/"
),
"© OpenRailwayMap contributors, © OpenStreetMap contributors"
)
try {
val railwayTileSource = XYTileSource(
"OpenRailwayMap", 8, 16, 256, ".png",
arrayOf(
"https://a.tiles.openrailwaymap.org/standard/",
"https://b.tiles.openrailwaymap.org/standard/",
"https://c.tiles.openrailwaymap.org/standard/"
),
"© OpenRailwayMap contributors, © OpenStreetMap contributors"
)
val railwayProvider = MapTileProviderBasic(context)
railwayProvider.tileSource = railwayTileSource
val railwayProvider = MapTileProviderBasic(context)
railwayProvider.tileSource = railwayTileSource
val railwayOverlay = TilesOverlay(railwayProvider, context)
railwayOverlay.loadingBackgroundColor = android.graphics.Color.TRANSPARENT
railwayOverlay.loadingLineColor = android.graphics.Color.TRANSPARENT
val railwayOverlay = TilesOverlay(railwayProvider, context)
railwayOverlay.loadingBackgroundColor = android.graphics.Color.TRANSPARENT
railwayOverlay.loadingLineColor = android.graphics.Color.TRANSPARENT
overlays.add(railwayOverlay)
} catch (e: Exception) {
e.printStackTrace()
}
try {
val locationProvider = GpsMyLocationProvider(context).apply {
locationUpdateMinDistance = 10f
locationUpdateMinTime = 1000
overlays.add(railwayOverlay)
} catch (e: Exception) {
e.printStackTrace()
}
MyLocationNewOverlay(locationProvider, this).apply {
enableMyLocation()
}.also { overlays.add(it) }
} catch (e: Exception) {
e.printStackTrace()
try {
val locationProvider = GpsMyLocationProvider(context).apply {
locationUpdateMinDistance = 10f
locationUpdateMinTime = 1000
}
MyLocationNewOverlay(locationProvider, this).apply {
enableMyLocation()
}.also { overlays.add(it) }
} catch (e: Exception) {
e.printStackTrace()
}
mergedRecord.records.forEach { record ->
record.getCoordinates()?.let { coordinates ->
if (coordinates.latitude != 0.0 || coordinates.longitude != 0.0) {
val recordMap = record.toMap()
val marker = Marker(this)
marker.position = coordinates
val latStr = String.format("%.4f", coordinates.latitude)
val lonStr = String.format("%.4f", coordinates.longitude)
val coordStr = "${latStr}°N, ${lonStr}°E"
marker.title = recordMap["train"]?.toString() ?: "列车"
marker.snippet = coordStr
marker.setInfoWindowAnchor(Marker.ANCHOR_CENTER, 0f)
overlays.add(marker)
if (record == latestRecord) {
marker.showInfoWindow()
}
}
}
}
if (mapViewState != null) {
controller.setZoom(mapViewState.zoom)
controller.setCenter(mapViewState.center)
} else if (allValidCoordinates.size > 1) {
val boundingBox = BoundingBox.fromGeoPoints(allValidCoordinates)
val layoutListener = object : android.view.View.OnLayoutChangeListener {
override fun onLayoutChange(v: android.view.View?, left: Int, top: Int, right: Int, bottom: Int, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int) {
if (width > 0 && height > 0) {
val zoomLevel = org.osmdroid.views.MapView.getTileSystem().getBoundingBoxZoom(boundingBox, width, height)
val latSpan = boundingBox.latitudeSpan
val adjustedCenter = org.osmdroid.util.GeoPoint(
boundingBox.center.latitude + latSpan * 0.25, // Shift center UP (north) to create top padding
boundingBox.center.longitude
)
val newZoom = zoomLevel - 1.0
controller.setZoom(newZoom)
controller.setCenter(adjustedCenter)
onMapViewStateChange(CardMapView(adjustedCenter, newZoom))
removeOnLayoutChangeListener(this)
}
}
}
addOnLayoutChangeListener(layoutListener)
} else if (allValidCoordinates.isNotEmpty()) {
val center = allValidCoordinates.first()
val zoom = 14.0
controller.setZoom(zoom)
controller.setCenter(center)
onMapViewStateChange(CardMapView(center, zoom))
}
}
val marker = Marker(this)
marker.position = coordinates
val latStr = String.format("%.4f", coordinates.latitude)
val lonStr = String.format("%.4f", coordinates.longitude)
val coordStr = "${latStr}°N, ${lonStr}°E"
marker.title = recordMap["train"]?.toString() ?: "列车"
marker.snippet = coordStr
marker.setInfoWindowAnchor(Marker.ANCHOR_CENTER, 0f)
overlays.add(marker)
marker.showInfoWindow()
}
},
update = { mapView -> mapView.invalidate() }
)
},
update = { mapView -> mapView.invalidate() }
)
}
}
if (recordMap.containsKey("position_info")) {
@@ -903,9 +971,10 @@ fun HistoryScreen(
editMode: Boolean = false,
selectedRecords: Set<String> = emptySet(),
expandedStates: Map<String, Boolean> = emptyMap(),
mapViewStates: Map<String, CardMapView> = emptyMap(),
scrollPosition: Int = 0,
scrollOffset: Int = 0,
onStateChange: (Boolean, Set<String>, Map<String, Boolean>, Int, Int) -> Unit = { _, _, _, _, _ -> }
onStateChange: (Boolean, Set<String>, Map<String, Boolean>, Map<String, CardMapView>, Int, Int) -> Unit = { _, _, _, _, _, _ -> }
) {
val refreshKey = latestRecord?.timestamp?.time ?: 0
@@ -935,6 +1004,9 @@ fun HistoryScreen(
val expandedStatesMap = remember(expandedStates) {
mutableStateMapOf<String, Boolean>().apply { putAll(expandedStates) }
}
val mapViewStatesMap = remember(mapViewStates) {
mutableStateMapOf<String, CardMapView>().apply { putAll(mapViewStates) }
}
val listState = rememberLazyListState(
initialFirstVisibleItemIndex = scrollPosition,
@@ -965,28 +1037,28 @@ fun HistoryScreen(
LaunchedEffect(isInEditMode, selectedRecordsList.size) {
val selectedIds = selectedRecordsList.map { it.uniqueId }.toSet()
onStateChange(isInEditMode, selectedIds, expandedStatesMap.toMap(), listState.firstVisibleItemIndex, listState.firstVisibleItemScrollOffset)
onStateChange(isInEditMode, selectedIds, expandedStatesMap.toMap(), mapViewStatesMap.toMap(), listState.firstVisibleItemIndex, listState.firstVisibleItemScrollOffset)
}
LaunchedEffect(expandedStatesMap.toMap()) {
if (!isInEditMode) {
val selectedIds = selectedRecordsList.map { it.uniqueId }.toSet()
delay(50)
onStateChange(isInEditMode, selectedIds, expandedStatesMap.toMap(), listState.firstVisibleItemIndex, listState.firstVisibleItemScrollOffset)
onStateChange(isInEditMode, selectedIds, expandedStatesMap.toMap(), mapViewStatesMap.toMap(), listState.firstVisibleItemIndex, listState.firstVisibleItemScrollOffset)
}
}
LaunchedEffect(listState.firstVisibleItemIndex, listState.firstVisibleItemScrollOffset) {
if (!isInEditMode) {
val selectedIds = selectedRecordsList.map { it.uniqueId }.toSet()
onStateChange(isInEditMode, selectedIds, expandedStatesMap.toMap(), listState.firstVisibleItemIndex, listState.firstVisibleItemScrollOffset)
onStateChange(isInEditMode, selectedIds, expandedStatesMap.toMap(), mapViewStatesMap.toMap(), listState.firstVisibleItemIndex, listState.firstVisibleItemScrollOffset)
}
}
LaunchedEffect(selectedRecordsList.size) {
if (selectedRecordsList.isEmpty() && isInEditMode) {
isInEditMode = false
onStateChange(false, emptySet(), expandedStatesMap.toMap(), listState.firstVisibleItemIndex, listState.firstVisibleItemScrollOffset)
onStateChange(false, emptySet(), expandedStatesMap.toMap(), mapViewStatesMap.toMap(), listState.firstVisibleItemIndex, listState.firstVisibleItemScrollOffset)
}
}
@@ -1092,6 +1164,10 @@ fun HistoryScreen(
mergeSettings = mergeSettings,
isInEditMode = isInEditMode,
selectedRecords = selectedRecordsList,
mapViewState = mapViewStatesMap[item.groupKey],
onMapViewStateChange = { newState ->
mapViewStatesMap[item.groupKey] = newState
},
onToggleSelection = { record ->
if (selectedRecordsList.contains(record)) {
selectedRecordsList.remove(record)

View File

@@ -15,7 +15,7 @@ import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.noxylva.lbjconsole.model.MergeSettings
import org.noxylva.lbjconsole.model.GroupBy
import org.noxylva.lbjconsole.model.TimeWindow
@@ -24,7 +24,6 @@ import org.noxylva.lbjconsole.BackgroundService
import org.noxylva.lbjconsole.NotificationService
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.DisposableEffect
@OptIn(ExperimentalMaterial3Api::class)
@@ -195,23 +194,14 @@ fun SettingsScreen(
val context = LocalContext.current
val notificationService = remember(context) { NotificationService(context) }
var backgroundServiceEnabled by remember { mutableStateOf(false) }
var backgroundServiceEnabled by remember { mutableStateOf<Boolean?>(null) }
val coroutineScope = rememberCoroutineScope()
LaunchedEffect(context) {
backgroundServiceEnabled = SettingsActivity.isBackgroundServiceEnabled(context)
}
LaunchedEffect(backgroundServiceEnabled) {
SettingsActivity.setBackgroundServiceEnabled(context, backgroundServiceEnabled)
if (backgroundServiceEnabled) {
BackgroundService.startService(context)
} else {
BackgroundService.stopService(context)
}
}
var notificationEnabled by remember(context, notificationService) {
mutableStateOf(notificationService.isNotificationEnabled())
}
@@ -233,12 +223,24 @@ fun SettingsScreen(
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Switch(
checked = backgroundServiceEnabled,
onCheckedChange = { enabled ->
backgroundServiceEnabled = enabled
}
)
if (backgroundServiceEnabled == null) {
CircularProgressIndicator(modifier = Modifier.size(24.dp))
} else {
Switch(
checked = backgroundServiceEnabled!!,
onCheckedChange = { enabled ->
backgroundServiceEnabled = enabled
coroutineScope.launch {
SettingsActivity.setBackgroundServiceEnabled(context, enabled)
if (enabled) {
BackgroundService.startService(context)
} else {
BackgroundService.stopService(context)
}
}
}
)
}
}
Row(
@@ -436,4 +438,4 @@ fun SettingsScreen(
.padding(12.dp)
)
}
}
}

0
app/src/main/res/drawable/ic_launcher_background.xml Normal file → Executable file
View File

0
app/src/main/res/drawable/ic_launcher_foreground.xml Normal file → Executable file
View File

0
app/src/main/res/drawable/ic_notification.xml Normal file → Executable file
View File

0
app/src/main/res/drawable/ic_person.xml Normal file → Executable file
View File

0
app/src/main/res/layout/activity_settings.xml Normal file → Executable file
View File

0
app/src/main/res/layout/notification_train_record.xml Normal file → Executable file
View File

0
app/src/main/res/mipmap-anydpi/ic_launcher.xml Normal file → Executable file
View File

0
app/src/main/res/mipmap-anydpi/ic_launcher_round.xml Normal file → Executable file
View File

0
app/src/main/res/mipmap-hdpi/ic_launcher.webp Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 1.4 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

0
app/src/main/res/mipmap-hdpi/ic_launcher_round.webp Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

0
app/src/main/res/mipmap-mdpi/ic_launcher.webp Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 982 B

After

Width:  |  Height:  |  Size: 982 B

0
app/src/main/res/mipmap-mdpi/ic_launcher_round.webp Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

0
app/src/main/res/mipmap-xhdpi/ic_launcher.webp Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

0
app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

0
app/src/main/res/mipmap-xxhdpi/ic_launcher.webp Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

0
app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

0
app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

0
app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 7.6 KiB

0
app/src/main/res/raw/loco_info.csv Normal file → Executable file
View File

0
app/src/main/res/values/colors.xml Normal file → Executable file
View File

0
app/src/main/res/values/strings.xml Normal file → Executable file
View File

0
app/src/main/res/values/themes.xml Normal file → Executable file
View File

0
app/src/main/res/xml/backup_rules.xml Normal file → Executable file
View File

0
app/src/main/res/xml/data_extraction_rules.xml Normal file → Executable file
View File

0
app/src/main/res/xml/file_paths.xml Normal file → Executable file
View File

View File

@@ -20,4 +20,4 @@ kotlin.code.style=official
# Enables namespacing of each library's R class so that its R class includes only the
# resources declared in the library itself and none from the library's dependencies,
# thereby reducing the size of the R class for that library
android.nonTransitiveRClass=true
android.nonTransitiveRClass=true

0
gradlew vendored Normal file → Executable file
View File

View File

@@ -19,6 +19,6 @@ dependencyResolutionManagement {
}
}
rootProject.name = "LBJ Receiver"
rootProject.name = "LBJ_Console"
include(":app")