Commit Graph

4 Commits

Author SHA1 Message Date
Tristan Katana
9c199a6dcd feat(mobile): Add biometric lock for app resume (#1474)
* Feature: Biometric lock for app resume

User enables "Biometric Lock" in Settings → prompted to verify fingerprint/face first.
User backgrounds the app → _isLocked = true.
User returns → lock screen appears, auto-triggers biometric prompt.
Success → app unlocks, state preserved underneath.
Can retry or log out as fallback.
Add USE_BIOMETRIC permission to AndroidManifest.

* Fix: Remove duplicate local_auth entry in pubspec.lock and add NSFaceIDUsageDescription to iOS Info.plist

* fix(mobile) : Remove duplicate local auth files first

* fix(mobile): keep MainNavigationScreen in the Stack, let the lock screen float above, no unmounting

* Updtae: Swap out Flutter Activity for FlutterFragmentActivity that extends the lock scan feature

* fix(mobile): address biometric lock PR review feedback

* fix(mobile): only require biometric auth when enabling lock, not disabling

Prevents users from getting locked out if biometrics start failing —
they can now disable the lock without needing to pass biometric auth.

* fix(mobile): add missing closing brace in setBiometricEnabled

---------

Signed-off-by: Tristan Katana <50181095+felixmuinde@users.noreply.github.com>
2026-04-15 19:48:13 +02:00
Lazy Bone
fdc2ce1feb Add category support to transactions (#1251)
* Move debug logs button from Home to Settings page, remove refresh/logout from Home AppBar

- Remove Debug Logs, Refresh, and Sign Out buttons from DashboardScreen AppBar
- Add Debug Logs ListTile entry in SettingsScreen under app info section
- Remove unused _handleLogout method from DashboardScreen
- Remove unused log_viewer_screen.dart import from DashboardScreen

https://claude.ai/code/session_017XQZdaEwUuRS75tJMcHzB9

* Add category picker to Android transaction form

Implements category selection when creating transactions in the mobile app.
Uses the existing /api/v1/categories endpoint to fetch categories and sends
category_id when creating transactions via the API.

New files:
- Category model, CategoriesService, CategoriesProvider
Updated:
- Transaction/OfflineTransaction models with categoryId/categoryName
- TransactionsService/Provider to pass category_id
- DB schema v2 migration for category columns
- TransactionFormScreen with category dropdown in "More" section

Closes #78

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Fix ambiguous Category import in CategoriesProvider

Hide Flutter's built-in Category annotation from foundation.dart
to resolve name collision with our Category model.

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Add category filter on Dashboard, clear categories on data reset, fix ambiguous imports

- Add CategoryFilter widget (horizontal chip row like CurrencyFilter)
- Show category filter on Dashboard below currency filter (2nd row)
- Add "Show Category Filter" toggle in Settings > Display section
- Clear CategoriesProvider on "Clear Local Data" and "Reset Account"
- Fix Category name collision: hide Flutter's Category from material.dart
- Add getShowCategoryFilter/setShowCategoryFilter to PreferencesService

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Fix Category name collision using prefixed imports

Use 'import as models' instead of 'hide Category' to avoid
undefined_hidden_name warnings with flutter/material.dart.

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Fix duplicate column error in SQLite migration

Check if category_id/category_name columns exist before running
ALTER TABLE, preventing crashes when the DB was already at v2
or the migration had partially succeeded.

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Move CategoryFilter from dashboard to transaction list screen

CategoryFilter was filtering accounts on the dashboard but accounts
are already grouped by type. Moved it to TransactionsListScreen where
it filters transactions by category, which is the correct placement.

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Add category tag badge next to transaction name

Shows an oval-bordered category label after each transaction's
name for quick visual identification of transaction types.

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Address review findings for category feature

1. Category.fromJson now recursively parses parent chain;
   displayName walks all ancestors (e.g. "Grandparent > Parent > Child")
2. CategoriesProvider.fetchCategories guards against concurrent/duplicate
   calls by checking _isLoading and _hasFetched early
3. CategoryFilter chips use displayName to distinguish subcategories
4. Transaction badge resolves full displayName from CategoriesProvider
   with overflow ellipsis for long paths
5. Offline storage preserves local category values when server response
   omits them (coalesce with ??)

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Fix missing closing brace in PreferencesService causing theme_provider analyze errors

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

* Fix sync category upload, empty-state refresh, badge reactivity, and preferences syntax

- Add categoryId to SyncService pending transaction upload payload
- Replace non-scrollable Center with ListView for empty filter state so
  RefreshIndicator works when no transactions match
- Use listen:true for CategoriesProvider in badge display so badges
  rebuild when categories finish loading
- Fix missing closing brace in PreferencesService.setShowCategoryFilter

https://claude.ai/code/session_01Dgj8tYrCkoUaLW2WrQ3vMJ

---------

Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
2026-04-13 20:01:08 +02:00
Tristan Katana
b1fd8bbc99 Mobile: Add theme selection (light/dark/system) to settings (#1213)
* Feature: Add Theme selection in Settings page

* Fix: Theme provider exception handling.

* feat(mobile): Show theme selection option in settings screen.

* BuildID version 9

---------

Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
2026-03-26 22:47:31 +01:00
Lazy Bone
81cf473862 fix: Use getValidAccessToken() in connectivity banner sync button (#851)
* feat(mobile): Add transaction display on calendar date tap

Implement two-tap interaction for calendar dates:
- First tap selects a date (highlighted with thicker primary color border)
- Second tap on same date shows AlertDialog with transactions for that day

Each transaction displays with:
- Color-coded icon (red minus for expenses, green plus for income)
- Transaction name as title
- Notes as subtitle (if present)
- Amount with color matching expense/income

Selection is cleared when changing account, account type, or month.

https://claude.ai/code/session_019m7ZrCakU6h9xLwD1NTx9i

* feat(mobile): optimize asset/liability display with filters

- Add NetWorthCard widget with placeholder for future net worth API
- Add side-by-side Assets/Liabilities display with tap-to-filter
- Implement CurrencyFilter widget for multi-select currency filtering
- Replace old _SummaryCard with new unified design
- Remove _CollapsibleSectionHeader in favor of filter-based navigation

The net worth section shows a placeholder as the API endpoint is not yet available.
Users can now filter accounts by type (assets/liabilities) and by currency.

https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3

* fix(mobile): remove unused variables and add const

- Remove unused _totalAssets, _totalLiabilities, _getPrimaryCurrency
- Add const to Text('All') widget

https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3

* feat(mobile): enhance dashboard with icons, long-press breakdown, and grouped view

- NetWorthCard: replace text labels with trending icons, add colored
  bottom borders for asset (green) and liability (red) sections
- Add long-press gesture on asset/liability areas to show full currency
  breakdown in a bottom sheet popup
- Add collapsible account type grouping (Crypto, Bank, Investment, etc.)
  with type-specific icons and expand/collapse headers
- Add PreferencesService for persisting display settings
- Add "Group by Account Type" toggle in Settings screen
- Wire settings change to dashboard via GlobalKey for live updates

https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3

* refactor(mobile): remove welcome header from dashboard

Strip the Welcome greeting and subtitle to let the financial
overview take immediate focus.

https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3

* feat(mobile): compact filter buttons with scroll-wheel currency switcher

- Remove trending icons from asset/liability filter buttons
- Increase amount font size to titleMedium bold
- Reduce Net Worth section and filter button padding
- Show single currency at a time with ListWheelScrollView for
  scrolling between currencies (wheel-picker style)
- Absorb scroll events via NotificationListener to prevent
  triggering pull-to-refresh
- Keep icons in the long-press currency breakdown popup

https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3

* feat: Add API key login option to mobile app

Add a "Via API Key Login" button on the login screen that opens a
dialog for entering an API key. The API key is validated by making a
test request to /api/v1/accounts with the X-Api-Key header, and on
success is persisted in secure storage. All HTTP services now use a
centralized ApiConfig.getAuthHeaders() helper that returns the correct
auth header (X-Api-Key or Bearer) based on the current auth mode.

https://claude.ai/code/session_01DnyCzdMjVpSsbBZK3XbzUH

* fix: Improve API key dialog context handling and controller disposal

- Use outer context for SnackBar so it displays on the main screen
  instead of behind the dialog
- Explicitly dispose TextEditingController to prevent memory leaks
- Close dialog on failure before showing error SnackBar for better UX
- Avoid StatefulBuilder context parameter shadowing

https://claude.ai/code/session_01DnyCzdMjVpSsbBZK3XbzUH

* fix: Use user-friendly error message in API key login catch block

Log the technical exception details via LogService.instance.error and
show a generic "Unable to connect" message to the user instead of
exposing the raw exception string.

https://claude.ai/code/session_01DnyCzdMjVpSsbBZK3XbzUH

* fix: Use getValidAccessToken() in connectivity banner sync button

Replace direct authProvider.tokens?.accessToken access with
getValidAccessToken() so the Sync Now button works in API-key
auth mode where _tokens is null.

https://claude.ai/code/session_01DnyCzdMjVpSsbBZK3XbzUH

* Revert "fix: Use getValidAccessToken() in connectivity banner sync button"

This reverts commit 7015c160f0.

* Reapply "fix: Use getValidAccessToken() in connectivity banner sync button"

This reverts commit b29e010de3.

* fix: Use getValidAccessToken() in connectivity banner sync button

Replace direct authProvider.tokens?.accessToken access with
getValidAccessToken() so the Sync Now button works in API-key
auth mode where _tokens is null.

https://claude.ai/code/session_01DnyCzdMjVpSsbBZK3XbzUH

* fix(mobile): prevent bottom sheet overflow with ConstrainedBox

Use ConstrainedBox + ListView.separated with shrinkWrap for the
currency breakdown popup. Few currencies: sheet sizes to content.
Many currencies: caps at 50% screen height and scrolls.

Also add isScrollControlled and useSafeArea to showModalBottomSheet.

https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3

* fix: Prevent multiple syncs and handle auth errors in connectivity banner

Set _isSyncing immediately on tap to disable the button during token
refresh, wrap getValidAccessToken() in try/catch with user-facing error
snackbar, and await _handleSync so errors propagate correctly.

https://claude.ai/code/session_01GgVgjqwyXhWMZN3eWfaMCk

---------

Signed-off-by: Lazy Bone <89256478+dwvwdv@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-02-01 23:16:02 +01:00