v0.1.2 — audit fixes

Critical:
  - DetectionService.startInForeground now passes
    FOREGROUND_SERVICE_TYPE_LOCATION OR'd with TYPE_CONNECTED_DEVICE on
    Android 14+. Without this, the system silently revoked location access
    once the screen locked, breaking DeFlock + Waze for foreground-service
    use (the whole point of the foreground service).
  - DeflockClient and WazeClient now skip JSON entries whose lat/lon parse
    to NaN. Previously NaN flowed into Location.distanceBetween, the
    NaN > limit check returned false (IEEE 754), and we submitted a
    full-confidence detection labeled "@0m" — instant false-positive RED
    from a single malformed map entry.

UX:
  - First-run permission flow auto-starts scanning after the user grants
    everything; no second tap on START required.
  - Settings shows a "Restart scan to apply" button when toggling sources
    while scanning. Source toggle changes used to silently no-op until
    the next manual stop+start.

versionCode 1 → 3, versionName 0.1.0 → 0.1.2.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
KaraZajac
2026-04-28 21:22:20 -04:00
parent aa34a1c518
commit 246c738ee4
6 changed files with 60 additions and 17 deletions
@@ -13,6 +13,9 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
@@ -35,6 +38,8 @@ import org.soulstone.overwatch.data.settings.Settings
@Composable
fun SettingsScreen(
settings: Settings,
isRunning: Boolean,
onRestart: () -> Unit,
onBack: () -> Unit
) {
val ble by settings.bleEnabled.collectAsState()
@@ -74,11 +79,29 @@ fun SettingsScreen(
SourceToggle("DEFLOCK • ALPR map (cdn.deflock.me)", deflock) { settings.setDeflockEnabled(it) }
SourceToggle("WAZE • Live police reports", waze) { settings.setWazeEnabled(it) }
Spacer(Modifier.height(8.dp))
Text(
"Source toggles take effect on next Start.",
fontSize = 11.sp,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
if (isRunning) {
Button(
onClick = onRestart,
colors = ButtonDefaults.buttonColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant,
contentColor = MaterialTheme.colorScheme.onSurface
),
shape = RoundedCornerShape(8.dp),
modifier = Modifier.fillMaxWidth()
) {
Text(
text = "Restart scan to apply",
fontSize = 13.sp,
fontFamily = FontFamily.Monospace
)
}
} else {
Text(
"Source toggles take effect on next Start.",
fontSize = 11.sp,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
Spacer(Modifier.height(16.dp))
SectionLabel("Proximity thresholds")