From c6d6088189e53f10fb8ffa5733d60683b4ae9f6a Mon Sep 17 00:00:00 2001 From: stylianosgakis Date: Thu, 27 Aug 2026 16:34:57 +0200 Subject: [PATCH 1/3] chore: add import style rule to CLAUDE.md Import the type, never the namespace. An import may shorten a qualified reference only when the short name still says what it is to someone reading that line cold. Sealed subclasses and enum entries pass that test and stay allowed; around 1200 such imports already exist and they are the house style. Members reached through a receiver that carries the meaning do not: Res.string, Res.drawable and Clock.System are banned, since string.FOO and System.now() lose what Res.string.FOO and Clock.System.now() tell the reader. Also bans import-only changes to lines that are not otherwise being edited. PR #3100 carried 29 gratuitous new imports and ~60 rewritten call sites through a single screen refactor, which buried the real change under churn. --- CLAUDE.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 80f1cbf821..55130dbcf9 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -480,6 +480,47 @@ Configuration in `.editorconfig`: - **Entry functions:** `{feature}Entries` - **Use cases:** `{Action}{Domain}UseCase` (e.g., `GetHomeDataUseCase`) +### Imports + +**Import the type, never the namespace.** An import may shorten a qualified reference only when the +short name still says what it is to someone reading that line cold, without scrolling to the import +list. Sealed subclasses, enum entries and other types pass that test. A member reached through a +receiver that carries the meaning does not. + +Always allowed (this is the house style, ~1200 such imports exist): + +```kotlin +import com.hedvig.android.feature.home.home.ui.HomeUiState.Success // `is Success ->` reads fine +import com.hedvig.android.design.system.hedvig.TooltipDefaults.BeakDirection.TopEnd +import kotlin.time.Duration.Companion.seconds // enables the `5.seconds` idiom +``` + +Never allowed, because the receiver is the meaning: + +```kotlin +import hedvig.resources.Res.string // ❌ `stringResource(string.FOO)` → use `Res.string.FOO` +import hedvig.resources.Res.drawable // ❌ `painterResource(drawable.x)` → use `Res.drawable.x` +import kotlin.time.Clock.System // ❌ `System.now()` → use `Clock.System.now()` +import ...hedvig.TooltipDefaults.defaultStyle // ❌ `defaultStyle` alone names nothing +``` + +`Res` and `Clock` are the two that come up most: 193 files import `hedvig.resources.Res` plainly and +that is the standard. `System.now()` additionally reads as `java.lang.System` to anyone skimming. + +**Separately: never make an import-only change to a line you are not otherwise editing.** Converting +existing `HomeEvent.RefreshData` call sites to a bare `RefreshData` (or the reverse) is a whole-file +rewrite disguised as a diff. It buries the real change under churn and makes review and `git blame` +worse for no behavioural gain. + +**Why:** both halves of this rule protect the reader. The first protects whoever reads the line +later, the second protects whoever reviews the PR now. PR #3100 was one screen refactor carrying 29 +gratuitous new imports and ~60 rewritten call sites, and the formatting noise overshadowed the +actual work. + +**How to apply:** if you are touching a line for a real reason, use the correct form. If you are not +touching it, leave its qualification exactly as it is. Import cleanups that are genuinely wanted go +in their own commit. + ### Comments Code comments and KDoc must describe the **current** code and stand on their own. A comment fails to earn its place in two ways: it tells the wrong kind of story, or it repeats what is already there. Before writing one, apply the test: *would this make sense to someone reading the file cold, with no knowledge of the PR, the conversation, or what was decided against?* If not, it does not belong in the source. Do not reference: From 698cf5d980ac0b5ff66953c3f2f968046e2c2468 Mon Sep 17 00:00:00 2001 From: stylianosgakis Date: Thu, 27 Aug 2026 16:50:51 +0200 Subject: [PATCH 2/3] chore: add NamespaceImport lint check to enforce the import rule Reports imports that shorten a qualified reference past the point where the short name still says what it is, so Res.string.FOO cannot silently become string.FOO. An import is flagged when its owner resolves to a class and the imported name is a member, which leaves nothing meaningful at the use site. Types are left alone, so sealed subclasses and enum entries keep working the way they do today. Two escape hatches sit alongside that: a deny list for capitalized names that are still meaningless on their own, seeded with kotlin.time.Clock.System, and an allow list, both configurable through the shared lint.xml the way ComposeM2Api already is. Resolving the owner rather than matching path text is what keeps Kotlin/Native interop packages such as platform.Foundation from being misread as classes. hedvig-lint had no test source set, so this adds one along with the lint-tests dependency. Seven cases cover both directions of the rule. --- gradle/libs.versions.toml | 1 + hedvig-lint/build.gradle.kts | 3 + .../hedvig/android/lint/HedvigLintRegistry.kt | 1 + .../android/lint/NamespaceImportDetector.kt | 122 +++++++++++ .../lint/NamespaceImportDetectorTest.kt | 198 ++++++++++++++++++ 5 files changed, 325 insertions(+) create mode 100644 hedvig-lint/src/main/kotlin/com/hedvig/android/lint/NamespaceImportDetector.kt create mode 100644 hedvig-lint/src/test/kotlin/com/hedvig/android/lint/NamespaceImportDetectorTest.kt diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index cc345f31c8..f3bd52e4e1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -247,6 +247,7 @@ zXing = { module = "com.google.zxing:core", version.ref = "zXing" } zoomable = { module = "com.mxalbert.zoomable:zoomable", version.ref = "zoomable" } # lint dependencies lintApi = { module = "com.android.tools.lint:lint-api", version.ref = "lintApi" } +lintTests = { module = "com.android.tools.lint:lint-tests", version.ref = "lintApi" } # temporary bug workaround androidx-kmp-preview-bug1-workaround = { module = "androidx.customview:customview-poolingcontainer", version = "1.1.0" } diff --git a/hedvig-lint/build.gradle.kts b/hedvig-lint/build.gradle.kts index 585c1e0326..595239799e 100644 --- a/hedvig-lint/build.gradle.kts +++ b/hedvig-lint/build.gradle.kts @@ -9,6 +9,9 @@ plugins { dependencies { compileOnly(libs.lintApi) + testImplementation(libs.junit) + testImplementation(libs.lintApi) + testImplementation(libs.lintTests) } java { diff --git a/hedvig-lint/src/main/kotlin/com/hedvig/android/lint/HedvigLintRegistry.kt b/hedvig-lint/src/main/kotlin/com/hedvig/android/lint/HedvigLintRegistry.kt index bf5c2ddf08..f719a19c90 100644 --- a/hedvig-lint/src/main/kotlin/com/hedvig/android/lint/HedvigLintRegistry.kt +++ b/hedvig-lint/src/main/kotlin/com/hedvig/android/lint/HedvigLintRegistry.kt @@ -8,6 +8,7 @@ import com.android.tools.lint.detector.api.Issue class HedvigLintRegistry : IssueRegistry() { override val issues: List = listOf( Material2Detector.ISSUE, + NamespaceImportDetector.ISSUE, ) override val api: Int = CURRENT_API diff --git a/hedvig-lint/src/main/kotlin/com/hedvig/android/lint/NamespaceImportDetector.kt b/hedvig-lint/src/main/kotlin/com/hedvig/android/lint/NamespaceImportDetector.kt new file mode 100644 index 0000000000..b824c0ed7d --- /dev/null +++ b/hedvig-lint/src/main/kotlin/com/hedvig/android/lint/NamespaceImportDetector.kt @@ -0,0 +1,122 @@ +package com.hedvig.android.lint + +import com.android.tools.lint.client.api.UElementHandler +import com.android.tools.lint.detector.api.Category +import com.android.tools.lint.detector.api.Issue +import com.android.tools.lint.detector.api.JavaContext +import com.android.tools.lint.detector.api.Severity +import com.android.tools.lint.detector.api.SourceCodeScanner +import com.android.tools.lint.detector.api.StringOption +import com.android.tools.lint.detector.api.isKotlin +import com.hedvig.android.lint.config.Priorities +import com.hedvig.android.lint.util.OptionLoadingDetector +import com.hedvig.android.lint.util.StringSetLintOption +import com.hedvig.android.lint.util.sourceImplementation +import org.jetbrains.uast.UElement +import org.jetbrains.uast.UImportStatement + +private const val NamespaceImportDetectorIssueId = "NamespaceImport" + +/** + * Reports imports that shorten a qualified reference past the point where the short name still says + * what it is, such as `import hedvig.resources.Res.string` turning `Res.string.FOO` into `string.FOO`. + * + * Importing a type is fine, so a sealed subclass or enum entry (`HomeUiState.Success`) is left alone. + * Importing a member off a class owner is not, because the owner is what gave the name its meaning. + * A capitalized name that is still meaningless on its own, such as `Clock.System`, is covered by + * [DENY_LIST]. + */ +internal class NamespaceImportDetector + @JvmOverloads + constructor( + private val extraDeniedImports: StringSetLintOption = StringSetLintOption(DENY_LIST), + private val allowedImports: StringSetLintOption = StringSetLintOption(ALLOW_LIST), + ) : OptionLoadingDetector(extraDeniedImports, allowedImports), SourceCodeScanner { + override fun getApplicableUastTypes(): List> = listOf>( + UImportStatement::class.java, + ) + + override fun createUastHandler(context: JavaContext): UElementHandler? { + val language = context.uastFile?.lang ?: return null + if (!isKotlin(language)) return null + return object : UElementHandler() { + override fun visitImportStatement(node: UImportStatement) { + if (node.isOnDemand) return // Wildcards are owned by ktlint's no-wildcard-imports. + val importText = node.sourcePsi?.text ?: return + // An alias is a deliberate act of renaming, and gives the use site a name of its own. + if (importText.contains(" as ")) return + val qualifiedName = importText.removePrefix("import").trim() + + val importedName = qualifiedName.substringAfterLast('.') + val ownerPath = qualifiedName.substringBeforeLast('.', "") + val ownerName = ownerPath.substringAfterLast('.') + if (importedName.isEmpty() || ownerName.isEmpty()) return + // A lowercase owner is a package, so this is a plain top-level import. + if (!ownerName.first().isUpperCase()) return + // `Duration.Companion.seconds` and friends exist to enable the `5.seconds` receiver idiom. + if (ownerName == "Companion") return + // A capitalized path segment is not proof of a class: `platform.Foundation` is a package. + if (context.evaluator.findClass(ownerPath) == null) return + if (qualifiedName in allowedImports.value) return + + val importsAMember = importedName.first().isLowerCase() + val isDeniedByName = qualifiedName in DEFAULT_DENIED_IMPORTS || + qualifiedName in extraDeniedImports.value + if (!importsAMember && !isDeniedByName) return + + context.report( + issue = ISSUE, + location = context.getLocation(node), + message = "Import `$ownerName` and write `$ownerName.$importedName` at the use site. " + + "On its own, `$importedName` no longer says what it is.", + ) + } + } + } + + companion object { + /** + * Imports whose final segment is capitalized, so they read as a type, but which still leave + * nothing meaningful behind at the use site. + */ + private val DEFAULT_DENIED_IMPORTS = setOf( + "kotlin.time.Clock.System", + ) + + internal val DENY_LIST = StringOption( + "denied-member-imports", + "A comma-separated list of fully qualified imports to reject in addition to the built-in ones.", + null, + "This property should define a comma-separated list of fully qualified imports that must " + + "never be used, even though their final segment is capitalized", + ) + + internal val ALLOW_LIST = StringOption( + "allowed-member-imports", + "A comma-separated list of fully qualified member imports that should be allowed.", + null, + "This property should define a comma-separated list of fully qualified member imports that " + + "are allowed to shorten their receiver away", + ) + + val ISSUE = Issue.create( + id = NamespaceImportDetectorIssueId, + briefDescription = "Importing a member hides the receiver that carries its meaning", + explanation = """ + Import the type, never the namespace. An import may shorten a qualified reference only when \ + the short name still says what it is to someone reading that line cold. + + Sealed subclasses and enum entries pass that test, so `HomeUiState.Success` may be imported \ + as `Success`. Members reached through a receiver that carries the meaning do not: \ + `Res.string.FOO` must not become `string.FOO`, and `Clock.System.now()` must not become \ + `System.now()`, which additionally reads as `java.lang.System`. + """, + category = Category.CORRECTNESS, + priority = Priorities.NORMAL, + severity = Severity.ERROR, + implementation = sourceImplementation(), + ) + .setOptions(listOf(DENY_LIST, ALLOW_LIST)) + .setEnabledByDefault(true) + } + } diff --git a/hedvig-lint/src/test/kotlin/com/hedvig/android/lint/NamespaceImportDetectorTest.kt b/hedvig-lint/src/test/kotlin/com/hedvig/android/lint/NamespaceImportDetectorTest.kt new file mode 100644 index 0000000000..2e586d1b98 --- /dev/null +++ b/hedvig-lint/src/test/kotlin/com/hedvig/android/lint/NamespaceImportDetectorTest.kt @@ -0,0 +1,198 @@ +package com.hedvig.android.lint + +import com.android.tools.lint.checks.infrastructure.LintDetectorTest +import com.android.tools.lint.detector.api.Detector +import com.android.tools.lint.detector.api.Issue +import org.junit.Test + +class NamespaceImportDetectorTest : LintDetectorTest() { + override fun getDetector(): Detector = NamespaceImportDetector() + + override fun getIssues(): List = listOf(NamespaceImportDetector.ISSUE) + + private val resources = kotlin( + """ + package com.example.res + object Res { + object string { + const val GREETING = "hi" + } + object drawable + } + """, + ).indented() + + private val designSystem = kotlin( + """ + package com.example.ds + object TooltipDefaults { + val defaultStyle: Int = 0 + } + """, + ).indented() + + private val uiState = kotlin( + """ + package com.example.ui + sealed interface HomeUiState { + object Success : HomeUiState + object Loading : HomeUiState + } + """, + ).indented() + + private val duration = kotlin( + """ + package com.example.time + class Duration { + companion object { + val seconds: Int = 1 + } + } + """, + ).indented() + + // Kotlin/Native interop packages are capitalized, which a purely textual check misreads as a class. + private val capitalizedPackage = kotlin( + """ + package platform.Foundation + fun systemLocale(): String = "" + """, + ).indented() + + @Test + fun testReportsLowercaseMemberImport() { + lint() + .files( + resources, + kotlin( + """ + package com.example.app + import com.example.res.Res.string + fun greet() = string.GREETING + """, + ).indented(), + ) + .issues(NamespaceImportDetector.ISSUE) + .run() + .expectErrorCount(1) + .expectContains("Import Res and write Res.string at the use site") + } + + @Test + fun testReportsEveryOffendingImportInAFile() { + lint() + .files( + resources, + designSystem, + kotlin( + """ + package com.example.app + import com.example.ds.TooltipDefaults.defaultStyle + import com.example.res.Res.drawable + import com.example.res.Res.string + fun use() = listOf(string, drawable, defaultStyle) + """, + ).indented(), + ) + .issues(NamespaceImportDetector.ISSUE) + .run() + .expectErrorCount(3) + } + + @Test + fun testAllowsSealedSubclassImport() { + lint() + .files( + uiState, + kotlin( + """ + package com.example.app + import com.example.ui.HomeUiState + import com.example.ui.HomeUiState.Loading + import com.example.ui.HomeUiState.Success + fun describe(state: HomeUiState) = when (state) { + Success -> "ok" + Loading -> "wait" + } + """, + ).indented(), + ) + .issues(NamespaceImportDetector.ISSUE) + .run() + .expectClean() + } + + @Test + fun testAllowsCompanionExtensionImport() { + lint() + .files( + duration, + kotlin( + """ + package com.example.app + import com.example.time.Duration + import com.example.time.Duration.Companion.seconds + fun timeout() = Duration.seconds + """, + ).indented(), + ) + .issues(NamespaceImportDetector.ISSUE) + .run() + .expectClean() + } + + @Test + fun testIgnoresCapitalizedPackage() { + lint() + .files( + capitalizedPackage, + kotlin( + """ + package com.example.app + import platform.Foundation.systemLocale + fun locale() = systemLocale() + """, + ).indented(), + ) + .issues(NamespaceImportDetector.ISSUE) + .run() + .expectClean() + } + + @Test + fun testAllowsAliasedImport() { + lint() + .files( + resources, + kotlin( + """ + package com.example.app + import com.example.res.Res.string as StringResources + fun greet() = StringResources.GREETING + """, + ).indented(), + ) + .issues(NamespaceImportDetector.ISSUE) + .run() + .expectClean() + } + + @Test + fun testIgnoresWildcardImport() { + lint() + .files( + resources, + kotlin( + """ + package com.example.app + import com.example.res.* + fun greet() = Res.string.GREETING + """, + ).indented(), + ) + .issues(NamespaceImportDetector.ISSUE) + .run() + .expectClean() + } +} From 45a061099b7a5d13f71a26e10fc1a58b2e8caf4c Mon Sep 17 00:00:00 2001 From: stylianosgakis Date: Thu, 27 Aug 2026 16:50:59 +0200 Subject: [PATCH 3/3] chore: qualify imports that hid their receiver Fixes every existing violation of the NamespaceImport rule: 24 imports across 11 files. Res.string.FOO and Clock.System.now() are restored at their use sites in the three feature files that had shortened them away. The other 19 are design system Defaults members whose owning object lives in the same file, so they are now qualified as TooltipDefaults.defaultStyle and the like, matching what TopAppBar.kt already did. References from inside an owning object's own body are untouched, since they resolve without an import and gain nothing from the prefix. TopAppBar.kt's import turned out to be unused except for one call in TopAppBarLayoutForActions, which has no windowInsets parameter of its own and was silently reading the import. --- .../design/system/hedvig/ClickableList.kt | 3 +- .../android/design/system/hedvig/Dialog.kt | 5 +- .../design/system/hedvig/HedvigBigCard.kt | 15 ++-- .../design/system/hedvig/Notification.kt | 20 +++--- .../android/design/system/hedvig/Tooltip.kt | 14 ++-- .../android/design/system/hedvig/TopAppBar.kt | 3 +- .../system/hedvig/freetext/FreeTextOverlay.kt | 3 +- .../hedvig/freetext/FreeTextTriggerDisplay.kt | 12 ++-- .../details/ui/SubmittedAndClosedColumns.kt | 7 +- .../feature/home/home/ui/HomeDestination.kt | 70 +++++++++---------- .../ui/payments/PaymentsDestination.kt | 42 +++++------ 11 files changed, 87 insertions(+), 107 deletions(-) diff --git a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/ClickableList.kt b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/ClickableList.kt index 3a7b62da7a..7b20638907 100644 --- a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/ClickableList.kt +++ b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/ClickableList.kt @@ -18,7 +18,6 @@ import androidx.compose.ui.graphics.RectangleShape import androidx.compose.ui.graphics.Shape import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp -import com.hedvig.android.design.system.hedvig.ClickableListDefaults.iconSize import com.hedvig.android.design.system.hedvig.icon.ChevronRight import com.hedvig.android.design.system.hedvig.icon.HedvigIcons import com.hedvig.android.design.system.hedvig.tokens.ColorSchemeKeyTokens @@ -96,7 +95,7 @@ private fun ClickableListItem( horizontalArrangement = Arrangement.End, verticalAlignment = Alignment.CenterVertically, ) { - Icon(HedvigIcons.ChevronRight, "", Modifier.size(iconSize)) + Icon(HedvigIcons.ChevronRight, "", Modifier.size(ClickableListDefaults.iconSize)) } }, spaceBetween = 4.dp, diff --git a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Dialog.kt b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Dialog.kt index 080797e28b..6d226b271b 100644 --- a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Dialog.kt +++ b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Dialog.kt @@ -40,7 +40,6 @@ import com.hedvig.android.design.system.hedvig.DialogDefaults.ButtonSize.SMALL import com.hedvig.android.design.system.hedvig.DialogDefaults.DialogStyle import com.hedvig.android.design.system.hedvig.DialogDefaults.DialogStyle.Buttons import com.hedvig.android.design.system.hedvig.DialogDefaults.DialogStyle.NoButtons -import com.hedvig.android.design.system.hedvig.DialogDefaults.defaultButtonSize import com.hedvig.android.design.system.hedvig.EmptyStateDefaults.EmptyStateButtonStyle import com.hedvig.android.design.system.hedvig.EmptyStateDefaults.EmptyStateIconStyle.ERROR import com.hedvig.android.design.system.hedvig.tokens.DialogTokens @@ -86,7 +85,7 @@ fun HedvigAlertDialog( modifier: Modifier = Modifier, confirmButtonLabel: String = stringResource(Res.string.GENERAL_YES), dismissButtonLabel: String = stringResource(Res.string.GENERAL_NO), - buttonSize: DialogDefaults.ButtonSize = defaultButtonSize, + buttonSize: DialogDefaults.ButtonSize = DialogDefaults.defaultButtonSize, ) { HedvigAlertDialog( title = AnnotatedString(title), @@ -109,7 +108,7 @@ fun HedvigAlertDialog( modifier: Modifier = Modifier, confirmButtonLabel: String = stringResource(Res.string.GENERAL_YES), dismissButtonLabel: String = stringResource(Res.string.GENERAL_NO), - buttonSize: DialogDefaults.ButtonSize = defaultButtonSize, + buttonSize: DialogDefaults.ButtonSize = DialogDefaults.defaultButtonSize, ) { HedvigDialog( style = Buttons( diff --git a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/HedvigBigCard.kt b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/HedvigBigCard.kt index 02fc97e4ec..2e4a52c097 100644 --- a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/HedvigBigCard.kt +++ b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/HedvigBigCard.kt @@ -15,9 +15,6 @@ import androidx.compose.ui.graphics.Shape import androidx.compose.ui.text.TextStyle import androidx.compose.ui.unit.dp import com.hedvig.android.compose.ui.LayoutWithoutPlacement -import com.hedvig.android.design.system.hedvig.BigCardDefaults.inputTextStyle -import com.hedvig.android.design.system.hedvig.BigCardDefaults.labelTextStyle -import com.hedvig.android.design.system.hedvig.BigCardDefaults.padding import com.hedvig.android.design.system.hedvig.tokens.ColorSchemeKeyTokens import com.hedvig.android.design.system.hedvig.tokens.TypographyKeyTokens @@ -57,7 +54,7 @@ fun HedvigBigCard( inputText: String?, modifier: Modifier = Modifier, enabled: Boolean = true, - textStyle: TextStyle = inputTextStyle, + textStyle: TextStyle = BigCardDefaults.inputTextStyle, ) { Surface( shape = HedvigTheme.shapes.cornerLarge, @@ -72,14 +69,14 @@ fun HedvigBigCard( LayoutWithoutPlacement( sizeAdjustingContent = { // Always take up the space that the two texts would take - Column(Modifier.padding(padding)) { - HedvigText(text = labelText, style = labelTextStyle) + Column(Modifier.padding(BigCardDefaults.padding)) { + HedvigText(text = labelText, style = BigCardDefaults.labelTextStyle) HedvigText(text = "H", style = textStyle) } }, ) { if (inputText == null) { - Box(Modifier.padding(padding)) { + Box(Modifier.padding(BigCardDefaults.padding)) { HedvigText( text = labelText, style = textStyle, @@ -88,10 +85,10 @@ fun HedvigBigCard( ) } } else { - Column(Modifier.padding(padding)) { + Column(Modifier.padding(BigCardDefaults.padding)) { HedvigText( text = labelText, - style = labelTextStyle, + style = BigCardDefaults.labelTextStyle, color = bigCardColors.labelTextColor(enabled), ) HedvigText( diff --git a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Notification.kt b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Notification.kt index 511ea7f4d8..a05e5a0e8c 100644 --- a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Notification.kt +++ b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Notification.kt @@ -43,10 +43,6 @@ import com.hedvig.android.design.system.hedvig.NotificationDefaults.Notification import com.hedvig.android.design.system.hedvig.NotificationDefaults.NotificationPriority.Info import com.hedvig.android.design.system.hedvig.NotificationDefaults.NotificationPriority.InfoInline import com.hedvig.android.design.system.hedvig.NotificationDefaults.NotificationPriority.NeutralToast -import com.hedvig.android.design.system.hedvig.NotificationDefaults.defaultStyle -import com.hedvig.android.design.system.hedvig.NotificationDefaults.paddingNoIcon -import com.hedvig.android.design.system.hedvig.NotificationDefaults.paddingWithIcon -import com.hedvig.android.design.system.hedvig.NotificationDefaults.textStyle import com.hedvig.android.design.system.hedvig.icon.Campaign import com.hedvig.android.design.system.hedvig.icon.HedvigIcons import com.hedvig.android.design.system.hedvig.icon.InfoFilled @@ -82,7 +78,7 @@ fun HedvigNotificationCard( priority: NotificationPriority, modifier: Modifier = Modifier, withIcon: Boolean = NotificationDefaults.withIconDefault, - style: InfoCardStyle = defaultStyle, + style: InfoCardStyle = NotificationDefaults.defaultStyle, buttonLoading: Boolean = false, minLines: Int = 1, ) { @@ -104,10 +100,10 @@ fun HedvigNotificationCard( priority: NotificationPriority, modifier: Modifier = Modifier, withIcon: Boolean = NotificationDefaults.withIconDefault, - style: InfoCardStyle = defaultStyle, + style: InfoCardStyle = NotificationDefaults.defaultStyle, buttonLoading: Boolean = false, ) { - val padding = if (withIcon) paddingWithIcon else paddingNoIcon + val padding = if (withIcon) NotificationDefaults.paddingWithIcon else NotificationDefaults.paddingNoIcon val description = when (priority) { Attention, NotificationPriority.AttentionRound, Error, Info -> stringResource(Res.string.TALKBACK_NOTIFICATION_CARD) Campaign, InfoInline, NeutralToast, FancyInfo -> "" @@ -125,7 +121,7 @@ fun HedvigNotificationCard( border = if (priority !is FancyInfo) priority.colors.borderColor else null, ) { val buttonDarkTheme = if (priority is InfoInline) isSystemInDarkTheme() else false - ProvideTextStyle(textStyle) { + ProvideTextStyle(NotificationDefaults.textStyle) { Row(Modifier.padding(padding)) { if (withIcon) { LayoutWithoutPlacement( @@ -156,7 +152,7 @@ fun HedvigNotificationCard( buttonSize = Small, modifier = Modifier.weight(1f), ) { - HedvigText(style.leftButtonText, style = textStyle) + HedvigText(style.leftButtonText, style = NotificationDefaults.textStyle) } Spacer(Modifier.width(4.dp)) HedvigButton( @@ -166,7 +162,7 @@ fun HedvigNotificationCard( buttonSize = Small, modifier = Modifier.weight(1f), ) { - HedvigText(style.rightButtonText, style = textStyle) + HedvigText(style.rightButtonText, style = NotificationDefaults.textStyle) } } } @@ -184,11 +180,11 @@ fun HedvigNotificationCard( ) { LayoutWithoutPlacement( sizeAdjustingContent = { - HedvigText(style.buttonText, style = textStyle) + HedvigText(style.buttonText, style = NotificationDefaults.textStyle) }, ) { if (!buttonLoading) { - HedvigText(style.buttonText, style = textStyle) + HedvigText(style.buttonText, style = NotificationDefaults.textStyle) } else { Box( modifier = Modifier.fillMaxSize(), diff --git a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Tooltip.kt b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Tooltip.kt index 51f9fe76ae..cfebcca170 100644 --- a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Tooltip.kt +++ b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/Tooltip.kt @@ -49,10 +49,6 @@ import com.hedvig.android.design.system.hedvig.TooltipDefaults.TooltipStyle.Camp import com.hedvig.android.design.system.hedvig.TooltipDefaults.TooltipStyle.Campaign.Brightness.BLEAK import com.hedvig.android.design.system.hedvig.TooltipDefaults.TooltipStyle.Campaign.Brightness.BRIGHT import com.hedvig.android.design.system.hedvig.TooltipDefaults.TooltipStyle.Inbox -import com.hedvig.android.design.system.hedvig.TooltipDefaults.arrowHeightDp -import com.hedvig.android.design.system.hedvig.TooltipDefaults.arrowSpaceFromEdgeWhenOffCenteredDp -import com.hedvig.android.design.system.hedvig.TooltipDefaults.arrowWidthDp -import com.hedvig.android.design.system.hedvig.TooltipDefaults.defaultStyle import com.hedvig.android.design.system.hedvig.tokens.TooltipTokens import kotlin.time.Duration.Companion.seconds import kotlinx.coroutines.delay @@ -63,7 +59,7 @@ fun HedvigTooltip( showTooltip: Boolean, tooltipShown: () -> Unit, modifier: Modifier = Modifier, - tooltipStyle: TooltipStyle = defaultStyle, + tooltipStyle: TooltipStyle = TooltipDefaults.defaultStyle, beakDirection: BeakDirection = BottomCenter, maxWidth: Dp = TooltipDefaults.defaultMaxWidth, ) { @@ -150,9 +146,11 @@ private fun InnerChatTooltip( private fun Shape.withBeak(beakDirection: BeakDirection): Shape { return object : Shape { override fun createOutline(size: Size, layoutDirection: LayoutDirection, density: Density): Outline { - val arrowSpaceFromEdgeWhenOffCentered: Float = with(density) { arrowSpaceFromEdgeWhenOffCenteredDp.toPx() } - val arrowWidth = with(density) { arrowWidthDp.toPx() } - val arrowHeight = with(density) { arrowHeightDp.toPx() } + val arrowSpaceFromEdgeWhenOffCentered: Float = with(density) { + TooltipDefaults.arrowSpaceFromEdgeWhenOffCenteredDp.toPx() + } + val arrowWidth = with(density) { TooltipDefaults.arrowWidthDp.toPx() } + val arrowHeight = with(density) { TooltipDefaults.arrowHeightDp.toPx() } val squircleSize: Size = when (beakDirection) { BottomCenter, BottomStart, BottomEnd, TopCenter, TopStart, TopEnd -> { size.copy(height = size.height - arrowHeight) diff --git a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/TopAppBar.kt b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/TopAppBar.kt index fc624cdb91..e02e662b31 100644 --- a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/TopAppBar.kt +++ b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/TopAppBar.kt @@ -30,7 +30,6 @@ import androidx.compose.ui.text.style.TextOverflow import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.dropUnlessResumed -import com.hedvig.android.design.system.hedvig.TopAppBarDefaults.windowInsets import com.hedvig.android.design.system.hedvig.icon.ArrowLeft import com.hedvig.android.design.system.hedvig.icon.Close import com.hedvig.android.design.system.hedvig.icon.HedvigIcons @@ -183,7 +182,7 @@ fun TopAppBarLayoutForActions( horizontalArrangement = Arrangement.spacedBy(8.dp, Alignment.End), verticalAlignment = Alignment.CenterVertically, modifier = modifier - .windowInsetsPadding(windowInsets) + .windowInsetsPadding(TopAppBarDefaults.windowInsets) .height(TopAppBarTokens.ContainerHeight) .fillMaxWidth() .padding(contentPadding), diff --git a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/freetext/FreeTextOverlay.kt b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/freetext/FreeTextOverlay.kt index 8aca058ddc..a1fa4bec38 100644 --- a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/freetext/FreeTextOverlay.kt +++ b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/freetext/FreeTextOverlay.kt @@ -56,7 +56,6 @@ import com.hedvig.android.design.system.hedvig.HedvigText import com.hedvig.android.design.system.hedvig.HedvigTheme import com.hedvig.android.design.system.hedvig.HorizontalDivider import com.hedvig.android.design.system.hedvig.Surface -import com.hedvig.android.design.system.hedvig.freetext.FreeTextDefaults.counterPadding import com.hedvig.android.design.system.hedvig.fromToken import com.hedvig.android.design.system.hedvig.internal.Decoration import com.hedvig.android.design.system.hedvig.tokens.ColorSchemeKeyTokens.BackgroundBlack @@ -241,7 +240,7 @@ private fun FreeTextOverlayContent( color = freeTextColors.labelColor, modifier = Modifier .fillMaxWidth() - .padding(counterPadding) + .padding(FreeTextDefaults.counterPadding) .wrapContentWidth(Alignment.End) .semantics { contentDescription = characterLimitDescription diff --git a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/freetext/FreeTextTriggerDisplay.kt b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/freetext/FreeTextTriggerDisplay.kt index dd2ad8a6bb..67b179696f 100644 --- a/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/freetext/FreeTextTriggerDisplay.kt +++ b/app/design-system/design-system-hedvig/src/commonMain/kotlin/com/hedvig/android/design/system/hedvig/freetext/FreeTextTriggerDisplay.kt @@ -33,10 +33,6 @@ import com.hedvig.android.design.system.hedvig.freetext.FreeTextDisplayDefaults. import com.hedvig.android.design.system.hedvig.freetext.FreeTextDisplayDefaults.Height.Unlimited import com.hedvig.android.design.system.hedvig.freetext.FreeTextDisplayDefaults.Style import com.hedvig.android.design.system.hedvig.freetext.FreeTextDisplayDefaults.Style.Labeled -import com.hedvig.android.design.system.hedvig.freetext.FreeTextDisplayDefaults.contentPadding -import com.hedvig.android.design.system.hedvig.freetext.FreeTextDisplayDefaults.defaultHeight -import com.hedvig.android.design.system.hedvig.freetext.FreeTextDisplayDefaults.defaultStyle -import com.hedvig.android.design.system.hedvig.freetext.FreeTextDisplayDefaults.supportingTextPadding import com.hedvig.android.design.system.hedvig.fromToken import com.hedvig.android.design.system.hedvig.icon.HedvigIcons import com.hedvig.android.design.system.hedvig.icon.WarningFilled @@ -64,8 +60,8 @@ fun FreeTextDisplay( freeTextPlaceholder: String, modifier: Modifier = Modifier, maxLength: Int = FreeTextDisplayDefaults.maxLength, - height: Height = defaultHeight, - style: Style = defaultStyle, + height: Height = FreeTextDisplayDefaults.defaultHeight, + style: Style = FreeTextDisplayDefaults.defaultStyle, hasError: Boolean = false, supportingText: String? = null, showCount: Boolean = true, @@ -87,7 +83,7 @@ fun FreeTextDisplay( color = freeTextColors.displayContainerColor, ) { Column( - Modifier.padding(contentPadding), + Modifier.padding(FreeTextDisplayDefaults.contentPadding), ) { if (style is Labeled && freeTextValue != null) { Row(Modifier.fillMaxWidth()) { @@ -147,7 +143,7 @@ fun FreeTextDisplay( text = supportingText, color = displayColors.supportingTextColor, style = FreeTextDisplayDefaults.countLabelStyle.value, - modifier = Modifier.padding(supportingTextPadding), + modifier = Modifier.padding(FreeTextDisplayDefaults.supportingTextPadding), ) } } diff --git a/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/SubmittedAndClosedColumns.kt b/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/SubmittedAndClosedColumns.kt index 4f1ba9dc96..ee84d2e8e4 100644 --- a/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/SubmittedAndClosedColumns.kt +++ b/app/feature/feature-claim-details/src/main/kotlin/com/hedvig/android/feature/claim/details/ui/SubmittedAndClosedColumns.kt @@ -21,7 +21,6 @@ import hedvig.resources.claim_status_detail_closed import hedvig.resources.claim_status_detail_submitted import java.util.Locale import kotlin.time.Clock -import kotlin.time.Clock.System import kotlin.time.Duration import kotlin.time.Duration.Companion.days import kotlin.time.Duration.Companion.seconds @@ -77,7 +76,7 @@ private fun SubmittedAndClosedColumn(topText: String, bottomText: String, modifi } @Composable -private fun currentTimeAsState(updateInterval: Duration = 1.seconds, clock: Clock = System): State { +private fun currentTimeAsState(updateInterval: Duration = 1.seconds, clock: Clock = Clock.System): State { return produceState(initialValue = clock.now()) { while (isActive) { delay(updateInterval) @@ -123,8 +122,8 @@ private fun PreviewSubmittedAndClosedInformation() { HedvigTheme { Surface(color = HedvigTheme.colorScheme.backgroundPrimary) { SubmittedAndClosedColumns( - submittedAt = System.now().minus(10.days), - closedAt = System.now().minus(30.seconds), + submittedAt = Clock.System.now().minus(10.days), + closedAt = Clock.System.now().minus(30.seconds), locale = Locale.ENGLISH, ) } diff --git a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomeDestination.kt b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomeDestination.kt index 5f337228cc..98a9fe96f8 100644 --- a/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomeDestination.kt +++ b/app/feature/feature-home/src/main/kotlin/com/hedvig/android/feature/home/home/ui/HomeDestination.kt @@ -225,8 +225,7 @@ import hedvig.resources.RESUME_CLAIM_DELETE_BUTTON import hedvig.resources.RESUME_CLAIM_DELETE_TITLE import hedvig.resources.RESUME_CLAIM_EXPIRED_BODY import hedvig.resources.RESUME_CLAIM_EXPIRED_TITLE -import hedvig.resources.Res.drawable -import hedvig.resources.Res.string +import hedvig.resources.Res import hedvig.resources.TOAST_NEW_OFFER import hedvig.resources.blur_background import hedvig.resources.general_cancel_button @@ -237,7 +236,6 @@ import hedvig.resources.home_tab_welcome_title_without_name import hedvig.resources.ongoing_shop_session_dismiss_offer import kotlin.math.roundToInt import kotlin.time.Clock -import kotlin.time.Clock.System import kotlin.time.Duration.Companion.milliseconds import kotlin.time.ExperimentalTime import kotlin.time.Instant @@ -388,8 +386,8 @@ private fun HomeScreen( // The draft is expired, so acknowledging the notice (Close button, scrim, or back) removes it. // Matches the Ready-for-dev design: single Close, closing removes the draft claim card. ErrorDialog( - title = stringResource(string.RESUME_CLAIM_EXPIRED_TITLE), - message = stringResource(string.RESUME_CLAIM_EXPIRED_BODY), + title = stringResource(Res.string.RESUME_CLAIM_EXPIRED_TITLE), + message = stringResource(Res.string.RESUME_CLAIM_EXPIRED_BODY), onDismiss = { showDraftExpiredDialog = false draftClaim?.let { deleteDraftClaim(it.id) } @@ -399,10 +397,10 @@ private fun HomeScreen( val draftIdToDelete = draftIdPendingDeleteConfirmation if (draftIdToDelete != null) { HedvigAlertDialog( - title = stringResource(string.RESUME_CLAIM_DELETE_TITLE), - text = stringResource(string.RESUME_CLAIM_DELETE_BODY), - confirmButtonLabel = stringResource(string.RESUME_CLAIM_DELETE_BUTTON), - dismissButtonLabel = stringResource(string.general_cancel_button), + title = stringResource(Res.string.RESUME_CLAIM_DELETE_TITLE), + text = stringResource(Res.string.RESUME_CLAIM_DELETE_BODY), + confirmButtonLabel = stringResource(Res.string.RESUME_CLAIM_DELETE_BUTTON), + dismissButtonLabel = stringResource(Res.string.general_cancel_button), onDismissRequest = { draftIdPendingDeleteConfirmation = null }, onConfirmClick = { draftIdPendingDeleteConfirmation = null @@ -457,7 +455,7 @@ private fun HomeScreen( }, onContinueDraftClaim = { if (draftClaim != null) { - if (draftClaim.isExpired(System.now())) { + if (draftClaim.isExpired(Clock.System.now())) { showDraftExpiredDialog = true } else { navigateToClaimChat(true) @@ -558,7 +556,7 @@ private fun HomeScreenTopBar( } if (shouldShowNewMessageTooltip) { HedvigTooltip( - message = stringResource(string.CHAT_NEW_MESSAGE), + message = stringResource(Res.string.CHAT_NEW_MESSAGE), showTooltip = shouldShowNewMessageTooltip, tooltipStyle = Inbox, beakDirection = TopEnd, @@ -587,7 +585,7 @@ private fun ColumnScope.CrossSellsTooltip(uiState: Success, setEpochDayWhenLastT var shouldSetEpochDayWhenLastToolTipShown by remember { mutableStateOf(false) } LaunchedEffect(shouldSetEpochDayWhenLastToolTipShown) { if (shouldSetEpochDayWhenLastToolTipShown) { - val today = System.now().toLocalDateTime( + val today = Clock.System.now().toLocalDateTime( TimeZone.currentSystemDefault(), ).date.toEpochDays() delay(5000.milliseconds) @@ -596,7 +594,7 @@ private fun ColumnScope.CrossSellsTooltip(uiState: Success, setEpochDayWhenLastT } if (shouldShowCrossSellsTooltip) { HedvigTooltip( - message = stringResource(string.TOAST_NEW_OFFER), + message = stringResource(Res.string.TOAST_NEW_OFFER), showTooltip = true, tooltipStyle = Campaign( subMessage = null, @@ -683,7 +681,7 @@ private fun HomeScreenSuccess( // to "hide" it (the content cards already do; so do the pinned pills). if (HedvigTheme.colorScheme.isLight) { Image( - painter = painterResource(drawable.blur_background), + painter = painterResource(Res.drawable.blur_background), contentDescription = null, contentScale = ContentScale.Crop, modifier = Modifier.matchParentSize(), @@ -1212,7 +1210,7 @@ private fun MemberRemindersSection( .padding(horizontalInsets), ) { HedvigText( - text = stringResource(string.HOME_TODO_SECTION_TITLE), + text = stringResource(Res.string.HOME_TODO_SECTION_TITLE), style = HedvigTheme.typography.headlineSmall, modifier = Modifier.semantics { heading() }, ) @@ -1244,7 +1242,7 @@ private fun QuotesSection( val contentPadding = PaddingValues(horizontal = 16.dp) + horizontalInsets Column(Modifier.fillMaxWidth()) { HedvigText( - text = stringResource(string.HOME_QUOTES_SECTION_TITLE), + text = stringResource(Res.string.HOME_QUOTES_SECTION_TITLE), style = HedvigTheme.typography.headlineSmall, modifier = Modifier .padding(contentPadding) @@ -1301,7 +1299,7 @@ private fun QuoteCard( HedvigText(text = session.title, style = HedvigTheme.typography.bodySmall) val secondary = session.monthlyNet?.let { stringResource( - string.OFFER_COST_AND_PREMIUM_PERIOD_ABBREVIATION, + Res.string.OFFER_COST_AND_PREMIUM_PERIOD_ABBREVIATION, it, ) } ?: session.subtitle @@ -1323,13 +1321,13 @@ private fun QuoteCard( ) { Icon( imageVector = HedvigIcons.Close, - contentDescription = stringResource(string.ongoing_shop_session_dismiss_offer), + contentDescription = stringResource(Res.string.ongoing_shop_session_dismiss_offer), ) } } Spacer(Modifier.height(12.dp)) HedvigButton( - text = stringResource(string.general_continue_button), + text = stringResource(Res.string.general_continue_button), onClick = { onResumeClick(session.resumeUrl) }, buttonStyle = Secondary, buttonSize = ButtonSize.Medium, @@ -1357,7 +1355,7 @@ private fun QuickActionTilesSection( .padding(horizontalInsets), ) { HedvigText( - text = stringResource(string.HC_QUICK_ACTIONS_TITLE), + text = stringResource(Res.string.HC_QUICK_ACTIONS_TITLE), style = HedvigTheme.typography.headlineSmall, modifier = Modifier.semantics { heading() }, ) @@ -1485,21 +1483,21 @@ private fun MainActionCarouselSection( .padding(horizontalInsets), ) { HedvigButton( - text = stringResource(string.home_tab_claim_button_text), + text = stringResource(Res.string.home_tab_claim_button_text), onClick = onMakeClaim, enabled = true, buttonStyle = RoundedPrimary, ) if (isHelpCenterEnabled) { HedvigButton( - text = stringResource(string.home_tab_get_help), + text = stringResource(Res.string.home_tab_get_help), onClick = onHelpAndSupport, enabled = true, buttonStyle = RoundedLiquidGlass, ) } HedvigButton( - text = stringResource(string.DASHBOARD_OPEN_CHAT), + text = stringResource(Res.string.DASHBOARD_OPEN_CHAT), onClick = onContactUs, enabled = true, buttonStyle = RoundedLiquidGlass, @@ -1522,7 +1520,7 @@ private fun AddonsSection( .padding(horizontalInsets), ) { HedvigText( - text = stringResource(string.INSURANCE_ADDONS_SUBHEADING), + text = stringResource(Res.string.INSURANCE_ADDONS_SUBHEADING), style = HedvigTheme.typography.headlineSmall, modifier = Modifier.semantics { heading() }, ) @@ -1532,7 +1530,7 @@ private fun AddonsSection( subtitle = addon.description, pillowImage = null, pillow = { AddonPillow(addon.flowType) }, - buttonText = stringResource(string.HOME_ADDONS_READ_MORE_BUTTON), + buttonText = stringResource(Res.string.HOME_ADDONS_READ_MORE_BUTTON), onButtonClick = { navigateToAddonPurchaseFlow(addon.eligibleInsurancesIds) }, imageLoader = imageLoader, modifier = Modifier.fillMaxWidth(), @@ -1550,13 +1548,13 @@ private fun DiscoverInsurancesSection( imageLoader: ImageLoader, ) { CrossSellsSection( - title = stringResource(string.HOME_DISCOVER_SECTION_TITLE), + title = stringResource(Res.string.HOME_DISCOVER_SECTION_TITLE), crossSells = crossSells, onCrossSellClick = onCrossSellClick, modifier = Modifier.padding(horizontal = 16.dp), onSheetDismissed = {}, imageLoader = imageLoader, - buttonText = stringResource(string.HOME_DISCOVER_SEE_PRICE_BUTTON), + buttonText = stringResource(Res.string.HOME_DISCOVER_SEE_PRICE_BUTTON), buttonSize = ButtonSize.Small, buttonShape = HedvigTheme.shapes.cornerFull, ) @@ -1573,7 +1571,7 @@ private fun WelcomeMessage(firstName: String, modifier: Modifier = Modifier) { ) if (firstName.isBlank()) { HedvigText( - text = stringResource(string.home_tab_welcome_title_without_name), + text = stringResource(Res.string.home_tab_welcome_title_without_name), style = titleStyle, modifier = modifier.fillMaxWidth(), ) @@ -1584,12 +1582,12 @@ private fun WelcomeMessage(firstName: String, modifier: Modifier = Modifier) { modifier = modifier.fillMaxWidth(), ) { HedvigText( - text = stringResource(string.HOME_GREETING_TITLE, firstName), + text = stringResource(Res.string.HOME_GREETING_TITLE, firstName), style = titleStyle, modifier = Modifier.fillMaxWidth(), ) HedvigText( - text = stringResource(string.HOME_GREETING_SUBTITLE), + text = stringResource(Res.string.HOME_GREETING_SUBTITLE), color = HedvigTheme.colorScheme.textSecondary, style = titleStyle, modifier = Modifier.fillMaxWidth(), @@ -1879,19 +1877,19 @@ private fun PreviewHomeScreenAllHomeTextTypes( private val previewQuickActions: List = listOf( MultiSelectExpandedLink( - titleRes = string.HC_QUICK_ACTIONS_EDIT_INSURANCE_TITLE, - hintTextRes = string.HC_QUICK_ACTIONS_EDIT_INSURANCE_SUBTITLE, + titleRes = Res.string.HC_QUICK_ACTIONS_EDIT_INSURANCE_TITLE, + hintTextRes = Res.string.HC_QUICK_ACTIONS_EDIT_INSURANCE_SUBTITLE, links = listOf( StandaloneQuickLink( - titleRes = string.HC_QUICK_ACTIONS_UPGRADE_COVERAGE_TITLE, - hintTextRes = string.HC_QUICK_ACTIONS_UPGRADE_COVERAGE_SUBTITLE, + titleRes = Res.string.HC_QUICK_ACTIONS_UPGRADE_COVERAGE_TITLE, + hintTextRes = Res.string.HC_QUICK_ACTIONS_UPGRADE_COVERAGE_SUBTITLE, quickLinkDestination = QuickLinkChangeTier, ), ), ), StandaloneQuickLink( - titleRes = string.HC_QUICK_ACTIONS_CHANGE_ADDRESS_TITLE, - hintTextRes = string.HC_QUICK_ACTIONS_CHANGE_ADDRESS_SUBTITLE, + titleRes = Res.string.HC_QUICK_ACTIONS_CHANGE_ADDRESS_TITLE, + hintTextRes = Res.string.HC_QUICK_ACTIONS_CHANGE_ADDRESS_SUBTITLE, quickLinkDestination = QuickLinkChangeAddress, ), ) diff --git a/app/feature/feature-payments/src/main/kotlin/com/hedvig/android/feature/payments/ui/payments/PaymentsDestination.kt b/app/feature/feature-payments/src/main/kotlin/com/hedvig/android/feature/payments/ui/payments/PaymentsDestination.kt index 5d674040e5..f2c7a75f37 100644 --- a/app/feature/feature-payments/src/main/kotlin/com/hedvig/android/feature/payments/ui/payments/PaymentsDestination.kt +++ b/app/feature/feature-payments/src/main/kotlin/com/hedvig/android/feature/payments/ui/payments/PaymentsDestination.kt @@ -117,7 +117,7 @@ import hedvig.resources.Res import hedvig.resources.TAB_PAYMENTS_TITLE import hedvig.resources.info_card_missing_payment_body import hedvig.resources.info_card_missing_payment_missing_payments_body -import kotlin.time.Clock.System +import kotlin.time.Clock import kotlin.time.Duration.Companion.days import kotlinx.datetime.LocalDate import kotlinx.datetime.TimeZone @@ -822,7 +822,7 @@ private class PaymentsStatePreviewProvider : CollectionPreviewParameterProvider< isRetrying = false, upcomingPayment = UpcomingPayment.Content( UiMoney(100.0, SEK), - System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, "rdg", ), upcomingPaymentInfo = NoInfo, @@ -837,7 +837,7 @@ private class PaymentsStatePreviewProvider : CollectionPreviewParameterProvider< isRetrying = false, upcomingPayment = UpcomingPayment.Content( UiMoney(100.0, SEK), - System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, "rdg", ), upcomingPaymentInfo = NoInfo, @@ -854,7 +854,7 @@ private class PaymentsStatePreviewProvider : CollectionPreviewParameterProvider< isRetrying = false, upcomingPayment = UpcomingPayment.Content( UiMoney(100.0, SEK), - System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, "iky", ), upcomingPaymentInfo = InProgress, @@ -869,12 +869,12 @@ private class PaymentsStatePreviewProvider : CollectionPreviewParameterProvider< isRetrying = false, upcomingPayment = UpcomingPayment.Content( UiMoney(400.0, SEK), - System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, "pwe", ), upcomingPaymentInfo = PaymentFailed( - System.now().toLocalDateTime(TimeZone.UTC).date, - System.now().minus(30.days).toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().minus(30.days).toLocalDateTime(TimeZone.UTC).date, isManualChargeAllowed = ManualChargeToPrompt( UiMoney(200.0, UiCurrencyCode.SEK), ), @@ -890,7 +890,7 @@ private class PaymentsStatePreviewProvider : CollectionPreviewParameterProvider< isRetrying = false, upcomingPayment = UpcomingPayment.Content( UiMoney(100.0, SEK), - System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, "fkjse", ), upcomingPaymentInfo = NoInfo, @@ -905,12 +905,12 @@ private class PaymentsStatePreviewProvider : CollectionPreviewParameterProvider< isRetrying = false, upcomingPayment = UpcomingPayment.Content( UiMoney(100.0, SEK), - System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, "qrdfgeth", ), upcomingPaymentInfo = PaymentFailed( - System.now().toLocalDateTime(TimeZone.UTC).date, - System.now().minus(30.days).toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().minus(30.days).toLocalDateTime(TimeZone.UTC).date, isManualChargeAllowed = null, ), ongoingCharges = emptyList(), @@ -926,7 +926,7 @@ private class PaymentsStatePreviewProvider : CollectionPreviewParameterProvider< isRetrying = false, upcomingPayment = UpcomingPayment.Content( UiMoney(100.0, SEK), - System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, "qrdfgeth2", ), upcomingPaymentInfo = NoInfo, @@ -943,17 +943,17 @@ private class PaymentsStatePreviewProvider : CollectionPreviewParameterProvider< isRetrying = false, upcomingPayment = UpcomingPayment.Content( UiMoney(100.0, SEK), - System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, "w345423t6", ), upcomingPaymentInfo = PaymentFailed( - System.now().toLocalDateTime(TimeZone.UTC).date, - System.now().minus(30.days).toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().minus(30.days).toLocalDateTime(TimeZone.UTC).date, isManualChargeAllowed = null, ), ongoingCharges = emptyList(), connectedPaymentInfo = ConnectedPaymentInfo.NeedsPayinSetup( - dueDateToConnect = System.now().plus(30.days).toLocalDateTime(TimeZone.UTC).date, + dueDateToConnect = Clock.System.now().plus(30.days).toLocalDateTime(TimeZone.UTC).date, ), showPayoutButton = false, memberType = MemberType.STANDARD_MEMBER, @@ -964,17 +964,17 @@ private class PaymentsStatePreviewProvider : CollectionPreviewParameterProvider< isRetrying = false, upcomingPayment = UpcomingPayment.Content( UiMoney(100.0, SEK), - System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, "42345", ), upcomingPaymentInfo = PaymentFailed( - System.now().toLocalDateTime(TimeZone.UTC).date, - System.now().minus(30.days).toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().minus(30.days).toLocalDateTime(TimeZone.UTC).date, isManualChargeAllowed = null, ), ongoingCharges = emptyList(), connectedPaymentInfo = ConnectedPaymentInfo.NeedsPayinSetup( - System.now().plus(30.days).toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().plus(30.days).toLocalDateTime(TimeZone.UTC).date, ), showPayoutButton = false, memberType = MemberType.STANDARD_MEMBER, @@ -1029,7 +1029,7 @@ private class PaymentsStatePreviewProvider : CollectionPreviewParameterProvider< isRetrying = false, upcomingPayment = UpcomingPayment.Content( UiMoney(100.0, SEK), - System.now().toLocalDateTime(TimeZone.UTC).date, + Clock.System.now().toLocalDateTime(TimeZone.UTC).date, "w345423t6", ), upcomingPaymentInfo = UpcomingPaymentInfo.NoInfo,