mirror of
https://github.com/we-promise/sure.git
synced 2026-08-05 16:42:18 +00:00
ea0b5fbd293f2e789d1bd480a2f9ecfebb2f2c8a
11 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
401cd6ab08 |
feat(mobile): privacy mode to mask money values (#2386)
* feat(mobile): add privacy mode to mask money values Adds an app-wide "privacy mode" so users can hide monetary amounts from over-the-shoulder view. - PrivacyProvider (ChangeNotifier) backed by PreferencesService, so the choice persists across launches and every money widget rebuilds on toggle. - MoneyMasker.mask() collapses an amount's numeric portion into a short fixed run of bullets while keeping the currency symbol and sign (e.g. CA$1,234.56 -> CA$••••). A fixed run avoids leaking the value's magnitude and reads cleanly without stray separators. Currency- and locale-agnostic — it operates on already-formatted strings. - Masking applied at every money render site: net worth + per-currency totals + breakdown sheet (NetWorthCard), account balances (AccountCard, AccountDetailHeader, transaction form account selector), and transaction amounts (transactions list, recent transactions, calendar). - Two entry points: a "Hide amounts" switch in Settings -> Security, and a quick eye toggle in the top bar (visible on every tab). Tests: MoneyMasker unit tests (fixed-run mask, magnitude hidden, symbol/ sign kept, passthrough, idempotent) + a widget test asserting the net worth masks/unmasks as the provider flips; account_card_test updated to provide the new provider. flutter analyze: no new issues; full suite (123) green. * fix(mobile): address privacy-mode review feedback - Startup masking (Codex P1): read the privacy preference in main() before runApp and seed PrivacyProvider with it, so the first frame already has the correct value — money is never briefly rendered unmasked for a user who enabled "Hide amounts". Provider stays fail-closed otherwise: starts masked, SureApp's no-arg default is masked, and a failed read keeps it masked. A late-completing initial load no longer clobbers an explicit user toggle. - setHidden() reverts the in-memory state (and logs) if persistence fails, keeping the UI consistent with what's actually stored. - Mask the cash-balance detail chip in AccountDetailHeader (was leaking the cash position in privacy mode). - Privacy top-bar toggle gets a "Toggle privacy" tooltip + icon semantic label for accessibility (kept as an InkWell to match the adjacent settings control). - Tests: assert fail-closed initial state; assert the exact masked count; test the persistence round-trip (set -> reload); add PreferencesService.resetForTest() and reset between tests so the cached singleton can't leak state. 125 tests pass; flutter analyze: no new issues. * refactor(mobile): thread hideAmounts through calendar tiles Per review: the calendar tile builders read PrivacyProvider via context.read, relying implicitly on the parent build()'s context.watch to rebuild them — fragile if a tile is later extracted or wrapped in a RepaintBoundary. Pass hideAmounts down explicitly instead, matching the recent_transactions_screen pattern: - build() (context.watch) -> _buildCalendar -> _buildDayCell - _showTransactionsDialog reads once when the modal opens -> _buildTransactionTile No more context.read inside tile methods. 125 tests pass; analyze clean. * fix(mobile): watch PrivacyProvider inside calendar dialog builder Moving the hideAmounts read inside the showDialog builder and switching from context.read to context.watch ensures the dialog re-masks transaction amounts if the user toggles privacy mode while the dialog is open. |
||
|
|
9ea8261919 |
feat(mobile): migrate all hardcoded UI strings to gen_l10n ARB (Phase 1 + 2) (#2384)
* feat(mobile): add Flutter i18n foundation (gen_l10n Phase 1)
- Wire flutter_localizations + gen_l10n (pubspec.yaml + l10n.yaml)
- Bump intl ^0.18.1 → ^0.20.2 for Flutter 3.32 pin
- Add lib/l10n/app_en.arb with 9 seed keys (appTitle, 3 common*, 4 chatSuggestion*)
- Generate AppLocalizations via flutter gen-l10n
- Replace MaterialApp title: with onGenerateTitle + localizationsDelegates + supportedLocales
- Migrate suggested_questions.dart from const list to BuildContext function
- Update chat_conversation_screen.dart call site (one-line change at pre-designed seam)
* feat(mobile): migrate all hardcoded UI strings to gen_l10n ARB (Phase 2)
Extends the i18n foundation from Phase 1 to cover every remaining
hardcoded user-facing string across the mobile app.
Files changed (21 source files + ARB/generated):
- lib/l10n/app_en.arb: 226 keys (+~80 new keys covering all screens)
- lib/screens/dashboard_screen.dart
- lib/screens/calendar_screen.dart
- lib/screens/transactions_list_screen.dart
- lib/screens/backend_config_screen.dart
- lib/screens/recent_transactions_screen.dart
- lib/screens/biometric_lock_screen.dart
- lib/screens/chat_conversation_screen.dart
- lib/screens/chat_list_screen.dart
- lib/screens/log_viewer_screen.dart
- lib/screens/login_screen.dart
- lib/screens/main_navigation_screen.dart
- lib/screens/more_screen.dart
- lib/screens/settings_screen.dart
- lib/screens/sso_onboarding_screen.dart
- lib/screens/transaction_edit_screen.dart
- lib/screens/transaction_form_screen.dart
- lib/widgets/account_detail_header.dart
- lib/widgets/category_filter.dart
- lib/widgets/connectivity_banner.dart
- lib/widgets/currency_filter.dart
- lib/widgets/custom_proxy_headers_editor.dart
Notable patterns:
- ICU plural for connectivity pending-sync count
- Parameterised keys for greeting (firstName), update dialog
(version), cash chip (amount), delete confirmation (name),
show-N menu (count), proxy-headers count, multi-delete count
- AppLocalizations captured before async gaps; dialog builders
re-obtain from their own BuildContext
- const removed only from Text/InputDecoration/SnackBar/Row
widgets that directly reference localisation getters; sibling
const widgets preserved
116/116 unit tests pass; flutter analyze --no-fatal-infos: 0 errors.
* feat(mobile): migrate the remaining secondary UI strings to gen_l10n ARB
Completes the i18n migration by covering the lower-traffic strings the
earlier passes left behind — secondary dialogs, snackbars, settings
rows, validators, helper texts, and tooltips across 11 files.
- settings_screen.dart: reset/delete-account dialogs, clear-data and
proxy-header snackbars, list-tile titles/subtitles, theme-segment
tooltips, biometric prompt reason, debug-logs semantics label
- transaction_form_screen.dart: amount validators, session/success/
failure/generic-error snackbars, More/Less toggle, date/name/category
fields + helper texts, create button
- transaction_edit_screen.dart: session/update snackbars, validators,
category/merchant/tag fallbacks, synced-only notice
- login_screen.dart: API-key dialog, demo/sign-up TextSpan, MFA info +
validator, divider, server-URL heading, API-key + backend tooltip
- chat_list_screen.dart: multi-delete plural, result snackbars, error
heading, relative-time fallback
- chat_conversation_screen.dart: edit-title dialog, refresh tooltip,
load-error heading
- connectivity_banner.dart: sign-in / sync-success / sync-failure /
auth-failure snackbars (also resolves the const removals cleanly)
- main_navigation_screen.dart: enable-AI dialog + failure snackbar
- log_viewer_screen.dart: clear-logs confirmation dialog
- biometric_lock_screen.dart, transactions_list_screen.dart: snackbar
and edit tooltip
Adds 98 ARB keys (now 324 total), reusing common* and existing
screen keys where text matched. Interpolations use String/int
placeholders; multi-delete uses an ICU plural. AppLocalizations is
captured before async gaps and re-obtained inside dialog builders;
const removed only where a localisation getter is introduced, with
const restored on still-const siblings.
116/116 unit tests pass; flutter analyze --no-fatal-infos: 0 errors
(6 pre-existing infos unchanged). No remaining hardcoded user-facing
strings (verified by grep; only a doc-comment example remains).
* fix(mobile): address i18n review feedback and prune dead ARB keys
Resolves the still-valid CodeRabbit/Codex review findings on the i18n
migration; the majority were already handled by earlier commits.
- pubspec: switch intl to `any` so flutter_localizations selects the
SDK-pinned version (0.19.x on <3.32, 0.20.x on 3.32+). Pinning
^0.20.2 conflicted with the declared `flutter: '>=3.27.0'` floor and
would break `flutter pub get` on pre-3.32 SDKs.
- sso_onboarding: localize "Signed in as {email}" / "Google account
verified" / the link- and create-form notes; fix the first/last-name
validators that wrongly returned the "Email is required" message.
- backend_config: localize _testConnection / _saveAndContinue /
_validateUrl messages and the headers helper text (validator now
takes AppLocalizations; async methods capture it before awaits).
- recent_transactions: localize "Unknown Account"; locale-aware
timestamp.
- account_detail_header: localize the unavailable-details message via a
render-time flag (avoids touching inherited widgets in the
initState-driven load path); treat empty/whitespace securityName as
missing for the holding-name fallback.
- dashboard: wrap syncing/refreshing snackbar text in Expanded to avoid
overflow with long translations; use the distinct dashboardSyncError
key on the exception path.
- chat_list: localize relative-time labels (plural keys) and use a
locale-aware fallback date; calendar: locale-aware displayed dates and
weekday letters (map-key formats left fixed; Sunday-anchored grid
preserved).
- connectivity_banner: capture ScaffoldMessenger before the async gap
(removes use_build_context_synchronously); log_viewer: const Duration.
- Prune 55 unused ARB keys (never-wired scaffolding + superseded
duplicates). ARB now 298 keys, 0 unused.
116/116 tests pass; flutter analyze --no-fatal-infos: 0 errors, only 3
pre-existing infos in the untouched intro_screen_web.dart.
* fix(mobile): localize the log viewer empty-state string
The 'No logs yet' empty state was the last hardcoded user-facing string
(the logViewerEmpty key had been pruned before this string was migrated).
Re-add the key and route the empty state through AppLocalizations.
Closes the final CodeRabbit i18n-coverage thread. 0 analyze errors,
116 tests pass, ARB at 299 keys with 0 unused.
* fix(mobile): address i18n review feedback
- sso_onboarding: the "Accept Invitation" tab and submit buttons showed
the Terms-of-Service string (ssoOnboardingAcceptTerms) when a household
invitation was pending. Add ssoOnboardingAcceptInvitation and use it in
both spots; drop the now-unused ToS key (no ToS checkbox exists).
- transaction_form: restore the required-field indicator on the amount
label ("Amount *") that the migration dropped.
- settings: localize the "a newer version" fallback used in the update
dialog when the store version is unknown.
- ARB plurals: use the CLDR `one{}` category instead of the exact-match
`=1{}` so future non-English locales pluralize correctly. English output
is unchanged.
ARB at 300 keys, 0 unused. 116 tests pass; flutter analyze: no new issues.
* fix(mobile): reconcile i18n with design-system primitives after merge
The merge of main into this branch pulled in the design-system primitive
migrations (SureCard/SureChip/SureSegmentedControl/SureTextField/
SureListGroup), which collided with the i18n string migration and left
several files broken (compile errors / un-localized text).
Re-apply the i18n migration on top of the design-system versions:
- more_screen: SureListGroup/SureListRow rows now use l.more* keys
(was a mangled mix of _buildMenuItem + SureListGroup).
- transaction_form_screen: SureSegmentedControl segments + amount/date/
name/category labels, helpers, validators, and snackbars localized;
add transactionFormAmountHelper ("Required") for the amount helper text.
- custom_proxy_headers_editor: SureTextField label/hint params localized.
- currency_filter: the "All" chip is a SureChip again (the merge had left
it as a Material FilterChip) and uses l.commonAll.
- currency_filter_test / custom_proxy_headers_editor_test: add the
localization delegates the widgets now require.
ARB at 301 keys, 0 unused. 165 tests pass; flutter analyze: 0 errors.
---------
Signed-off-by: Juan José Mata <juanjo.mata@gmail.com>
Co-authored-by: Juan José Mata <juanjo.mata@gmail.com>
|
||
|
|
94d5ad2151 |
fix(mobile): neutral Sure tokens for FAB/badge/avatar surfaces + themed logo (#2366)
On screens not yet redesigned with SureColors (the Chats list, etc.), Material's primary/secondary *container* roles were unset, so they fell back to defaults that read as blue on the FAB, unread-badge, and avatar surfaces. - Pin `primaryContainer`/`secondaryContainer` to a neutral Sure surface (`surfaceInset` + `textPrimary`), and add a `FloatingActionButtonThemeData` so FABs use Sure's neutral primary action color (`buttonPrimary`). `primary` / `secondary` stay `link` / `info`, so existing link/accent callers are unchanged. - Add a `SureLogo` widget that renders `logomark.svg` with the wordmark's `currentColor` strokes tinted to the theme's secondary text color, and route every logomark consumer (nav bar, login) through it — so the mark stays legible in dark mode (the hardcoded grey was too dim) and no caller renders the strokes as the flutter_svg default (black). The green brand mark keeps its fill. Refs #2235. |
||
|
|
1995c62ddf | Flutter title and icon alignment fixes | ||
|
|
2dcb4b4f67 | Small Flutter UI tweaks | ||
|
|
eb0d05a7fb | Intro mode in Flutter client fixes | ||
|
|
bf0be85859 |
Expose ui_layout and ai_enabled to mobile clients and add enable_ai endpoint (#983)
* Wire ui layout and AI flags into mobile auth Include ui_layout and ai_enabled in mobile login/signup/SSO payloads, add an authenticated endpoint to enable AI from Flutter, and gate mobile navigation based on intro layout and AI consent flow. * Linter * Ensure write scope on enable_ai * Make sure AI is available before enabling it * Test improvements * PR comment * Fix review issues: test assertion bug, missing coverage, and Dart defaults (#985) - Fix login test to use ai_enabled? (method) instead of ai_enabled (column) to match what mobile_user_payload actually serializes - Add test for enable_ai when ai_available? returns false (403 path) - Default aiEnabled to false when user is null in AuthProvider to avoid showing AI as available before authentication completes - Remove extra blank lines in auth_provider.dart and auth_service.dart https://claude.ai/code/session_01LEYYmtsDBoqizyihFtkye4 Co-authored-by: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
2ac3f3dff0 |
Add account filtering and net worth card to dashboard (#818)
* 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 * 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(mobile): reload dashboard preferences on any tab switch to Home Previously only reloaded when navigating directly from Settings to Home. Now reloads whenever the Home tab is selected, covering paths like Settings -> More -> Home. https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3 * chore(mobile): simplify net worth placeholder to single line Replace the two-line Net Worth / -- placeholder with a compact "Net Worth — coming soon" label while the API endpoint is pending. https://claude.ai/code/session_01W8cQSCzmgTmTqwRJ8Ycpx3 --------- Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
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 |
||
|
|
19da11ed4e |
This commit adds two new features to the More tab in the mobile app: (#612)
Calendar View: Monthly calendar displaying daily balance changes for selected account Account selection dropdown to switch between different accounts Month navigation with previous/next buttons Visual indicators (green for income, red for expenses) Monthly profit/loss summary at the top Auto-calculation of daily transaction totals Recent Transactions: View recent N transactions across all accounts Configurable display limit (10/20/50/100 transactions) Pull-to-refresh functionality Transaction details including account name, date, amount, and notes Visual distinction between income and expenses Sorted by date (most recent first) Implementation details: Created MoreScreen as menu hub for new features Replaced PlaceholderScreen with functional MoreScreen Leverages existing Provider pattern for state management Uses offline-first approach with existing data providers Full Chinese localization Material Design 3 compliant UI Files added: mobile/lib/screens/more_screen.dart mobile/lib/screens/calendar_screen.dart mobile/lib/screens/recent_transactions_screen.dart Files modified: mobile/lib/screens/main_navigation_screen.dart Signed-off-by: Lazy Bone <89256478+dwvwdv@users.noreply.github.com> Co-authored-by: dwvwdv <dwvwdv@protonmail.com> |
||
|
|
f52b3fceb6 |
feat: implement mobile AI chat feature and fix duplicate response issue (#610)
Backend fixes: - Fix duplicate AssistantResponseJob triggering causing duplicate AI responses - UserMessage model already handles job triggering via after_create_commit callback - Remove redundant job enqueue in chats_controller and messages_controller Mobile app features: - Implement complete AI chat interface and conversation management - Add Chat, Message, and ToolCall data models - Add ChatProvider for state management with polling mechanism - Add ChatService to handle all chat-related API requests - Add chat list screen (ChatListScreen) - Add conversation detail screen (ChatConversationScreen) - Refactor navigation structure with bottom navigation bar (MainNavigationScreen) - Add settings screen (SettingsScreen) - Optimize TransactionsProvider to support account filtering Technical details: - Implement message polling mechanism for real-time AI responses - Support chat creation, deletion, retry and other operations - Integrate Material Design 3 design language - Improve user experience and error handling Co-authored-by: dwvwdv <dwvwdv@protonmail.com> |