Checklists in the body, colour from tags, and commit-derived CalVer #4

Merged
bvandeusen merged 73 commits from dev into main 2026-08-29 13:39:45 -04:00
2 changed files with 30 additions and 27 deletions
Showing only changes of commit f92a3d0a99 - Show all commits
@@ -79,10 +79,12 @@ object AppUpdate {
* Every uncertain answer is `false`: the cautious one costs nothing.
*/
fun onWifi(context: Context): Boolean {
val manager = context.getSystemService(ConnectivityManager::class.java) ?: return false
val active = manager.activeNetwork ?: return false
val caps = manager.getNetworkCapabilities(active) ?: return false
return caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
val caps =
context
.getSystemService(ConnectivityManager::class.java)
?.let { manager -> manager.activeNetwork?.let(manager::getNetworkCapabilities) }
return caps != null &&
caps.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) &&
caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_NOT_METERED)
}
@@ -88,30 +88,31 @@ class UpdateViewModel(
* when one ran recently: flicking between two apps is not a request to re-check.
*/
fun checkInBackground() {
if (state.busy) return
// Already fetched and waved away — say so again. "Later" is for that sitting,
// not forever, and without this the early return below would mean a single
// dismissal silenced the update permanently. Which is precisely the "lost"
// this whole path exists to prevent.
if (state.ready) {
if (state.nagDismissed) state = state.copy(nagDismissed = false)
return
}
// Already found one and never fetched it — almost always because the last look
// happened on mobile data. Retry the FETCH rather than the check, and ignore
// the interval: this is what makes an update found on the train arrive when
// the person gets home, instead of waiting out six hours first.
if (state.available != null) {
if (AppUpdate.onWifi(context)) viewModelScope.launch { download() }
return
}
val now = System.currentTimeMillis()
if (now - lastCheckAt < CHECK_INTERVAL_MS) return
lastCheckAt = now
runCheck(fetch = true)
when {
state.busy -> Unit
// Already fetched and waved away — say so again. "Later" is for that
// sitting, not forever, and without this branch a single dismissal would
// silence the update permanently. Which is precisely the "lost" this whole
// path exists to prevent.
state.ready -> if (state.nagDismissed) state = state.copy(nagDismissed = false)
// Found one and never fetched it — almost always because the last look
// happened on mobile data. Retry the FETCH rather than the check, and
// ignore the interval: this is what makes an update found on the train
// arrive when the person gets home instead of waiting out six hours.
state.available != null ->
if (AppUpdate.onWifi(context)) viewModelScope.launch { download() }
// Flicking between two apps is not a request to re-check.
now - lastCheckAt < CHECK_INTERVAL_MS -> Unit
else -> {
lastCheckAt = now
runCheck(fetch = true)
}
}
}
private fun runCheck(fetch: Boolean) {