refactor(ui): migrate MapView dialog to Compose M3 + drop legacy material dependency (#5988)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
James Rich
2026-06-28 09:24:44 -05:00
committed by GitHub
parent eb7bfce4d4
commit 23c6d2402e
4 changed files with 53 additions and 41 deletions

View File

@@ -235,7 +235,7 @@ dependencies {
implementation(libs.jetbrains.compose.material3.adaptive)
implementation(libs.jetbrains.compose.material3.adaptive.layout)
implementation(libs.jetbrains.compose.material3.adaptive.navigation)
implementation(libs.material)
implementation(libs.androidx.appcompat)
implementation(libs.compose.multiplatform.animation)
implementation(libs.compose.multiplatform.material3)
implementation(libs.compose.multiplatform.ui.tooling.preview)
@@ -283,7 +283,6 @@ dependencies {
googleImplementation(libs.dd.sdk.android.logs)
googleImplementation(libs.dd.sdk.android.rum)
googleImplementation(libs.dd.sdk.android.session.replay)
googleImplementation(libs.dd.sdk.android.session.replay.material)
googleImplementation(libs.dd.sdk.android.timber)
googleImplementation(libs.dd.sdk.android.trace)
googleImplementation(libs.dd.sdk.android.trace.otel)

View File

@@ -67,7 +67,6 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import co.touchlab.kermit.Logger
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import kotlinx.coroutines.launch
import org.jetbrains.compose.resources.StringResource
import org.jetbrains.compose.resources.stringResource
@@ -229,6 +228,7 @@ fun MapView(
var showDownloadButton: Boolean by remember { mutableStateOf(false) }
var showEditWaypointDialog by remember { mutableStateOf<Waypoint?>(null) }
var showDeleteWaypointDialog by remember { mutableStateOf<Waypoint?>(null) }
var showCacheManagerDialog by remember { mutableStateOf(false) }
var showCurrentCacheInfo by remember { mutableStateOf(false) }
var showPurgeTileSourceDialog by remember { mutableStateOf(false) }
@@ -393,39 +393,6 @@ fun MapView(
}
}
fun showDeleteMarkerDialog(waypoint: Waypoint) {
val builder = MaterialAlertDialogBuilder(context)
builder.setTitle(getString(Res.string.waypoint_delete))
builder.setNeutralButton(getString(Res.string.cancel)) { _, _ ->
Logger.d { "User canceled marker delete dialog" }
}
builder.setNegativeButton(getString(Res.string.delete_for_me)) { _, _ ->
Logger.d { "User deleted waypoint ${waypoint.id} for me" }
mapViewModel.deleteWaypoint(waypoint.id)
}
if (waypoint.locked_to in setOf(0, mapViewModel.myNodeNum ?: 0) && isConnected) {
builder.setPositiveButton(getString(Res.string.delete_for_everyone)) { _, _ ->
Logger.d { "User deleted waypoint ${waypoint.id} for everyone" }
mapViewModel.sendWaypoint(waypoint.copy(expire = 1))
mapViewModel.deleteWaypoint(waypoint.id)
}
}
val dialog = builder.show()
for (
button in
setOf(
androidx.appcompat.app.AlertDialog.BUTTON_NEUTRAL,
androidx.appcompat.app.AlertDialog.BUTTON_NEGATIVE,
androidx.appcompat.app.AlertDialog.BUTTON_POSITIVE,
)
) {
with(dialog.getButton(button)) {
textSize = 12F
isAllCaps = false
}
}
}
fun showMarkerLongPressDialog(id: Int) {
performHapticFeedback()
Logger.d { "marker long pressed id=$id" }
@@ -434,7 +401,7 @@ fun MapView(
if (waypoint.locked_to in setOf(0, mapViewModel.myNodeNum ?: 0) && isConnected) {
showEditWaypointDialog = waypoint
} else {
showDeleteMarkerDialog(waypoint)
showDeleteWaypointDialog = waypoint
}
}
@@ -718,7 +685,7 @@ fun MapView(
onDeleteClicked = { waypoint ->
Logger.d { "User clicked delete waypoint ${waypoint.id}" }
showEditWaypointDialog = null
showDeleteMarkerDialog(waypoint)
showDeleteWaypointDialog = waypoint
},
onDismissRequest = {
Logger.d { "User clicked cancel marker edit dialog" }
@@ -726,6 +693,54 @@ fun MapView(
},
)
}
if (showDeleteWaypointDialog != null) {
val waypoint = showDeleteWaypointDialog ?: return
val canDeleteForEveryone = waypoint.locked_to in setOf(0, mapViewModel.myNodeNum ?: 0) && isConnected
androidx.compose.material3.AlertDialog(
onDismissRequest = {
Logger.d { "User canceled marker delete dialog" }
showDeleteWaypointDialog = null
},
title = { Text(stringResource(Res.string.waypoint_delete)) },
// Both deletes are confirmations; Cancel is the dismiss action (mirrors the old neutral button).
confirmButton = {
Column {
TextButton(
onClick = {
Logger.d { "User deleted waypoint ${waypoint.id} for me" }
mapViewModel.deleteWaypoint(waypoint.id)
showDeleteWaypointDialog = null
},
) {
Text(stringResource(Res.string.delete_for_me))
}
if (canDeleteForEveryone) {
TextButton(
onClick = {
Logger.d { "User deleted waypoint ${waypoint.id} for everyone" }
mapViewModel.sendWaypoint(waypoint.copy(expire = 1))
mapViewModel.deleteWaypoint(waypoint.id)
showDeleteWaypointDialog = null
},
) {
Text(stringResource(Res.string.delete_for_everyone))
}
}
}
},
dismissButton = {
TextButton(
onClick = {
Logger.d { "User canceled marker delete dialog" }
showDeleteWaypointDialog = null
},
) {
Text(stringResource(Res.string.cancel))
}
},
)
}
}
/** F-Droid main map filter dropdown — favorites, waypoints, precision circle, and last-heard time filter slider. */

View File

@@ -24,7 +24,7 @@
<!-- The splash screen icon -->
<item name="windowSplashScreenAnimatedIcon">@drawable/ic_splash</item>
<!-- The theme to switch to after the splash screen is dismissed -->
<item name="postSplashScreenTheme">@style/Theme.Material3.DynamicColors.DayNight.NoActionBar</item>
<item name="postSplashScreenTheme">@style/Theme.AppCompat.DayNight.NoActionBar</item>
</style>
</resources>

View File

@@ -256,7 +256,6 @@ coil-svg = { module = "io.coil-kt.coil3:coil-svg", version.ref = "coil" }
dd-sdk-android-logs = { module = "com.datadoghq:dd-sdk-android-logs", version.ref = "dd-sdk-android" }
dd-sdk-android-rum = { module = "com.datadoghq:dd-sdk-android-rum", version.ref = "dd-sdk-android" }
dd-sdk-android-session-replay = { module = "com.datadoghq:dd-sdk-android-session-replay", version.ref = "dd-sdk-android" }
dd-sdk-android-session-replay-material = { module = "com.datadoghq:dd-sdk-android-session-replay-material", version.ref = "dd-sdk-android" }
dd-sdk-android-timber = { module = "com.datadoghq:dd-sdk-android-timber", version.ref = "dd-sdk-android" }
dd-sdk-android-trace = { module = "com.datadoghq:dd-sdk-android-trace", version.ref = "dd-sdk-android" }
dd-sdk-android-trace-otel = { module = "com.datadoghq:dd-sdk-android-trace-otel", version.ref = "dd-sdk-android" }
@@ -264,7 +263,6 @@ dokka-android-documentation-plugin = { module = "org.jetbrains.dokka:android-doc
markdown-renderer = { module = "com.mikepenz:multiplatform-markdown-renderer", version.ref = "markdownRenderer" }
markdown-renderer-m3 = { module = "com.mikepenz:multiplatform-markdown-renderer-m3", version.ref = "markdownRenderer" }
markdown-renderer-android = { module = "com.mikepenz:multiplatform-markdown-renderer-android", version.ref = "markdownRenderer" }
material = { module = "com.google.android.material:material", version = "1.14.0" }
kable-core = { module = "com.juul.kable:kable-core", version.ref = "kable" }
# mqtt-client 0.4.0 split the monolith into a BOM + core + per-transport modules. The BOM pins the