Skip to content

Previews to components and screens#7

Merged
rafaelfelipeac merged 21 commits intomainfrom
add-previews
Aug 2, 2025
Merged

Previews to components and screens#7
rafaelfelipeac merged 21 commits intomainfrom
add-previews

Conversation

@rafaelfelipeac
Copy link
Owner

@rafaelfelipeac rafaelfelipeac commented Aug 2, 2025

Summary by CodeRabbit

  • New Features

    • Added comprehensive UI previews for various components and screens in both light and dark themes, enabling easier visual inspection and development.
    • Introduced static preview data for replies and activity logs to support UI previews.
  • Refactor

    • Split several screen composables (e.g., Settings, Activity Log) into root/state and UI-only components for improved modularity and testability.
    • Updated function signatures to provide default parameter values and improve usage flexibility.
    • Updated navigation host to use new root composables for Settings and Activity Log screens.
  • Style

    • Enhanced visual consistency by adding explicit background and text colors to multiple UI components, ensuring better theming support.
  • Chores

    • Removed obsolete preview files and reorganized preview-related code for maintainability.

google-labs-jules bot and others added 19 commits July 29, 2025 14:19
This commit adds previews to all composables and screens in the project. This will make it easier to develop and test the UI components in isolation.

I have also removed the default empty lambda parameters from the composables as requested.
This commit moves all the previews from `commonMain` to `androidMain` to avoid issues with the build. It also removes the `@Preview` annotations from the composables in `commonMain`.
This commit moves all the previews from `commonMain` to `androidMain` to avoid issues with the build. It also removes the `@Preview` annotations from the composables in `commonMain`.

This also adds dark and light theme previews to all components and screens.
@coderabbitai
Copy link

coderabbitai bot commented Aug 2, 2025

Walkthrough

This change removes a legacy preview file and introduces a comprehensive, modularized preview infrastructure for Compose UI components and screens in the Android app. It creates dedicated preview files for each UI element, provides fake data and string providers, and implements light/dark theme wrappers. Several UI components are also updated for improved styling and composability. Key screen composables are refactored to separate state management from UI rendering.

Changes

Cohort / File(s) Change Summary
Legacy Preview Removal
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/Previews.kt
Removed the old, monolithic Compose preview file for ReplyListScreen.
Preview Infrastructure & Data
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/ReplyRadarPreviewWrapper.kt,
.../shared/Shared.kt,
.../shared/fakes/FakeNotificationPermissionManager.kt,
.../shared/fakes/PreviewStringsFake.kt
Added a theme-aware preview wrapper, static preview data (sample replies, user actions, app version), and fake implementations for notification permission management and string resources.
Component Previews
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/*
Added dedicated preview files for each Compose UI component (e.g., buttons, dialogs, lists, tabs, placeholders, error UIs, snackbars, etc.), each supporting light and dark themes, and using the new preview infrastructure.
Screen Previews
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/screens/ActivityLogScreenPreview.kt,
.../previews/screens/ReplyListScreenPreview.kt,
.../previews/screens/SettingsScreenPreview.kt
Added preview files for main screens (Activity Log, Reply List, Settings), covering various data states and both light/dark themes.
UI Styling Improvements
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyRadarError.kt,
.../ReplyRadarPlaceholder.kt,
.../ReplyReminder.kt,
.../ReplyTab.kt,
.../features/reply/presentation/replylist/components/ReplyList.kt,
.../ReplyTimestampInfo.kt,
.../TopBar.kt,
.../replybottomsheet/ReplyBottomSheetActions.kt
Updated UI components to explicitly set background and text colors according to the current theme, added default parameter values, and improved composability.
Component API Improvements
.../features/reply/presentation/replylist/components/FloatingActionButton.kt,
.../core/common/ui/components/ReplyTab.kt
Made certain parameters optional (e.g., default lambdas, default modifiers) to simplify usage.
Screen Refactoring: Activity Log & Settings
.../features/activitylog/presentation/ActivityLogScreen.kt,
.../features/settings/presentation/SettingsScreen.kt,
.../core/navigation/AppNavHost.kt
Split screen composables into "Root" (stateful) and "UI" (stateless) variants, decoupling state management from UI rendering. Updated navigation to use new root components.
ReplyListScreen Pager Fix
.../features/reply/presentation/replylist/ReplyListScreen.kt
Explicitly sets the initial page of the pager to the selected tab index from state.

Sequence Diagram(s)

Preview Wrapper and Component Preview Interaction

sequenceDiagram
    participant PreviewFunction as PreviewFunction
    participant ReplyRadarPreviewWrapper
    participant FakeProviders as FakeProviders/Theme
    participant UIComponent as UIComponent

    PreviewFunction->>ReplyRadarPreviewWrapper: Call with darkTheme param & content lambda
    ReplyRadarPreviewWrapper->>FakeProviders: Provide fake strings, notification manager
    ReplyRadarPreviewWrapper->>FakeProviders: Set MaterialTheme (light/dark)
    ReplyRadarPreviewWrapper->>UIComponent: Render content lambda (component preview)
Loading

Refactored Screen Composable Structure

sequenceDiagram
    participant ScreenRoot as ScreenRoot (e.g., SettingsScreenRoot)
    participant ViewModel
    participant ScreenUI as Stateless UI Composable

    ScreenRoot->>ViewModel: Collect state
    ScreenRoot->>ScreenUI: Pass state, event handlers, appVersion
    ScreenUI->>ScreenUI: Render UI based on state
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇
In the garden of Compose, I hop with delight,
New previews bloom in day and night.
Fake strings and data, a theme-wrapped view,
Light and dark, I show them all to you.
Old previews gone, new roots take hold—
A rabbit’s work, neat and bold!
🌱✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f8dd9b4 and 48a3e90.

📒 Files selected for processing (4)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyRadarPlaceholderPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyReminderPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTabPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/screens/ReplyListScreenPreview.kt (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTabPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyReminderPreview.kt
🚧 Files skipped from review as they are similar to previous changes (2)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyRadarPlaceholderPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/screens/ReplyListScreenPreview.kt
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build, Tests and Lint
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch add-previews

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Nitpick comments (25)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyReminder.kt (2)

115-120: Background is applied after padding – swap modifier order

Modifier.padding().background() draws the background inside the padded area, leaving the top-padding region transparent.
If the intent is a full-width surface stripe (incl. padding), call .background() first, then .padding().

-    Row(
-        modifier = Modifier
-            .fillMaxWidth()
-            .padding(top = paddingSmall)
-            .background(colorScheme.surface),
+    Row(
+        modifier = Modifier
+            .fillMaxWidth()
+            .background(colorScheme.surface)
+            .padding(top = paddingSmall),

171-174: Same padding/background ordering issue in ReminderText row

For consistency with the fix above, invert the order here as well so the surface colour covers the whole width.

-            modifier = Modifier
-                .fillMaxWidth()
-                .background(colorScheme.surface),
+            modifier = Modifier
+                .fillMaxWidth()
+                .background(colorScheme.surface),

(also add padding if required).

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/Shared.kt (1)

121-206: Capture now once to keep relative timestamps stable

Each System.currentTimeMillis() call is evaluated separately, so the deltas between items are slightly off.
For deterministic previews (and easier snapshot tests) capture the current time once:

-val previewActivityLogItems = listOf(
+private val now = System.currentTimeMillis()
+val previewActivityLogItems = listOf(
@@
-        createdAt = System.currentTimeMillis() - 1_000_000L
+        createdAt = now - 1_000_000L
@@
-        createdAt = System.currentTimeMillis() - 2_000_000L
+        createdAt = now - 2_000_000L
# …repeat for the remaining entries…
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/TopBar.kt (1)

50-53: Use onSurface instead of onBackground for content on a surface

Box is now painted with colorScheme.surface, so the title text should use onSurface for guaranteed contrast.

-            color = colorScheme.onBackground
+            color = colorScheme.onSurface
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyRoundedCornerPreview.kt (2)

14-15: Enable background for clearer previews

Without showBackground = true, the shape is rendered over the transparent IDE canvas. Adding it improves readability and catches unexpected clipping issues early.

-@Preview
+@Preview(showBackground = true)

20-27: Add clip to make shape effective for children

Modifier.background(shape = …) only paints the background; it does not clip nested content. In real usage you normally want both paint + clip to avoid rectangular hit-areas.

-        Box(
-            modifier = Modifier
-                .size(100.dp)
-                .background(
-                    color = colorScheme.primary,
-                    shape = ReplyRoundedCorner()
-                )
-        )
+        Box(
+            modifier = Modifier
+                .size(100.dp)
+                .clip(ReplyRoundedCorner())          // ✅ clip first
+                .background(
+                    color = colorScheme.primary,
+                    shape = ReplyRoundedCorner()
+                )
+        )

Apply the same change in the dark-theme preview below for consistency.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyButtonPreview.kt (1)

25-30: Remove redundant modifier = Modifier argument

ReplyButton already defaults modifier to Modifier; passing it explicitly adds noise.

-            ReplyButton(
-                modifier = Modifier,
-                text = "Button",
-                onClick = {}
-            )
+            ReplyButton(
+                text = "Button",
+                onClick = {}
+            )

Apply the same micro-cleanup in the dark preview for parity.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyNotificationPermissionDialogPreview.kt (1)

8-19: Show dialog background for visual accuracy

Dialogs often rely on the scrim for context; enabling showBackground makes the preview closer to runtime appearance.

-@Preview
+@Preview(showBackground = true)

Do the same for the dark-theme preview below.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTogglePreview.kt (1)

14-31: Use name/uiMode parameters to make previews distinguishable in the IDE.

Both previews are rendered with showBackground = true, but without a name or uiMode they appear in the preview pane with identical labels and default (light-theme) metadata. Consider:

@Preview(
    name = "ReplyToggle – Light",
    showBackground = true,
)

and for dark:

@Preview(
    name = "ReplyToggle – Dark",
    uiMode = UI_MODE_NIGHT_YES,
    showBackground = true,
)

This makes it obvious which variant you are inspecting and avoids manual theme switching.

Also applies to: 33-50

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyProgressPreview.kt (1)

15-30: Minor: give the progress indicator some fixed space to avoid zero-height warnings.

When a Box without explicit size hosts an indeterminate ReplyProgress, the preview engine sometimes logs “layout with infinite constraints” warnings and shows a clipped indicator. A tiny tweak keeps the preview noise-free:

-        Box(
-            modifier = Modifier
-                .background(MaterialTheme.colorScheme.background)
-                .padding(16.dp),
+        Box(
+            modifier = Modifier
+                .size(72.dp)             // any reasonable constant
+                .background(MaterialTheme.colorScheme.background)
+                .padding(16.dp),

Not critical, just keeps the preview canvas predictable.

Also applies to: 32-47

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyListPreview.kt (1)

19-28: Allow the list to occupy full height for a scrollable realistic preview.

ReplyList contains a LazyColumn. Without a size constraint its height becomes unconstrained inside the preview, so only the first few items are laid out and scrolling cannot be tested. Wrapping the Box (or the ReplyList directly) with fillMaxSize() makes the preview closer to runtime behaviour:

-        Box(
-            modifier = Modifier
-                .background(MaterialTheme.colorScheme.background)
-        ) {
+        Box(
+            modifier = Modifier
+                .fillMaxSize()
+                .background(MaterialTheme.colorScheme.background)
+        ) {

Same applies to the dark variant below.

Also applies to: 37-46

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTimestampInfoPreview.kt (1)

20-29: Small duplication: extract a private helper to reduce copy-paste.

Both light and dark previews differ only in the darkTheme flag. Extracting the shared body avoids duplication noise:

@Composable
private fun ReplyTimestampInfoPreviewImpl(darkTheme: Boolean) {
    ReplyRadarPreviewWrapper(darkTheme) {
        Column(Modifier.background(MaterialTheme.colorScheme.surface)) {
            ReplyTimestampInfo(
                state = ReplyBottomSheetState(reply = Replies.OnTheRadar.reply1)
            )
        }
    }
}

@Preview(name = "TimestampInfo – Light", showBackground = true)
@Composable fun ReplyTimestampInfoPreview()  = ReplyTimestampInfoPreviewImpl(false)

@Preview(name = "TimestampInfo – Dark",
         uiMode = UI_MODE_NIGHT_YES, showBackground = true)
@Composable fun ReplyTimestampInfoDarkPreview() = ReplyTimestampInfoPreviewImpl(true)

Not mandatory, but it keeps future tweaks DRY across both variants.

Also applies to: 39-48

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/fakes/PreviewStringsFake.kt (1)

7-127: Consider automating interface-sync to avoid manual drift.

The object hard-codes >120 string properties. Any addition/removal in the Strings interface will silently break the compiler until this file is manually updated, which is easy to overlook.
Generating the fake implementation from the real Strings interface (e.g. KSP / kapt, KotlinPoet, or a simple gradle task) would erase that maintenance burden and guarantee compile-time alignment.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/FloatingActionButtonPreview.kt (1)

23-26: Pass only the necessary parameters in previews.

FloatingActionButton already obtains MaterialTheme.colorScheme internally. Supplying it explicitly adds noise to the preview and can desynchronise if the implementation later derives additional colours from the theme.

-            FloatingActionButton(
-                onIntent = {},
-                colorScheme = MaterialTheme.colorScheme
-            )
+            FloatingActionButton(onIntent = {})
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/screens/SettingsScreenPreview.kt (1)

20-30: Expose variant previews for other locales / loading states.

The Settings screen supports language & loading combinations, yet only the happy-path (English, not loading) is previewed. Adding a second preview with isLoading = true and another with a non-default language would deliver faster visual validation of edge cases.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyConfirmationDialogPreview.kt (1)

17-28: Avoid suppressing the dismiss callback inside confirm.

ReplyConfirmationDialog internally invokes onDismiss after onConfirm. Passing empty lambdas for both in a preview is fine, but make sure future real usages don’t mistakenly double-dismiss or ignore the outer onDismiss. No change required—just flagging the pattern.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyReminderPreview.kt (1)

14-14: Extract duplicate time calculation to reduce code duplication.

Both preview functions calculate the current time identically. Consider extracting this to a shared variable at the file level to follow DRY principles.

+private val previewCurrentTime = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault())
+
 @Preview(showBackground = true)
 @Composable
 fun ReplyReminderPreview() {
-    val now = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault())
-
     ReplyRadarPreviewWrapper(
         darkTheme = false
     ) {
         // ReminderText wasn't showing in Preview because the icon row was collapsing the layout.
         ReplyReminder(
-            selectedTime = now.time,
-            selectedDate = now.date,
+            selectedTime = previewCurrentTime.time,
+            selectedDate = previewCurrentTime.date,

Also applies to: 33-33

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/PlatformDatePickerPreview.kt (1)

17-18: Consider consistency in string resource access.

This preview directly uses PreviewStringsFake properties while other previews access strings through LocalReplyRadarStrings.current provided by ReplyRadarPreviewWrapper. While both approaches work, using the LocalReplyRadarStrings pattern would be more consistent with the rest of the preview infrastructure.

However, since PlatformDatePicker likely requires these strings as direct parameters rather than accessing them internally, the current approach is acceptable and may be necessary.

Also applies to: 33-34

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyRadarErrorPreview.kt (1)

14-80: Good preview coverage with room for minor improvements.

The previews effectively cover the ReplyRadarError component states. Consider these enhancements:

  1. More descriptive function names: Instead of Preview1/Preview2, use names like DefaultErrorPreview/CustomErrorPreview
  2. Extract common Box setup: The repeated Box with surface background could be extracted to reduce duplication

Apply this pattern for more descriptive naming:

-fun ReplyRadarErrorPreview1() {
+fun ReplyRadarErrorDefaultPreview() {
-fun ReplyRadarErrorPreview2() {
+fun ReplyRadarErrorCustomMessagePreview() {
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyBottomSheetContentPreview.kt (1)

11-87: Comprehensive bottom sheet preview coverage!

The previews effectively cover the key interaction modes:

  • CREATE mode for new reply creation
  • EDIT mode with existing reply data
  • Both light and dark theme variants
  • Proper use of shared preview data

Consider more descriptive function names (e.g., CreateModePreview, EditModePreview) to immediately convey the mode being demonstrated.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTextFieldPreview.kt (1)

10-64: Solid text field preview implementation!

The previews provide good coverage of the ReplyTextField states:

  • Empty and populated text scenarios
  • Light and dark theme variants
  • Proper use of shared preview data and fake strings
  • Consistent preview wrapper usage

Like the other preview files, consider more descriptive function names (e.g., PopulatedTextFieldPreview, EmptyTextFieldPreview) for better clarity.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyBottomSheetActionsPreview.kt (2)

53-53: Remove redundant reply = null parameter in EDIT mode previews.

In EDIT mode previews, you're already setting reply = Replies.OnTheRadar.reply1 in the state object, making the separate reply = null parameter redundant and potentially confusing.

-            reply = null,

Also applies to: 102-102


11-108: Consider reducing code duplication with a shared preview helper.

The four preview functions follow an identical structure with only theme and mode variations. Consider extracting a private helper function to reduce duplication.

+@Composable
+private fun ReplyBottomSheetActionsPreviewContent(
+    darkTheme: Boolean,
+    mode: ReplyBottomSheetMode
+) {
+    val reply = if (mode == ReplyBottomSheetMode.EDIT) Replies.OnTheRadar.reply1 else null
+    
+    ReplyRadarPreviewWrapper(darkTheme = darkTheme) {
+        ReplyBottomSheetActions(
+            state = ReplyBottomSheetState(
+                replyBottomSheetMode = mode,
+                reply = reply
+            ),
+            onArchive = {},
+            onResolve = {},
+            onDelete = {},
+            onSave = {},
+            onInvalidReminderValue = {},
+            selectedDate = null,
+            selectedTime = null,
+            name = reply?.name ?: "",
+            subject = reply?.subject ?: ""
+        )
+    }
+}

 @Preview(showBackground = true)
 @Composable
-fun ReplyBottomSheetActionsPreview1() {
-    ReplyRadarPreviewWrapper(
-        darkTheme = false
-    ) {
-        // ... existing content
-    }
-}
+fun ReplyBottomSheetActionsPreview1() = 
+    ReplyBottomSheetActionsPreviewContent(false, ReplyBottomSheetMode.CREATE)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyOutlinedButtonPreview.kt (1)

21-175: Consider reducing code duplication with a helper function.

Similar to other preview files, this has repetitive structure that could benefit from a shared helper function.

+@Composable
+private fun ReplyOutlinedButtonStatePreview(
+    darkTheme: Boolean,
+    primaryButton: Pair<String, DrawableResource>,
+    secondaryButton: Pair<String, DrawableResource>
+) {
+    ReplyRadarPreviewWrapper(darkTheme = darkTheme) {
+        Row(
+            modifier = Modifier
+                .background(MaterialTheme.colorScheme.surface)
+                .padding(8.dp)
+        ) {
+            ReplyOutlinedButton(
+                text = primaryButton.first,
+                icon = primaryButton.second,
+                onClick = {}
+            )
+            ReplyOutlinedButton(
+                text = secondaryButton.first,
+                icon = secondaryButton.second,
+                onClick = {}
+            )
+        }
+    }
+}
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/screens/ReplyListScreenPreview.kt (1)

11-13: Add descriptive name to @Preview for easier Studio lookup

When many previews share similar signatures, Android Studio lists only the function names. Supplying name = "…", e.g.

-@Preview(showBackground = true)
+@Preview(name = "On-the-Radar • Empty • Light", showBackground = true)

makes the picker far more usable.

Also applies to: 31-33, 51-53, 71-73, 91-93, 111-113, 131-133, 151-153, 171-173, 191-193, 211-213, 231-233

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f2295bb and f8dd9b4.

📒 Files selected for processing (47)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/Previews.kt (0 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ActivityLogListItemPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/FloatingActionButtonPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/PlatformDatePickerPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/PlatformTimePickerPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/RepliesArchivedScreenPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/RepliesOnTheRadarScreenPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/RepliesResolvedScreenPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyBottomSheetActionsPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyBottomSheetContentPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyButtonPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyConfirmationDialogPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyListItemPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyListPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyNotificationPermissionDialogPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyOutlinedButtonPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyProgressPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyRadarErrorPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyRadarPlaceholderPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyReminderPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyRoundedCornerPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplySnackbarPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTabPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTextFieldPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTimestampInfoPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTogglePreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/TopBarPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/screens/ActivityLogScreenPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/screens/ReplyListScreenPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/screens/SettingsScreenPreview.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/ReplyRadarPreviewWrapper.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/Shared.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/fakes/FakeNotificationPermissionManager.kt (1 hunks)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/fakes/PreviewStringsFake.kt (1 hunks)
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyRadarError.kt (1 hunks)
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyRadarPlaceholder.kt (2 hunks)
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyReminder.kt (3 hunks)
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyTab.kt (1 hunks)
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/navigation/AppNavHost.kt (3 hunks)
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/activitylog/presentation/ActivityLogScreen.kt (1 hunks)
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/ReplyListScreen.kt (1 hunks)
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/FloatingActionButton.kt (1 hunks)
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/ReplyList.kt (2 hunks)
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/ReplyTimestampInfo.kt (2 hunks)
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/TopBar.kt (2 hunks)
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/replybottomsheet/ReplyBottomSheetActions.kt (2 hunks)
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/settings/presentation/SettingsScreen.kt (4 hunks)
💤 Files with no reviewable changes (1)
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/Previews.kt
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: rafaelfelipeac
PR: rafaelfelipeac/replyradar#5
File: composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/ReplyListViewModel.kt:0-0
Timestamp: 2025-07-24T22:13:32.263Z
Learning: The user rafaelfelipeac consistently implements robust solutions that go beyond the immediate problem, adding defensive programming measures like the isPendingReplyHandled flag in the ReplyListViewModel to prevent duplicate processing, showing strong attention to edge cases and race conditions.
Learnt from: rafaelfelipeac
PR: rafaelfelipeac/replyradar#5
File: config/detekt/detekt.yml:15-17
Timestamp: 2025-07-24T20:32:51.160Z
Learning: The user rafaelfelipeac prefers to create tech debt tasks to track future cleanup and refactoring work when temporarily relaxing code quality thresholds, showing a proactive approach to technical debt management.
📚 Learning: in replyradar app, reply entities have mutually exclusive states: a reply can only be in one state a...
Learnt from: rafaelfelipeac
PR: rafaelfelipeac/replyradar#5
File: composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/ReplyListViewModel.kt:310-329
Timestamp: 2025-07-24T20:32:50.724Z
Learning: In ReplyRadar app, Reply entities have mutually exclusive states: a reply can only be in one state at a time (pending/resolved/archived). This means replies cannot exist in multiple collections simultaneously, eliminating concerns about race conditions when processing replies across different state-based collections in the ReplyListViewModel.

Applied to files:

  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/TopBar.kt
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyReminder.kt
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/replybottomsheet/ReplyBottomSheetActions.kt
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyRadarError.kt
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/navigation/AppNavHost.kt
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/ReplyListScreen.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/RepliesOnTheRadarScreenPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyButtonPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyRoundedCornerPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTimestampInfoPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/RepliesArchivedScreenPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyConfirmationDialogPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/RepliesResolvedScreenPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplySnackbarPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyReminderPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyRadarPlaceholderPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyListItemPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyProgressPreview.kt
  • composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/ReplyList.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyListPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTogglePreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyBottomSheetActionsPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTextFieldPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyOutlinedButtonPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/Shared.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyRadarErrorPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyBottomSheetContentPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTabPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/screens/ReplyListScreenPreview.kt
📚 Learning: the user rafaelfelipeac consistently implements robust solutions that go beyond the immediate proble...
Learnt from: rafaelfelipeac
PR: rafaelfelipeac/replyradar#5
File: composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/ReplyListViewModel.kt:0-0
Timestamp: 2025-07-24T22:13:32.263Z
Learning: The user rafaelfelipeac consistently implements robust solutions that go beyond the immediate problem, adding defensive programming measures like the isPendingReplyHandled flag in the ReplyListViewModel to prevent duplicate processing, showing strong attention to edge cases and race conditions.

Applied to files:

  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/RepliesResolvedScreenPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyListItemPreview.kt
  • composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/Shared.kt
🧬 Code Graph Analysis (11)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/ReplyRadarPreviewWrapper.kt (1)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/theme/ReplyRadarTheme.kt (1)
  • ReplyRadarTheme (7-20)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/RepliesOnTheRadarScreenPreview.kt (2)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/ReplyRadarPreviewWrapper.kt (1)
  • ReplyRadarPreviewWrapper (11-21)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/RepliesScreen.kt (1)
  • RepliesScreen (18-59)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyConfirmationDialogPreview.kt (3)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/ReplyRadarPreviewWrapper.kt (1)
  • ReplyRadarPreviewWrapper (11-21)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyConfirmationDialog.kt (1)
  • ReplyConfirmationDialog (26-95)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/util/String.kt (1)
  • format (3-11)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplySnackbarPreview.kt (1)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/ReplyRadarPreviewWrapper.kt (1)
  • ReplyRadarPreviewWrapper (11-21)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyReminderPreview.kt (2)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/ReplyRadarPreviewWrapper.kt (1)
  • ReplyRadarPreviewWrapper (11-21)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyReminder.kt (1)
  • ReplyReminder (42-165)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyRadarPlaceholderPreview.kt (2)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/ReplyRadarPreviewWrapper.kt (1)
  • ReplyRadarPreviewWrapper (11-21)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyRadarPlaceholder.kt (1)
  • ReplyRadarPlaceholder (12-22)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyListPreview.kt (2)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/ReplyRadarPreviewWrapper.kt (1)
  • ReplyRadarPreviewWrapper (11-21)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/ReplyList.kt (1)
  • ReplyList (21-63)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTextFieldPreview.kt (2)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/ReplyRadarPreviewWrapper.kt (1)
  • ReplyRadarPreviewWrapper (11-21)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyTextField.kt (1)
  • ReplyTextField (29-75)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ActivityLogListItemPreview.kt (2)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/ReplyRadarPreviewWrapper.kt (1)
  • ReplyRadarPreviewWrapper (11-21)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/activitylog/presentation/ActivityLogScreen.kt (1)
  • ActivityLogListItem (209-258)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyBottomSheetContentPreview.kt (2)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/ReplyRadarPreviewWrapper.kt (1)
  • ReplyRadarPreviewWrapper (11-21)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/replybottomsheet/ReplyBottomSheetContent.kt (1)
  • ReplyBottomSheetContent (31-103)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/settings/presentation/SettingsScreen.kt (3)
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/core/version/Version.android.kt (1)
  • getAppVersion (7-12)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/version/Version.kt (1)
  • getAppVersion (3-3)
composeApp/src/iosMain/kotlin/com/rafaelfelipeac/replyradar/core/version/Version.native.kt (1)
  • getAppVersion (5-8)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Build, Tests and Lint
🔇 Additional comments (35)
composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyReminder.kt (1)

181-183: Typography updated – looks good

Explicitly setting color = colorScheme.onSurface aligns with Material 3 guidance.
No further action needed.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/fakes/FakeNotificationPermissionManager.kt (1)

5-8: Stub implementation is adequate for previews

Returns deterministic truthy result and avoids side-effects – perfect for design-time previews.

composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyRadarPlaceholder.kt (1)

18-20: Explicit colour on placeholder – looks correct

Using colorScheme.onSurface matches the (implicit) surface background in most containers.
No issues here.

composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/ReplyTimestampInfo.kt (1)

5-5: LGTM! Explicit theming improves consistency.

The addition of explicit text color using MaterialTheme.colorScheme.onSurface ensures proper theming in both light and dark modes, which aligns well with the comprehensive preview infrastructure being introduced in this PR.

Also applies to: 27-28

composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/ReplyList.kt (1)

3-3: LGTM! Background theming enhances visual consistency.

Adding the surface background color to reply items provides consistent visual styling across the app and aligns with the Material3 design system.

Also applies to: 37-37

composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/navigation/AppNavHost.kt (1)

16-16: LGTM! Architecture improvement with proper separation of concerns.

The refactoring to use ScreenRoot composables for navigation properly separates state collection from UI rendering, following good architectural practices. This ensures the navigation layer interacts with state-aware components while keeping UI components pure.

Also applies to: 20-20, 55-55, 70-70

composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/replybottomsheet/ReplyBottomSheetActions.kt (1)

3-3: LGTM! Consistent theming implementation.

The background color addition follows the established pattern across the PR, ensuring visual consistency in the bottom sheet actions while maintaining all existing functionality.

Also applies to: 11-11, 59-59

composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/ReplyListScreen.kt (1)

118-119: LGTM! Fixes initial pager state consistency.

Setting initialPage = state.selectedTabIndex ensures the pager starts on the correct tab, preventing potential UI inconsistency where the selected tab and displayed page could be mismatched during initialization.

composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyTab.kt (1)

13-13: LGTM! Excellent improvement for component reusability.

Adding a default Modifier parameter follows Compose best practices and makes the component more convenient to use, especially in preview scenarios where explicit modifiers are often unnecessary.

composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/reply/presentation/replylist/components/FloatingActionButton.kt (1)

14-14: LGTM! Good pattern for preview-friendly components.

Making the onIntent parameter optional with a default empty lambda is an excellent approach that maintains existing functionality while enabling the component to be used in previews without requiring real event handling logic.

composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/core/common/ui/components/ReplyRadarError.kt (2)

13-13: LGTM! Good improvement for component reusability.

Making the errorMessage parameter optional with a sensible default enhances the component's usability, especially in preview scenarios.


15-16: Excellent theming improvements for Material3 consistency.

The explicit background and text color usage ensures proper visual contrast and consistency across light/dark themes. Using MaterialTheme.colorScheme.surface and onSurface follows Material3 design guidelines perfectly.

Also applies to: 20-20

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/ReplyRadarPreviewWrapper.kt (1)

11-21: Excellent shared preview infrastructure design!

This wrapper provides a clean, centralized approach to preview setup that:

  • Eliminates code duplication across preview files
  • Ensures consistent theming and localization context
  • Uses appropriate fake implementations for dependencies
  • Enables easy light/dark theme testing

The implementation follows Compose best practices and aligns well with your preference for robust, comprehensive solutions.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/TopBarPreview.kt (2)

8-19: Well-structured light theme preview.

Clean implementation that leverages the shared preview wrapper and provides appropriate empty handlers for preview scenarios.


21-32: Excellent dual-theme preview approach.

Providing both light and dark theme previews ensures comprehensive visual testing. The consistent structure and naming convention make it easy to understand the purpose of each preview.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/PlatformTimePickerPreview.kt (1)

13-23: Nullability Verified for PlatformTimePicker Parameters
All PlatformTimePicker declarations in commonMain, androidMain, iosMain, and desktopMain define selectedTime: LocalTime? and selectedDate: LocalDate?. Passing null in the previews is correct—no changes required.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/RepliesOnTheRadarScreenPreview.kt (1)

14-26: LGTM – solid state isolation

Preview sets up realistic ReplyListState with sample data and keeps side-effects nil. Good separation of concerns.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/shared/fakes/PreviewStringsFake.kt (1)

55-61: Placeholder count safety.

Several strings contain multiple % placeholders (e.g. %1 at %2). The helper in core.util.format performs sequential replace, so supplying a mismatching arg count will produce a malformed string at runtime.
A defensive assertion (unit-test or require(args.size == expected)) around format would surface issues early, especially because these strings are duplicated here and in production resources.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/FloatingActionButtonPreview.kt (1)

14-29: LGTM – clean, minimal preview implementation.

Nothing blocking; layout and theme wrapper are correctly applied.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/RepliesArchivedScreenPreview.kt (2)

11-39: LGTM – consistent with other tab previews.

The setup matches the OnTheRadar/Resolved previews, ensuring parity across tabs.


16-23: No action needed – ReplyListState provides defaults for all parameters
The ReplyListState primary constructor declares default values for replies, resolvedReplies, archivedReplies, isLoading, and errorMessage, so supplying only isLoading and archivedReplies is valid and will compile.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyConfirmationDialogPreview.kt (1)

11-51: LGTM – previews correctly exercise light & dark variants with formatted strings.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/RepliesResolvedScreenPreview.kt (1)

1-44: LGTM! Well-structured preview implementation.

The preview follows excellent patterns:

  • Consistent use of shared constants (RESOLVED_INDEX) and mock data (Replies.Resolved.replies)
  • Proper theme isolation with light/dark variants
  • Appropriate callback stubbing with empty lambdas for preview isolation
  • Good use of the shared ReplyRadarPreviewWrapper for consistent theming
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyListItemPreview.kt (1)

1-64: LGTM! Comprehensive preview coverage.

Excellent preview implementation with:

  • Good coverage using different sample data (reply1, reply2)
  • Consistent light/dark theme variants
  • Clear function naming convention
  • Proper callback isolation with empty lambdas
  • Consistent use of shared preview infrastructure
composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplySnackbarPreview.kt (2)

17-21: Excellent documentation explaining preview limitations.

The comment clearly explains why the actual ReplySnackbar component can't be used directly in previews due to SnackbarHostState requiring runtime coroutine execution. This kind of documentation is invaluable for future maintainers.


28-40: LGTM! Correct manual simulation approach.

The manual simulation correctly replicates the styling from the actual ReplySnackbar component:

  • Uses matching containerColor and contentColor from the theme
  • Proper Box wrapper with background for visual context
  • Consistent with the component's color scheme usage

Also applies to: 49-61

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/screens/ActivityLogScreenPreview.kt (1)

10-72: Excellent preview coverage and structure!

The preview functions provide comprehensive coverage of the ActivityLogScreen with:

  • Both empty and populated states
  • Light and dark theme variants
  • Consistent use of ReplyRadarPreviewWrapper
  • Clear, descriptive naming conventions
  • Proper state-driven approach enabling isolated UI testing

This aligns well with the refactored ActivityLogScreen separation of concerns.

composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/activitylog/presentation/ActivityLogScreen.kt (1)

86-101: Excellent architectural refactoring!

The separation of ActivityLogScreenRoot (state collection) from ActivityLogScreen (UI rendering) follows clean architecture principles:

  • Enables isolated UI testing and previewing
  • Maintains clear separation of concerns
  • Consistent with the broader refactoring pattern in the codebase
  • Makes the UI composable purely state-driven

This approach facilitates the comprehensive preview coverage demonstrated in the preview files.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ActivityLogListItemPreview.kt (2)

320-338: Excellent use of helper function to reduce duplication.

The PreviewAction helper function effectively eliminates code duplication across the numerous preview variants while maintaining flexibility for different parameters. The use of Clock.System.now() with time offsets is a clever approach to demonstrate varied timestamps in previews.


28-166: Comprehensive coverage of user action scenarios.

The preview functions provide excellent coverage of all UserActionType and UserActionTargetType combinations, with meaningful test data from the shared Replies object. This will be valuable for visual testing and development.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyOutlinedButtonPreview.kt (1)

21-175: Good coverage of button states with appropriate icons and text.

The previews effectively demonstrate the ReplyOutlinedButton component across different reply states (Active/Resolved/Archived) with contextually appropriate icons and text. The Row layout provides good visual context for how buttons appear together.

composeApp/src/commonMain/kotlin/com/rafaelfelipeac/replyradar/features/settings/presentation/SettingsScreen.kt (3)

68-83: Excellent separation of state management from UI rendering.

The split into SettingsScreenRoot and SettingsScreen follows excellent Compose patterns by separating state management concerns from pure UI rendering. This improves testability and reusability of the UI composable.


383-402: Good elimination of side effects in UI composable.

Moving the getAppVersion() call out of the AppVersionFooter composable and passing it as a parameter eliminates side effects and makes the component more testable and predictable.


130-144: Clean parameter passing pattern for intent handling.

The consistent use of onIntent parameter throughout the component hierarchy (Theme, Language, App components) provides a clean and predictable way to handle user interactions without tight coupling to the ViewModel.

composeApp/src/androidMain/kotlin/com/rafaelfelipeac/replyradar/previews/components/ReplyTabPreview.kt (1)

14-45: Good use of TabRow with proper indicator positioning.

The TabRow setup with tabIndicatorOffset and Material3 theming is well-implemented. The OnTheRadar preview correctly shows the first tab as selected, matching selectedTabIndex = 0.

@rafaelfelipeac rafaelfelipeac merged commit 6a6035e into main Aug 2, 2025
2 checks passed
@rafaelfelipeac rafaelfelipeac deleted the add-previews branch August 2, 2025 21:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant