show usage notes in dev builds too, but never send from them

This commit is contained in:
Seb3thehacker committed 2026-10-05 01:31:15 -07:00
1 parent 62fb8babad
commit 302dd6c344
4 files changed
+26 -30

No files matched your search

@@ -51,15 +51,15 @@ object UsageStats {
private fun prefs(context: Context) = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
/**
* Dev builds never send anything and never ask: no switch in Settings, no page in setup, so
* testing doesn't muddy the numbers. Only release builds offer the choice.
* Dev builds show every switch and screen, so they can be tested, but never send anything:
* testing mustn't muddy the numbers.
*/
val choosable: Boolean get() = !BuildConfig.DEBUG
val sends: Boolean get() = !BuildConfig.DEBUG && BuildConfig.STATS_URL.isNotBlank()
fun enabled(context: Context): Boolean = choosable && prefs(context).getBoolean(KEY_ENABLED, false)
fun enabled(context: Context): Boolean = prefs(context).getBoolean(KEY_ENABLED, false)
/** Whether the driver has answered the question in setup, either way. */
fun asked(context: Context): Boolean = !choosable || prefs(context).getBoolean(KEY_ASKED, false)
fun asked(context: Context): Boolean = prefs(context).getBoolean(KEY_ASKED, false)
fun choices(context: Context): Choices {
val p = prefs(context)
@@ -98,7 +98,7 @@ object UsageStats {
* a car recorded mid-send still goes out.
*/
private fun sendSoon(context: Context) {
if (!enabled(context)) return
if (!sends || !enabled(context)) return
if (!sending.compareAndSet(false, true)) { sendAgain = true; return }
val app = context.applicationContext
Thread({
@@ -192,9 +192,8 @@ object UsageStats {
/** Sends the note now; false when it didn't get through. */
private fun send(context: Context): Boolean {
if (!enabled(context)) return true
if (!sends || !enabled(context)) return true
val endpoint = BuildConfig.STATS_URL
if (endpoint.isBlank()) return true
val p = prefs(context)
val note = synchronized(carsLock) { preview(context) }
val sentCars = note.optJSONArray("cars")?.toString()
@@ -55,7 +55,6 @@ import androidx.compose.ui.unit.dp
import app.seb3thehacker.gearslip.AppSettings
import app.seb3thehacker.gearslip.BuildConfig
import app.seb3thehacker.gearslip.CertProvider
import app.seb3thehacker.gearslip.stats.UsageStats
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
@@ -94,9 +93,7 @@ fun SettingsScreen(
ConnectionSection()
if (SHOW_RECOMMENDED_APPS) AppsSection(onOpenRecommendedApps)
CertificateSection()
if (UsageStats.choosable) {
SettingsSection("Usage notes", header = USAGE_STATS_INTRO) { UsageStatsRows(showNote = true) }
}
SettingsSection("Usage notes", header = USAGE_STATS_INTRO) { UsageStatsRows(showNote = true) }
Spacer(Modifier.height(16.dp))
}
}
@@ -287,21 +287,18 @@ private fun pages(context: Context, onRequestCallScreening: () -> Unit): List<Gu
// --- The very end, every time: usage notes. The first time through, leaving the page
// without turning them on is a no; on a replay, the switch shows what was chosen before.
// Dev builds never send, so they skip the page.
if (UsageStats.choosable) {
add(
GuidePage(
title = USAGE_STATS_TITLE,
explanation = USAGE_STATS_INTRO,
content = {
UsageStatsChoices()
DisposableEffect(Unit) {
onDispose { if (!UsageStats.asked(context)) UsageStats.set(context, false) }
}
},
),
)
}
add(
GuidePage(
title = USAGE_STATS_TITLE,
explanation = USAGE_STATS_INTRO,
content = {
UsageStatsChoices()
DisposableEffect(Unit) {
onDispose { if (!UsageStats.asked(context)) UsageStats.set(context, false) }
}
},
),
)
}
/**
@@ -84,7 +84,11 @@ internal fun ColumnScope.UsageStatsRows(showNote: Boolean) {
SettingsRow(
"Send usage notes",
Modifier.toggleable(on, role = Role.Switch) { on = it; save() },
subtitle = if (BuildConfig.STATS_URL.isBlank()) "This build has no stats server, so it sends nothing" else null,
subtitle = when {
BuildConfig.DEBUG -> "Dev build: nothing is ever sent"
BuildConfig.STATS_URL.isBlank() -> "This build has no stats server, so it sends nothing"
else -> null
},
icon = Icons.Filled.Send,
trailing = { Switch(checked = on, onCheckedChange = null) },
)
@@ -154,11 +158,10 @@ private fun Choice(label: String, checked: Boolean, onChange: (Boolean) -> Unit)
/**
* Asks once, for people who set Gearslip up before usage notes existed and so never saw the
* setup page. Either answer is final; Settings changes it later. Release builds only.
* setup page. Either answer is final; Settings changes it later.
*/
@Composable
internal fun UsageStatsPrompt() {
if (!UsageStats.choosable) return
val context = LocalContext.current
var show by remember { mutableStateOf(!UsageStats.asked(context)) }
if (!show) return