Android overhaul: shared failure texts, saved-split label and limits in :core:design
* format/Failures.kt: FAILURE_NETWORK and commonFailureText, the §14.3.2 code-to-text map that :feature:account
(Errors.kt) and :feature:settings (Messages.kt) each spelled out; both keep only their own codes. The "network"
literals in :feature:onboarding and the two NETWORK constants use FAILURE_NETWORK.
* component/Split.kt: savedSplitLabel, the S-8 and S-16 line ("Kontots standard 50/50", "Egen fördelning 70/30",
"Exakta belopp", "Allt på dig/Anna") that ExpenseDetailScreen.modeLabel and SyncStatusScreen.lostModeLabel
duplicated line for line.
* format/Limits.kt: BP_TOTAL (five copies in four features and a literal in :core:design and S-19) and
DISPLAY_NAME_MAX (three copies in :feature:onboarding and :feature:settings).
Behaviour and goldens unchanged.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TQd3pEP9UeN2uifbHknQ7B
This commit is contained in:
@@ -48,6 +48,7 @@ import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.withStyle
|
||||
import se.hagstedt.kvitt.core.design.R
|
||||
import se.hagstedt.kvitt.design.KvittTheme
|
||||
import se.hagstedt.kvitt.design.format.BP_TOTAL
|
||||
import se.hagstedt.kvitt.design.format.MoneyFormatter
|
||||
import se.hagstedt.kvitt.design.icon.KvittIcon
|
||||
import se.hagstedt.kvitt.design.theme.KvittDimens
|
||||
@@ -113,7 +114,7 @@ fun ratioSpoken(left: User, leftBp: Int, right: User): String {
|
||||
personName(left),
|
||||
MoneyFormatter.basisPoints(leftBp, language),
|
||||
personName(right),
|
||||
MoneyFormatter.basisPoints(10_000 - leftBp, language),
|
||||
MoneyFormatter.basisPoints(BP_TOTAL - leftBp, language),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -202,6 +203,29 @@ fun splitModeLabel(mode: SplitMode, defaultLabel: String): String = when (mode)
|
||||
fun defaultModeLabel(viewerPercent: Int): String =
|
||||
stringResource(R.string.editor_split_mode_default, stringResource(R.string.common_ratio, viewerPercent.toString(), (100 - viewerPercent).toString()))
|
||||
|
||||
/**
|
||||
* A saved split as one line (design-spec S-8, S-16): "Kontots standard 50/50" or "Egen fördelning 70/30" with the
|
||||
* [viewer]'s basis points from [shares] (50/50 for a default split without them), "Exakta belopp", or "Allt på dig" /
|
||||
* "Allt på <[partnerName]>" by who bears the amount.
|
||||
*/
|
||||
@Composable
|
||||
fun savedSplitLabel(mode: SplitMode, shares: List<Share>, viewer: UserId, partnerName: String): String {
|
||||
val language = kvittLanguage()
|
||||
val mineBp = shares.firstOrNull { it.userId == viewer }?.shareBp
|
||||
val ratio = mineBp?.let { stringResource(R.string.common_ratio, MoneyFormatter.basisPoints(it, language), MoneyFormatter.basisPoints(BP_TOTAL - it, language)) }
|
||||
return when (mode) {
|
||||
SplitMode.DEFAULT -> if (ratio != null) stringResource(R.string.editor_split_mode_default, ratio) else defaultModeLabel(HALF_PERCENT)
|
||||
SplitMode.RATIO -> splitModeLabel(mode, "") + (ratio?.let { " $it" } ?: "")
|
||||
SplitMode.EXACT -> splitModeLabel(mode, "")
|
||||
SplitMode.FULL -> {
|
||||
val bearer = shares.firstOrNull { it.shareOre > 0 }?.userId
|
||||
if (bearer == viewer) stringResource(R.string.editor_split_full_on_you) else stringResource(R.string.editor_split_full_on, partnerName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val HALF_PERCENT = 50
|
||||
|
||||
/**
|
||||
* The open split section (design-spec §3.7): a flat section with the header "Delning" and a collapse button, the four
|
||||
* mode chips as a radio group, then [body]: the split bar and preview for `default`, or [RatioEditor],
|
||||
@@ -474,4 +498,3 @@ fun viewerPercentOf(defaultShares: Map<UserId, Int>, viewer: UserId): Int = (def
|
||||
|
||||
private const val HALF_BP = 5_000
|
||||
private const val BP_PER_PERCENT = 100
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package se.hagstedt.kvitt.design.format
|
||||
|
||||
import androidx.annotation.StringRes
|
||||
import se.hagstedt.kvitt.core.design.R
|
||||
|
||||
/** The code of an online call that did not reach the server: `OnlineResult.Failed("network", null)` (D-029). */
|
||||
const val FAILURE_NETWORK = "network"
|
||||
|
||||
/**
|
||||
* The shared snackbar text of a refused online call (design-spec §1, `strings.csv` `error_*`) for the codes every
|
||||
* screen can meet: [FAILURE_NETWORK] is "Kunde inte nå servern", the §14.3.2 codes their text. Null for any other code,
|
||||
* which the screen maps itself (falling back to `error_generic_invalid`).
|
||||
*/
|
||||
@StringRes
|
||||
fun commonFailureText(code: String): Int? = when (code) {
|
||||
FAILURE_NETWORK -> R.string.common_could_not_reach_server
|
||||
"household_incomplete" -> R.string.error_household_incomplete
|
||||
"not_found" -> R.string.error_not_found
|
||||
"forbidden" -> R.string.error_forbidden
|
||||
"rate_limited" -> R.string.error_rate_limited
|
||||
"protocol_unsupported" -> R.string.error_app_too_old
|
||||
"internal", "unavailable", "not_implemented" -> R.string.error_server
|
||||
"validation_failed" -> R.string.error_validation
|
||||
else -> null
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package se.hagstedt.kvitt.design.format
|
||||
|
||||
/** Basis points of a whole: a ratio's per-user shares sum to 10000 bp, 100 % (SPEC §1, §9.3). */
|
||||
const val BP_TOTAL = 10_000
|
||||
|
||||
/** A user's display name is 1 to 40 code points after trimming (SPEC §9.6). */
|
||||
const val DISPLAY_NAME_MAX = 40
|
||||
Reference in New Issue
Block a user