Main moved ahead with the home-polish (#29/#32/#33), category HSV color
picker (#30), and category lock-icon fix (#31) PRs. The only conflicts
were in ExpenseListScreen.kt:
- Imports: main added AppBar + EmptyStateIllustration. The branch had
already removed AppBar (replaced by SearchToolbar) and replaced the
inline text empty state. Resolution: keep the branch's
AppBarTitle/SearchToolbar/TabText set, drop AppBar (no longer used),
add EmptyStateIllustration.
- ExpensesTabContent empty state: main replaced the Box+Text
'No expenses yet' with EmptyStateIllustration. Resolution: use
EmptyStateIllustration (consistent with main's new design) but keep
the branch's three-way message selection (no results vs no data).
For visual consistency between the two tabs, also swap
RecurringTabContent's empty state to EmptyStateIllustration. No
behavioral change for the recurring case — same per-tab vs no-results
message selection, same strings, just rendered through the shared
component.
All other files (build.gradle.kts, libs.versions.toml, HomeScreen,
SettingsScreen, CategoryScreen, EmptyStateIllustration.kt, strings.xml)
auto-merged cleanly.
Replace the inline OutlinedTextField inside ExpensesTabContent with
the shared SearchToolbar in the topBar. The query is shared across
both tabs; closing the toolbar (X / navigate-up) deactivates search
and clears the filter.
In ExpenseListScreenModel:
- searchQuery becomes StateFlow<String?> (null = inactive, "" = active
empty, "foo" = active query)
- setSearchQuery now accepts String? to match SearchToolbar's
onChangeSearchQuery signature
- expenses and recurring combine on
_searchQuery.debounce(SEARCH_DEBOUNCE_MILLIS).distinctUntilChanged()
so fast typing does not re-filter on every keystroke
- recurring is now filtered by query against category name and
recurring note (case-insensitive substring)
In ExpenseListScreen:
- Remove the inline search field, the date-range-filter search hint
label, and the now-unused OutlinedTextField / Icons.Outlined.Search
imports
- Both ExpensesTabContent and RecurringTabContent now take a nullable
searchQuery and show a generic 'No results' message when the active
filter empties the list, or the per-tab empty copy otherwise
- Add the expense_list_no_results string
Replace the plain Text inside PrimaryTabRow's Tab with the shared
TabText composable. Pass the current size of the expenses and
recurring state flows as badgeCount so each tab shows a small pill
with the (post-filter) list size. Counts update reactively as
items are added, deleted, or filtered by search/date.
Add ExpandedFabScrim composable that renders a Material 3 scrim
overlay fading in/out in sync with the mini-FABs. Tapping the scrim
dismisses the FAB.
Move the ExpandedFab out of Scaffold's floatingActionButton slot and
into the body inside a Box, so the scrim can match the body size via
matchParentSize() and stack above the list but below the FAB. Add a
BackHandler that dismisses the FAB on system back while it is open.