M6b: core:design fixes after the M7 wave

Bugs: viewerPercentOf reads basis points (Samples in bp); FullSplitPicker and the
split labels use editor_split_full_on_you ("Allt på dig"); AmountInput.of restores
money with both decimals (AmountInput.percent for ratio fields), replacing M7c's
moneyInput; quickRowCategories does the D-060 fill itself; KvittScaffold resolves
resource-backed snackbars (showKvittSnackbar) while shown.

Gaps: ConfirmDialog optional and styled body; KvittButton loading form (M7a uses it,
ProgressBottomButton removed); InviteCodeField wraps after a group, placeholder,
imeAction; EmptyState icon tile and actionEnabled; DateFormatter.monthName and
dayRangeLong; AnalyticsFilterBar periodOwnRow; segmentedItem builder; screen tokens
in KvittDimens (OnboardingDimens removed); common_ok, common_undo; module-proposed
keys recorded in strings.csv; quick-row labels end in an ellipsis on line two.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
This commit is contained in:
2026-10-18 11:35:06 +02:00
parent c4ab35f66e
commit b24c8b5ba3
49 changed files with 655 additions and 261 deletions
@@ -93,8 +93,8 @@ fun AboutContent(state: AboutScreenState?, actions: AboutActions, updateCheckAva
verticalArrangement = Arrangement.spacedBy(KvittTheme.spacing.detailGap),
) {
Column(Modifier.fillMaxWidth().padding(vertical = KvittTheme.spacing.s4), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.spacedBy(KvittTheme.spacing.s2)) {
Box(Modifier.size(KvittTheme.spacing.s12 * 2).background(MaterialTheme.colorScheme.primary, KvittTheme.shapes.avatarLarge).clearAndSetSemantics { }, contentAlignment = Alignment.Center) {
KvittIconImage(KvittIcon.ReceiptLong, null, filled = true, size = KvittTheme.spacing.s12, tint = MaterialTheme.colorScheme.onPrimary)
Box(Modifier.size(KvittDimens.aboutAppMark).background(MaterialTheme.colorScheme.primary, KvittTheme.shapes.avatarLarge).clearAndSetSemantics { }, contentAlignment = Alignment.Center) {
KvittIconImage(KvittIcon.ReceiptLong, null, filled = true, size = KvittDimens.aboutAppMarkIcon, tint = MaterialTheme.colorScheme.onPrimary)
}
Text(stringResource(R.string.settings_about_version, about.versionName, about.versionCode), style = MaterialTheme.typography.headlineMedium, textAlign = TextAlign.Center)
Text(stringResource(DesignR.string.common_tagline), style = MaterialTheme.typography.bodyMedium, color = MaterialTheme.colorScheme.onSurfaceVariant)
@@ -246,8 +246,8 @@ private fun EditorBody(state: RecurringEditorState, actions: RecurringEditorActi
}
SplitMode.RATIO -> {
val viewerTyped = form.ratioTyped == RatioField.Viewer
val viewerText = if (viewerTyped) form.ratioInput.display(language) else AmountInput.of(form.viewerBp.toLong()).display(language)
val partnerText = if (viewerTyped) AmountInput.of((10_000 - form.viewerBp).toLong()).display(language) else form.ratioInput.display(language)
val viewerText = if (viewerTyped) form.ratioInput.display(language) else AmountInput.percent(form.viewerBp.toLong()).display(language)
val partnerText = if (viewerTyped) AmountInput.percent((10_000 - form.viewerBp).toLong()).display(language) else form.ratioInput.display(language)
val focused = when (form.focus) {
EditorFocus.RatioViewer -> RatioField.Viewer
EditorFocus.RatioPartner -> RatioField.Partner
@@ -370,7 +370,7 @@ private fun EditorDialogs(state: RecurringEditorState, actions: RecurringEditorA
EditorDialog.Discard -> ConfirmDialog(
icon = KvittIcon.Close,
title = stringResource(DesignR.string.common_discard_title),
body = "",
body = null,
confirm = stringResource(DesignR.string.common_discard),
dismiss = stringResource(DesignR.string.common_keep_editing),
onConfirm = actions.onDiscard,
@@ -14,6 +14,7 @@ import kotlinx.coroutines.launch
import se.hagstedt.kvitt.design.component.AccountChoice
import se.hagstedt.kvitt.design.component.RatioField
import se.hagstedt.kvitt.design.component.quickRowCategories
import se.hagstedt.kvitt.design.component.viewerPercentOf
import se.hagstedt.kvitt.design.format.AmountInput
import se.hagstedt.kvitt.design.format.AmountKey
import se.hagstedt.kvitt.feature.settings.common.UiMessage
@@ -64,7 +65,7 @@ data class RecurringEditorState(
val canSave: Boolean get() = online && !busy && changed && valid && !errors.any
/** The account's default ratio for "Kontots standard 60/40", viewer first. */
val viewerDefaultPercent: Int get() = (account?.defaultShares?.get(options.me.id) ?: BP_TOTAL / 2) / 100
val viewerDefaultPercent: Int get() = viewerPercentOf(account?.defaultShares.orEmpty(), options.me.id)
val dayClampHint: Boolean get() = (form.dayOfMonth ?: 0) >= 29
val resumeHint: Boolean get() = original?.paused == true && !form.paused
}
@@ -139,7 +139,7 @@ data class RecurringForm(
categoryPicked = true,
payer = d.payer,
mode = d.mode,
ratioInput = AmountInput.of((viewerBp ?: BP_TOTAL / 2).toLong()),
ratioInput = AmountInput.percent((viewerBp ?: BP_TOTAL / 2).toLong()),
exactTyped = typed,
exactInput = d.exactOre?.get(typed)?.let { AmountInput.of(it) } ?: AmountInput(),
fullOn = d.fullOn ?: me,
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Strings of :feature:settings (M7f), keys from docs/ux/strings.csv (module=settings). Keys marked PROPOSED are
not in strings.csv yet; the M7f report proposes them. Generated; change the CSV first. -->
<!-- Strings of :feature:settings (M7f), keys from docs/ux/strings.csv (module=settings). Generated; change the CSV
first. -->
<resources>
<string name="settings_profile_offline_banner">Kräver anslutning. Profilen kan bara ändras när telefonen är online.</string>
<string name="settings_title">Inställningar</string>
@@ -179,16 +179,10 @@
<string name="settings_about_server_version">Serverversion</string>
<string name="settings_about_server_version_unknown">Okänd</string>
<string name="settings_about_licences">Licenser för öppen källkod</string>
<!-- PROPOSED (M7f report): S-15 snackbar after Arkivera; %1$s category name -->
<string name="settings_category_archived_snackbar">%1$s arkiverades</string>
<!-- PROPOSED (M7f report): S-15 snackbar after Återställ från arkiv -->
<string name="settings_category_unarchived_snackbar">%1$s återställdes</string>
<!-- PROPOSED (M7f report): S-13 recurring row subtitle without templates (design-spec S-13) -->
<string name="settings_recurring_summary_none">Inga</string>
<!-- PROPOSED (M7f report): TalkBack state of the archived section (design-spec §3.11 CollapsibleRow) -->
<string name="settings_expanded">utfälld</string>
<!-- PROPOSED (M7f report): TalkBack state of the archived section -->
<string name="settings_collapsed">hopfälld</string>
<!-- PROPOSED (M7f report): S-13 partner row before the partner joins -->
<string name="settings_partner_missing">Partner saknas</string>
</resources>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Strings of :feature:settings (M7f), keys from docs/ux/strings.csv (module=settings). Keys marked PROPOSED are
not in strings.csv yet; the M7f report proposes them. Generated; change the CSV first. -->
<!-- Strings of :feature:settings (M7f), keys from docs/ux/strings.csv (module=settings). Generated; change the CSV
first. -->
<resources>
<string name="settings_profile_offline_banner">Needs connection. Your profile can only be changed online.</string>
<string name="settings_title">Settings</string>
@@ -179,16 +179,10 @@
<string name="settings_about_server_version">Server version</string>
<string name="settings_about_server_version_unknown">Unknown</string>
<string name="settings_about_licences">Open-source licences</string>
<!-- PROPOSED (M7f report): S-15 snackbar after Arkivera; %1$s category name -->
<string name="settings_category_archived_snackbar">%1$s was archived</string>
<!-- PROPOSED (M7f report): S-15 snackbar after Återställ från arkiv -->
<string name="settings_category_unarchived_snackbar">%1$s was restored</string>
<!-- PROPOSED (M7f report): S-13 recurring row subtitle without templates (design-spec S-13) -->
<string name="settings_recurring_summary_none">None</string>
<!-- PROPOSED (M7f report): TalkBack state of the archived section (design-spec §3.11 CollapsibleRow) -->
<string name="settings_expanded">expanded</string>
<!-- PROPOSED (M7f report): TalkBack state of the archived section -->
<string name="settings_collapsed">collapsed</string>
<!-- PROPOSED (M7f report): S-13 partner row before the partner joins -->
<string name="settings_partner_missing">Partner has not joined</string>
</resources>
@@ -97,7 +97,7 @@ class RecurringScreenshotTest(private val state: String) {
editor("edit_exact_over", SettingsScenarios.loaded, SettingsScenarios.netflix) { _, vm ->
vm.toggleSplit()
vm.focus(EditorFocus.Exact)
repeat(4) { vm.onKey(AmountKey.Delete) }
vm.onKey(AmountKey.Clear)
vm.type("200")
},
editor("edit_full", SettingsScenarios.loaded, SettingsScenarios.spotify) { _, vm -> vm.toggleSplit() },