mohd-faraz

_blogs

// blogs / 20260910.md

Dev Log: September 10 Wrap-up

2026-09-10
#android#kotlin#sqlite#ui-ux

Overview

Today was one of those days that started with a quick bug fix and spiraled into a much-needed UI overhaul. Most of my time was spent inside the ExpenseTracker logic, specifically cleaning up how I handle uncategorized transactions and making the category detail views way more flexible with date filtering.

What I Worked On

Hunting down ghost transactions

I noticed a frustrating little bug where transactions that were supposed to be dismissed (or 'greyed out') were still showing up in the uncategorized list. It felt like playing whack-a-mole; I’d dismiss a notification, only for the entry to resurface in another part of the app.

The fix was simple but required tightening up the SQL logic in the DAO. I had to ensure that if a transaction is marked as hidden or acknowledged, it stays that way across all queries. I updated the bulk-dismiss logic to explicitly mark transactions as 'grey' so they don't leak into the active uncategorized bucket.

Making category views respect time

Up until today, the category detail screen was a bit of a data dump—it just showed every transaction for that category ever recorded. That’s not super helpful when the main dashboard is filtered by month.

I had to write a new query to scope these results to a specific timestamp range. Now, when you click into a category, it actually respects the timeframe you’re looking at. To get this working, I had to update the repository and the ViewModel to combine the selected category ID with the current month state. It feels a lot more cohesive now.

Building the 'Filter Everything' UI

While working on the category scope, I realized: why limit it to just the current month? Sometimes you want to see your spending for the whole year or a specific trip. I ended up building a new DateRangeFilterChips component. It handles:

  • Month/Year modes with quick navigation arrows.
  • Custom Range using a date picker.
  • All Time for the big picture.

I had to be careful to keep this filter state separate from the main dashboard so that flipping through months in a category view doesn't mess up your home screen view. Here is a simplified look at how I'm handling that date range query now:

// Simplified query for fetching scoped data
@Query("""
    SELECT * FROM records 
    WHERE category_id = :id 
    AND timestamp >= :start 
    AND timestamp <= :end 
    AND deleted_at IS NULL 
    ORDER BY timestamp DESC
""")
fun get_records_in_range(id: Long, start: Long, end: Long): Flow<List<Record>>

Wrapping Up

I finished the day by adding some unit tests for the new filtering logic. It took four version bumps (1.5.4.1 to 1.5.4.4) to get everything through my local pipeline smoothly, but the app feels much more robust tonight. Tomorrow, I might look into some UI polish for the date range picker—it works, but it could look a little sharper.