Android overhaul: remove dead code (tokens, an icon, catalogue and fake samples, helpers, unused imports)

Nothing referenced any of these:
* :core:design KvittDimens iconMeta, seesawWidth, KEYPAD_COLUMNS, presetMinHeight, navIndicatorWidth/Height;
  KvittShapes largeIncreased, extraLargeIncreased, extraExtraLarge (the FAB's 20 is `fab`); KvittSpacing
  navigationBarHeight (ShortNavigationBar draws its own 64 dp); KvittMotion's spatial/effects springs, hero count,
  bunting stagger, shared-axis, sheet-enter and keypad-swap values (only the seesaw spring is used); the
  segmentedItem builder and snackbarMillis (KvittSnackbarVisuals maps the duration itself); KvittIcon.Description
  with its two drawables.
* Catalogue sample Samples.renamedGroceries; fake scenarios SettleScenarios.partnerOwes and longAccountIds.
* :data Clock.todayDate().
* Unused imports in Common.kt, Settle.kt, Timeline.kt, AnalyticsScenarios.kt, Clock.kt.

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 23:04:32 +02:00
parent 515b60fc65
commit e08aaf099b
14 changed files with 8 additions and 122 deletions
@@ -57,7 +57,6 @@ object Samples {
val fees = category("000000000014", DefaultCategoryKey.FEES, "account_balance", ColorToken.AMBER, 95)
val other = category("00000000000a", DefaultCategoryKey.OTHER, "category", ColorToken.GREY, 100)
val pant = Category(CategoryId("01920000-0000-7000-8000-0000000000c1"), null, "Pant", "water_drop", ColorToken.TEAL, 110, archived = true)
val renamedGroceries = groceries.copy(customName = "Matvaror")
/** A long custom name: two lines with an ellipsis in the quick row (D-081). */
val renovation = Category(CategoryId("01920000-0000-7000-8000-0000000000c2"), null, "Renovering av sommarstugan", "build", ColorToken.BROWN, 120, archived = false)
@@ -50,7 +50,6 @@ import androidx.compose.ui.semantics.stateDescription
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
@@ -88,22 +87,9 @@ fun KvittCard(
/** The fill of a segmented group's items: `card` (default) or `surface-container-low` (soft). */
enum class GroupFill { Card, Soft }
/** One item of a [SegmentedGroup]: its shape and fill. Built by [SegmentedGroup], or by [segmentedItem] row by row. */
/** One item of a [SegmentedGroup]: its shape and fill. */
class SegmentedItemScope internal constructor(val index: Int, val count: Int, val shape: Shape, val fill: Color)
/**
* The scope of item [index] of [count] of a segmented group, for building the group one row at a time where
* [SegmentedGroup] cannot hold the rows, such as one `LazyColumn` item per row (S-12): the item gets the §3.5 group
* shape (outer corners 24 on the ends, inner 8) and the [fill]; the caller spaces the items with
* `KvittTheme.spacing.groupGap`. Unlike [SegmentedGroup] it casts no shared group shadow (one per item would show
* between the rows), so lazily built groups are flat in light theme too.
*/
@Composable
fun segmentedItem(index: Int, count: Int, fill: GroupFill = GroupFill.Card): SegmentedItemScope {
val color = if (fill == GroupFill.Card) KvittTheme.colors.card else MaterialTheme.colorScheme.surfaceContainerLow
return SegmentedItemScope(index, count, KvittTheme.shapes.groupItem(index, count), color)
}
/**
* A vertical group of items 3 dp apart with outer corners 24 and inner corners 8 (design-spec §3.5). Each item draws
* its own background with `scope.shape` and `scope.fill` (so a row can tint itself, as the settlement row does).
@@ -517,9 +503,6 @@ fun KvittSnackbar(message: String, modifier: Modifier = Modifier, action: String
}
}
/** How long a snackbar stays: 4 s without an action, 10 s with one (design-spec §3.11). */
fun snackbarMillis(hasAction: Boolean): Long = if (hasAction) 10_000L else 4_000L
/** Loading placeholder blocks (`surface-container-highest`, radius 12); first sync and online fetches only. */
@Composable
fun Skeleton(width: Dp, height: Dp, modifier: Modifier = Modifier, pill: Boolean = false) {
@@ -15,7 +15,6 @@ import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.FilledTonalIconButton
import androidx.compose.material3.IconButton
import androidx.compose.material3.IconButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
@@ -32,7 +32,6 @@ import se.hagstedt.kvitt.design.KvittTheme
import se.hagstedt.kvitt.design.format.DateFormatter
import se.hagstedt.kvitt.design.format.KvittLanguage
import se.hagstedt.kvitt.design.format.MoneyFormatter
import se.hagstedt.kvitt.design.icon.KvittIcon
import se.hagstedt.kvitt.design.theme.KvittDimens
import se.hagstedt.kvitt.model.AuditAction
import se.hagstedt.kvitt.model.AuditSource
@@ -33,7 +33,6 @@ enum class KvittIcon(@param:DrawableRes val outline: Int, @param:DrawableRes val
ContentPaste(R.drawable.ic_content_paste, R.drawable.ic_content_paste_filled),
DateRange(R.drawable.ic_date_range, R.drawable.ic_date_range_filled),
Delete(R.drawable.ic_delete, R.drawable.ic_delete_filled),
Description(R.drawable.ic_description, R.drawable.ic_description_filled),
Devices(R.drawable.ic_devices, R.drawable.ic_devices_filled),
Dns(R.drawable.ic_dns, R.drawable.ic_dns_filled),
Download(R.drawable.ic_download, R.drawable.ic_download_filled),
@@ -7,10 +7,9 @@ import androidx.compose.ui.unit.dp
* is written down anywhere else; the spacing scale is [KvittSpacing].
*/
object KvittDimens {
// Icons (§2.12): 24 default, 18 in chips, 15–16 in row meta, 20 in buttons.
// Icons (§2.12): 24 default, 18 in chips, 16 in hints, 20 in buttons.
val icon = 24.dp
val iconChip = 18.dp
val iconMeta = 15.dp
val iconHint = 16.dp
val iconButton = 20.dp
val iconBadge = 14.dp
@@ -72,7 +71,6 @@ object KvittDimens {
val heroSide = 20.dp
val heroBottom = 20.dp
val heroSettledTop = 28.dp
val seesawWidth = 250.dp
val seesawHeight = 92.dp
val plankLength = 220.dp
val plankThickness = 8.dp
@@ -108,7 +106,6 @@ object KvittDimens {
val keypadKey = 52.dp
val keypadKeyCompact = 46.dp
val keypadDeleteIcon = 26.dp
const val KEYPAD_COLUMNS = 3
val keypadPadding = 12.dp
val keypadBottom = 8.dp
val fieldFocusOutline = 2.dp
@@ -143,7 +140,6 @@ object KvittDimens {
val knobHeight = 44.dp
val previewBar = 72.dp
val exactFieldBorder = 1.dp
val presetMinHeight = 40.dp
val fullPickerMinHeight = 52.dp
val avatarFullPicker = 28.dp
const val NOTES_MIN_LINES = 3
@@ -196,8 +192,6 @@ object KvittDimens {
// Scaffolding (§3.11).
val wordmarkMark = 22.dp
val wordmarkIcon = 15.dp
val navIndicatorWidth = 56.dp
val navIndicatorHeight = 32.dp
val fabHeight = 56.dp
val buttonSmall = 40.dp
val buttonMedium = 56.dp
@@ -1,60 +1,21 @@
package se.hagstedt.kvitt.design.theme
import androidx.compose.animation.core.CubicBezierEasing
import androidx.compose.animation.core.FiniteAnimationSpec
import androidx.compose.animation.core.Spring
import androidx.compose.animation.core.spring
import androidx.compose.ui.unit.dp
// Motion of docs/ux/design-spec.md §2.11.
//
// Expressive status against the pinned Material 3 1.4.0 (design-spec §3.1, §6 open point 5): `MotionScheme`,
// `MotionScheme.expressive()` and the `MaterialTheme(motionScheme = …)` overload are internal in 1.4.0, so neither the
// Expressive scheme nor a custom one can be installed. Fallback: Material components keep 1.4.0's own (standard)
// motion, and Kvitt's components animate with the springs below, which carry the Expressive values of §2.11.
// motion, and Kvitt's own animations use the springs below, which carry the Expressive values of §2.11. Only the
// motions a component uses are defined; add the next one from §2.11 when a component needs it.
/** Spring parameters and the named motions of design-spec §2.11. */
/** The named motions of design-spec §2.11 that Kvitt's components use. */
object KvittMotion {
const val SPATIAL_FAST_DAMPING = 0.6f
const val SPATIAL_FAST_STIFFNESS = 800f
const val SPATIAL_DEFAULT_DAMPING = 0.8f
const val SPATIAL_DEFAULT_STIFFNESS = 380f
const val SPATIAL_SLOW_DAMPING = 0.8f
const val SPATIAL_SLOW_STIFFNESS = 200f
const val EFFECTS_FAST_STIFFNESS = 3800f
const val EFFECTS_DEFAULT_STIFFNESS = 1600f
const val EFFECTS_SLOW_STIFFNESS = 800f
/** Seesaw re-tilt when the global balance changes. */
const val SEESAW_DAMPING = 0.55f
const val SEESAW_STIFFNESS = 300f
/** The hero amount counts from the old to the new value over this many milliseconds, emphasized decelerate. */
const val HERO_COUNT_MILLIS = 400
val EmphasizedDecelerate = CubicBezierEasing(0.05f, 0.7f, 0.1f, 1f)
/** Settling to zero: the bunting drops one pennant at a time with this stagger. */
const val BUNTING_STAGGER_MILLIS = 40
/** Pushed screens: horizontal shared axis, slide distance. S-7 and S-9 enter from the bottom by this fraction. */
val SharedAxisSlide = 30.dp
const val SHEET_ENTER_FRACTION = 0.10f
/** Keypad swap for the system keyboard (design-spec §5.2). */
const val KEYPAD_SWAP_MILLIS = 150
fun <T> fastSpatial(): FiniteAnimationSpec<T> = spring(SPATIAL_FAST_DAMPING, SPATIAL_FAST_STIFFNESS)
fun <T> defaultSpatial(): FiniteAnimationSpec<T> = spring(SPATIAL_DEFAULT_DAMPING, SPATIAL_DEFAULT_STIFFNESS)
fun <T> slowSpatial(): FiniteAnimationSpec<T> = spring(SPATIAL_SLOW_DAMPING, SPATIAL_SLOW_STIFFNESS)
fun <T> fastEffects(): FiniteAnimationSpec<T> = spring(Spring.DampingRatioNoBouncy, EFFECTS_FAST_STIFFNESS)
fun <T> defaultEffects(): FiniteAnimationSpec<T> = spring(Spring.DampingRatioNoBouncy, EFFECTS_DEFAULT_STIFFNESS)
fun <T> slowEffects(): FiniteAnimationSpec<T> = spring(Spring.DampingRatioNoBouncy, EFFECTS_SLOW_STIFFNESS)
fun <T> seesaw(): FiniteAnimationSpec<T> = spring(SEESAW_DAMPING, SEESAW_STIFFNESS)
/**
* Reduced motion (system "remove animations", animator duration scale 0): every spring becomes critically damped
* and immediate (design-spec §2.11).
*/
fun <T> reduced(): FiniteAnimationSpec<T> = spring(Spring.DampingRatioNoBouncy, Spring.StiffnessHigh)
}
@@ -14,7 +14,8 @@ import androidx.compose.ui.unit.dp
// Expressive status against the pinned Material 3 1.4.0 (design-spec §3.1, §6 open point 5): `MaterialShapes`
// (Cookie4Sided, Clover4Leaf, Sunny, Cookie9Sided) is not part of the 1.4.0 release, and `Shapes.largeIncreased`,
// `extraLargeIncreased` and `extraExtraLarge` are internal there. Every shape below therefore uses the stable
// fallback the spec names; the swap to MaterialShapes happens here and nowhere else.
// fallback the spec names (the FAB's largeIncreased 20 is [KvittShapes.fab]); the swap to MaterialShapes happens here
// and nowhere else.
/** Material 3 shape scale: extraSmall 4, small 8, medium 12, large 16, extraLarge 28. */
internal val KvittMaterialShapes = Shapes(
@@ -28,12 +29,6 @@ internal val KvittMaterialShapes = Shapes(
/** Kvitt's named shapes (design-spec §2.9, §2.14). */
@Immutable
data class KvittShapes(
/** largeIncreased 20: the FAB. */
val largeIncreased: CornerBasedShape = RoundedCornerShape(20.dp),
/** extraLargeIncreased 32. */
val extraLargeIncreased: CornerBasedShape = RoundedCornerShape(32.dp),
/** extraExtraLarge 48. */
val extraExtraLarge: CornerBasedShape = RoundedCornerShape(48.dp),
/** Category tile: MaterialShapes.Cookie4Sided, fallback 30 % rounded. */
val categoryTile: Shape = RoundedCornerShape(30),
/** Account tile: MaterialShapes.Clover4Leaf, fallback 16 dp rounded. */
@@ -36,9 +36,8 @@ data class KvittSpacing(
val ledgerRowMin: Dp = 72.dp,
/** Bottom padding of a scrolling column under a FAB. */
val fabClearance: Dp = 120.dp,
/** Top app bar height; bottom navigation height (plus the system inset). */
/** Top app bar height. */
val topAppBarHeight: Dp = 64.dp,
val navigationBarHeight: Dp = 64.dp,
/** Minimum touch target. */
val touchTarget: Dp = 48.dp,
)
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Material Symbols Rounded "description", FILL 0, wght 500, GRAD 0, opsz 24 (Google, Apache License 2.0). Generated from the SVG; do not edit. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<group android:translateY="960">
<path
android:fillColor="@android:color/black"
android:pathData="M361.91-239.28h236.42q17.71 0 29.69-12.05T640-281.2q0-17.71-11.98-29.69t-29.69-11.98H361.67q-17.71 0-29.69 11.98Q320-298.9 320-281.19t12.05 29.81q12.05 12.1 29.86 12.1Zm0-160h236.42q17.71 0 29.69-12.05T640-441.2q0-17.71-11.98-29.69t-29.69-11.98H361.67q-17.71 0-29.69 11.98Q320-458.9 320-441.19t12.05 29.81q12.05 12.1 29.86 12.1ZM242.87-71.87q-37.78 0-64.39-26.61t-26.61-64.39v-634.26q0-37.78 26.61-64.39t64.39-26.61H525.8q18.22 0 34.72 6.84 16.5 6.83 29.18 19.51L781.78-669.7q12.68 12.68 19.51 29.18 6.84 16.5 6.84 34.72v442.93q0 37.78-26.61 64.39t-64.39 26.61H242.87Zm274.26-570.76v-154.5H242.87v634.26h474.26v-434.26h-154.5q-19.15 0-32.33-13.17-13.17-13.18-13.17-32.33Zm-274.26-154.5V-597.13v-200 634.26-634.26Z" />
</group>
</vector>
@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Material Symbols Rounded "description", FILL 1, wght 600, GRAD 0, opsz 24 (Google, Apache License 2.0). Generated from the SVG; do not edit. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<group android:translateY="960">
<path
android:fillColor="@android:color/black"
android:pathData="M364.52-238.3h231.52q18.7 0 31.33-12.92Q640-264.13 640-282.83q0-18.69-12.63-31.32-12.63-12.63-31.33-12.63H363.96q-18.7 0-31.33 12.63Q320-301.52 320-282.83q0 18.7 12.91 31.61 12.92 12.92 31.61 12.92Zm0-160h231.52q18.7 0 31.33-12.92Q640-424.13 640-442.83q0-18.69-12.63-31.32-12.63-12.63-31.33-12.63H363.96q-18.7 0-31.33 12.63Q320-461.52 320-442.83q0 18.7 12.91 31.61 12.92 12.92 31.61 12.92ZM246.78-60.78q-44.3 0-75.15-30.85-30.85-30.85-30.85-75.15v-626.44q0-44.3 30.85-75.15 30.85-30.85 75.15-30.85h277.39q21.09 0 40.4 7.98 19.3 7.98 34.26 22.94L788.3-678.83q14.96 14.96 22.94 34.26 7.98 19.31 7.98 40.4v437.39q0 44.3-30.85 75.15-30.85 30.85-75.15 30.85H246.78Zm266.44-585.44q0 22.09 15.45 37.55 15.46 15.45 37.55 15.45h147l-200-200v147Z" />
</group>
</vector>
@@ -17,7 +17,6 @@ import se.hagstedt.kvitt.model.Measure
import se.hagstedt.kvitt.model.RangePreset
import se.hagstedt.kvitt.model.Share
import se.hagstedt.kvitt.model.SplitMode
import se.hagstedt.kvitt.model.UserId
/**
* Scenarios of S-11 (analytics) and S-12 (drill-down), M7e. All share FakeScenarios.empty's household and clock
@@ -66,15 +66,6 @@ object SettleScenarios {
expenses = proposal.expenses + listOf(expense(0xe4, vardag, jacob, 650_000, "2026-10-12")),
)
/** S-9 with the partner owing globally: the direction defaults to "Anna betalar dig". */
val partnerOwes: FakeScenario = proposal.copy(
expenses = listOf(
expense(0xe1, huset, jacob, 616_900, "2026-10-02"),
expense(0xe2, japan, jacob, 270_000, "2026-10-05"),
expense(0xe3, vardag, anna, 236_900, "2026-10-09"),
),
)
/** S-9 offline with pending changes: settling up works unchanged (AC-11.6). */
val offline: FakeScenario = proposal.copy(
online = false,
@@ -162,9 +153,6 @@ object SettleScenarios {
),
)
/** The long scenario's accounts in created order. */
val longAccountIds: List<AccountId> = longAccounts.map { it.id }
private fun id(suffix: Int): String = "01920000-0000-7000-8000-" + suffix.toString(16).padStart(12, '0')
private fun account(suffix: Int, name: String, createdAt: String, archived: Boolean = false): Account =