From 53e8f8df09413b5893f2662dbf7d9ebd49df42e8 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Jul 2026 16:30:07 +0000 Subject: [PATCH] feat: always-on service cost card with a link to notification settings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The uptime row told users the service ran, not what it cost — and the setting to turn it off lives three screens away. The resource screen now shows a dedicated card (only while the service has run this week) that frames the cost in decision terms: running time and restarts, the relay connections it held while the app was closed, and the measured background battery drain — with a button straight to notification settings where the delivery method can be changed. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_016RJ8EAsdkHx5WHHU2eQJ1P --- .../loggedIn/settings/ResourceUsageScreen.kt | 57 +++++++++++++++++-- amethyst/src/main/res/values/strings.xml | 11 +++- 2 files changed, 63 insertions(+), 5 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/ResourceUsageScreen.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/ResourceUsageScreen.kt index d76c0a1ae3..2b972a6d14 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/ResourceUsageScreen.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/ResourceUsageScreen.kt @@ -39,6 +39,7 @@ import androidx.compose.material3.CardDefaults import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -51,6 +52,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.pluralStringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import com.vitorpamplona.amethyst.Amethyst @@ -65,6 +67,7 @@ import com.vitorpamplona.amethyst.service.resourceusage.ResourceUsageReportAssem import com.vitorpamplona.amethyst.service.resourceusage.ResourceUsageReportAssembler.Companion.formatDurationMs import com.vitorpamplona.amethyst.service.resourceusage.UsageSummary import com.vitorpamplona.amethyst.ui.navigation.navs.INav +import com.vitorpamplona.amethyst.ui.navigation.routes.Route import com.vitorpamplona.amethyst.ui.navigation.routes.routeToMessage import com.vitorpamplona.amethyst.ui.navigation.topbars.TopBarWithBackButton import com.vitorpamplona.amethyst.ui.screen.loggedIn.AccountViewModel @@ -140,6 +143,7 @@ fun ResourceUsageScreen( } SubsystemSection(weekSummary) ActivitySection(weekSummary) + AlwaysOnServiceSection(weekSummary, nav) MemorySection(memory) SendReportSection(accountViewModel, nav, loaded, today, memory) } @@ -310,10 +314,6 @@ private fun ActivitySection(s: UsageSummary) { SettingsDivider() MetricRow(R.string.resource_usage_tor, formatDurationMs(s.torMs)) } - if (s.alwaysOnMs > 0) { - SettingsDivider() - MetricRow(R.string.resource_usage_always_on, formatDurationMs(s.alwaysOnMs)) - } if (s.callMs > 0) { SettingsDivider() MetricRow(R.string.resource_usage_calls, formatDurationMs(s.callMs)) @@ -400,6 +400,55 @@ private fun MemorySection(memory: MemorySnapshot?) { } } +/** + * Decision-support card for the always-on notification service — the one + * background consumer users can directly turn off. Shows what the service + * actually costs in the last 7 days (uptime, the relay connections it holds + * while the app is closed, and the measured background battery drain) and + * links straight to the setting that controls it. + */ +@Composable +private fun AlwaysOnServiceSection( + s: UsageSummary, + nav: INav, +) { + if (s.alwaysOnMs <= 0) return + val starts = s.alwaysOnStarts.toInt() + SettingsSection(R.string.resource_usage_alwayson_section) { + Column( + modifier = Modifier.padding(16.dp), + verticalArrangement = Arrangement.spacedBy(12.dp), + ) { + Text( + text = stringRes(R.string.resource_usage_alwayson_explanation), + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + ) + } + MetricRow( + R.string.resource_usage_alwayson_uptime, + "${formatDurationMs(s.alwaysOnMs)} · ${pluralStringResource(R.plurals.resource_usage_alwayson_starts, starts, starts)}", + ) + SettingsDivider() + MetricRow( + R.string.resource_usage_alwayson_bg_relay, + formatConnHours(s.relayConnMsMobileBg + s.relayConnMsWifiBg), + ) + if (s.batteryDrainBg > 0) { + SettingsDivider() + MetricRow(R.string.resource_usage_alwayson_battery, "${s.batteryDrainBg}%") + } + Column(modifier = Modifier.padding(horizontal = 8.dp, vertical = 4.dp)) { + TextButton( + onClick = { nav.nav(Route.NotificationSettings) }, + modifier = Modifier.align(Alignment.End), + ) { + Text(stringRes(R.string.resource_usage_alwayson_settings_button)) + } + } + } +} + @Composable private fun SendReportSection( accountViewModel: AccountViewModel, diff --git a/amethyst/src/main/res/values/strings.xml b/amethyst/src/main/res/values/strings.xml index e3e5e34e8e..df93f3236c 100644 --- a/amethyst/src/main/res/values/strings.xml +++ b/amethyst/src/main/res/values/strings.xml @@ -3213,11 +3213,20 @@ Remote signatures Proof-of-work mining Tor uptime - Always-on notification service Time in calls Time in audio rooms Location listening Battery used (in app / background) + Background notification service + Keeps connections to your relays open while the app is closed, so notifications arrive without Google’s push servers. While enabled, this is usually the largest background battery cost. If battery matters more to you than instant notifications, you can change the delivery method or turn it off. + Running time + + %1$d start + %1$d starts + + Relay connections held while closed + Battery drained meanwhile (whole device) + Change notification settings Data by feature (7 days) Relay sync Images