mirror of
https://github.com/we-promise/sure.git
synced 2026-04-07 22:34:47 +00:00
e573896efe6dee2ee71fa187a869b4e593603565
3 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
e573896efe |
fix: locale-dependent category duplication bug (#956)
* fix: locale-dependent category duplication bug * fix: use family locale for investment contributions category to prevent duplicates and handle legacy data * Remove v* tag trigger from flutter-build to fix double-runs publish.yml already calls flutter-build via workflow_call on v* tags, so the direct push trigger was causing duplicate workflow runs. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Refactor mobile release asset flow * fix: category uniqueness and workflow issues * fix: fix test issue * fix: solve test issue * fix: resolve legacy problem * fix: solve lint test issue * fix: revert unrelated changes --------- Co-authored-by: Juan José Mata <juanjo.mata@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> |
||
|
|
2f4e2eab8d |
Workflow chores: publish Flutter builds & bump alpha versions (#599)
* Add debug mobile artifacts to GitHub releases - Modify flutter-build.yml to trigger on version tags (v*) and support workflow_call for use by other workflows - Add mobile job to publish.yml that calls flutter-build workflow - Add release job that creates GitHub release with debug APK and unsigned iOS build when a version tag is pushed - Auto-detect debug vs release APK and name appropriately - Mark alpha/beta/rc versions as pre-releases * Add automatic alpha version bump after release When an alpha tag (e.g., v0.6.7-alpha.3) is published and the Docker image is built, automatically bump the alpha number in version.rb (e.g., alpha.3 -> alpha.4) and push to main branch. * Fix APK copying to include both debug and release builds Change if/elif to separate if statements so both app-debug.apk and app-release.apk are copied to release assets when both exist. * Rename artifact names in publish workflow Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> * Revert rename of artifact names Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> * Enhance version bump process in publish.yml Refactor version bump script to ensure version file exists and improve error handling. Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> --------- Signed-off-by: Juan José Mata <juanjo.mata@gmail.com> Co-authored-by: Claude <noreply@anthropic.com> |
||
|
|
7866598057 |
Mobile native client via Flutter (#426)
* feat: mobile support. Basic functionality development includes adding and deleting transactions,viewing balances, * Fix mobile support issues in PR #426 This commit addresses the critical issues identified in the mobile-support PR: 1. **GitHub Actions Workflow Path Issues (Critical)** - Add mobile/ prefix to all path filters in flutter-build.yml - Add working-directory to all Flutter commands - Fix Android keystore and iOS CocoaPods paths - Fix artifact upload paths 2. **Error Handling Improvements** - Add try-catch blocks to all HTTP requests in services - Wrap all JSON parsing operations in error handling - Add proper error messages for network failures 3. **HTTP Request Timeout Configuration** - Add 30-second timeout to all HTTP requests - Prevents hanging on network failures 4. **Defensive Null Checks in Providers** - Add containsKey() checks before accessing result maps - Add proper type casting with null safety - Add fallback error messages These changes ensure the workflow triggers correctly on mobile/ directory changes and improves overall code robustness. * Fix transactions exposure and error handling issues - Add UnmodifiableListView to transactions getter to prevent external mutation - Call notifyListeners() immediately after setting _isLoading = false - Move jsonDecode to run only after successful statusCode verification - Replace string concatenation with Uri.replace() for proper URL encoding - Add try/catch for jsonDecode on non-2xx responses to handle non-JSON errors * Fix exception handling and duplicate parsing in auth_service.dart - Replace broad catch-all exception handlers with targeted exception handling - Add specific catches for SocketException, TimeoutException, HttpException, FormatException, and TypeError - Return safe, user-friendly error messages instead of exposing internal details - Log full exception details and stack traces using debugPrint for debugging - Fix duplicate User.fromJson calls in login and signup methods by parsing once and reusing the instance - Improve code efficiency and security by preventing information leakage * Fix 2FA login crash and improve UX Fixed the crash that occurred when logging in with 2FA-enabled accounts and improved the user experience by not showing error messages when MFA is required (it's a normal flow, not an error). Changes: - Added mounted check before setState() in login screen - Modified AuthProvider to not set error message when MFA is required - Ensures smooth transition from password entry to OTP entry - Prevents "setState() called after dispose()" error The flow now works correctly: 1. User enters email/password → clicks Sign In 2. Backend responds with mfa_required 3. OTP input field appears with friendly blue prompt (no red error) 4. User enters 6-digit code → clicks Sign In again 5. Login succeeds * Add debug logs to trace 2FA login flow Added comprehensive debug logging to understand why OTP field is not showing when MFA is required: - Log backend response status and body - Log login result in AuthProvider - Log MFA required state - Log when OTP field should be shown This will help identify if the issue is: 1. Backend not returning mfa_required flag 2. Response parsing issue 3. State management issue 4. UI rendering issue * Fix 2FA login flow by moving MFA state to AuthProvider PROBLEM: The LoginScreen was being recreated when AuthProvider called notifyListeners(), causing all internal state (_showOtpField) to be lost. This resulted in the OTP input field never appearing, making 2FA login impossible. ROOT CAUSE: The AppWrapper uses a Consumer<AuthProvider> that rebuilds the entire widget tree when auth state changes. When login() sets isLoading=false and calls notifyListeners(), a brand new LoginScreen instance is created, resetting all internal state. SOLUTION: - Moved _showMfaInput state from LoginScreen to AuthProvider - AuthProvider now manages when to show the MFA input field - LoginScreen uses Consumer to read this state reactively - State survives widget rebuilds FLOW: 1. User enters email/password → clicks Sign In 2. Backend responds with mfa_required: true 3. AuthProvider sets _showMfaInput = true 4. Consumer rebuilds, showing OTP field (state preserved) 5. User enters code → clicks Sign In 6. Backend validates → returns tokens → login succeeds Backend is confirmed working via tests (auth_controller_test.rb). * Fix mobile 2FA login requiring double password entry Problem: When 2FA is required during mobile login, the LoginScreen was being destroyed and recreated, causing text controllers to reset and forcing users to re-enter their credentials. Root cause: AppWrapper was checking authProvider.isLoading and showing a full-screen loading indicator during login attempts. This caused LoginScreen to be unmounted when isLoading=true, destroying the State and text controllers. When the backend returned mfa_required, isLoading=false triggered recreation of LoginScreen with empty fields. Solution: - Add isInitializing state to AuthProvider to distinguish initial auth check from active login attempts - Update AppWrapper to only show loading spinner during isInitializing, not during login flow - LoginScreen now persists across login attempts, preserving entered credentials Flow after fix: 1. User enters email/password 2. LoginScreen stays mounted (shows loading in button only) 3. Backend returns mfa_required 4. MFA field appears, email/password fields retain values 5. User enters OTP and submits (email/password automatically included) Files changed: - mobile/lib/providers/auth_provider.dart: Add isInitializing state - mobile/lib/main.dart: Use isInitializing instead of isLoading in AppWrapper * Add OTP error feedback for mobile 2FA login When users enter an incorrect OTP code during 2FA login, the app now: - Displays an error message indicating the code was invalid - Keeps the MFA input field visible for retry - Automatically clears the OTP field for easy re-entry Changes: - mobile/lib/providers/auth_provider.dart: * Distinguish between first MFA request vs invalid OTP error * Show error message when OTP code was submitted but invalid * Keep MFA input visible when in MFA flow with errors - mobile/lib/screens/login_screen.dart: * Clear OTP field after failed login attempt * Improve UX by allowing easy retry without re-entering credentials User flow after fix: 1. User enters email/password 2. MFA required - OTP field appears 3. User enters wrong OTP 4. Error message shows "Two-factor authentication required" 5. OTP field clears, ready for new code 6. User can immediately retry without re-entering email/password * Improve OTP error message clarity When user enters an invalid OTP code, show clearer error message "Invalid authentication code. Please try again." instead of the confusing "Two-factor authentication required" from backend. This makes it clear that the OTP was wrong, not that they need to start the 2FA process. * chore: delete generation ai create test flow md. * Update mobile/lib/screens/login_screen.dart Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Lazy Bone <89256478+dwvwdv@users.noreply.github.com> * feat: add pubspec.lock file. * Linter * Update mobile/android/app/build.gradle Co-authored-by: Pedro Piñera Buendía <663605+pepicrft@users.noreply.github.com> Signed-off-by: Lazy Bone <89256478+dwvwdv@users.noreply.github.com> * Update mobile/android/app/build.gradle com.sure.mobile -> am.sure.mobile Co-authored-by: Pedro Piñera Buendía <663605+pepicrft@users.noreply.github.com> Signed-off-by: Lazy Bone <89256478+dwvwdv@users.noreply.github.com> * Update mobile/ios/Runner.xcodeproj/project.pbxproj Co-authored-by: Pedro Piñera Buendía <663605+pepicrft@users.noreply.github.com> Signed-off-by: Lazy Bone <89256478+dwvwdv@users.noreply.github.com> * Update mobile/ios/Runner.xcodeproj/project.pbxproj Co-authored-by: Pedro Piñera Buendía <663605+pepicrft@users.noreply.github.com> Signed-off-by: Lazy Bone <89256478+dwvwdv@users.noreply.github.com> * Update mobile/ios/Runner.xcodeproj/project.pbxproj Co-authored-by: Pedro Piñera Buendía <663605+pepicrft@users.noreply.github.com> Signed-off-by: Lazy Bone <89256478+dwvwdv@users.noreply.github.com> * Fix iOS deployment target and update documentation - Update iOS minimum deployment target from 12.0 to 13.0 in Podfile for Flutter compatibility - Translate SIGNING_SETUP.md from Chinese to English for better accessibility - Remove TECHNICAL_GUIDE.md as requested * Restore TECHNICAL_GUIDE.md with partial content removal - Restore mobile/docs/TECHNICAL_GUIDE.md (previously deleted) - Remove only License, Contributing, and Related Links sections (from line 445 onwards) - Keep all technical documentation content (lines 1-444) * Fix setState after dispose errors across mobile app This commit fixes 5 critical setState/dispose errors identified by Cursor: 1. backend_config_screen.dart: Add mounted checks in _testConnection() and _saveAndContinue() methods to prevent setState calls after async operations (http.get, SharedPreferences) when widget is disposed. 2. transaction_form_screen.dart: Add mounted check in _selectDate() after showDatePicker to prevent setState when modal is dismissed while date picker is open. 3. main.dart: Add mounted check in _checkBackendConfig() after ApiConfig.initialize() to handle disposal during async initialization. 4. transactions_list_screen.dart: Add mounted check in the .then() callback of _showAddTransactionForm() to prevent calling _loadTransactions() on a disposed widget when modal is closed. 5. transactions_provider.dart: Fix premature notifyListeners() by removing intermediate notification after _isLoading = false, ensuring listeners only get notified once with complete state updates to prevent momentary stale UI state. All setState calls after async operations now properly check mounted status to prevent "setState() called after dispose()" errors. * Fix Android build: Remove package attribute from AndroidManifest.xml Remove deprecated package attribute from AndroidManifest.xml. The namespace is now correctly defined only in build.gradle as required by newer versions of Android Gradle Plugin. This fixes the build error: "Incorrect package="com.sure.mobile" found in source AndroidManifest.xml. Setting the namespace via the package attribute in the source AndroidManifest.xml is no longer supported." * Update issue templates * Change package name from com.sure.mobile to am.sure.mobile Updated Android package name across all files: - build.gradle: namespace and applicationId - MainActivity.kt: package declaration and file path - Moved MainActivity.kt from com/sure/mobile to am/sure/mobile This aligns with the package name change made in the mobile-support branch and fixes app crashes caused by package name mismatch. * Fix mobile app code quality issues - Add mounted check in backend_config_screen.dart to prevent setState after dispose - Translate Chinese comments to English in transactions_list_screen.dart for better maintainability - Replace brittle string-split date conversion with DateFormat in transaction_form_screen.dart for safer date handling These changes address code review feedback and improve code robustness. * Remove feature request template Delete unused feature request issue template file. * Fix mobile app code quality issues - Fix URL construction in backend_config_screen.dart to prevent double slashes by normalizing base URL (removing trailing slashes) before appending paths - Update pubspec.yaml to require Flutter 3.27.0+ for withValues API compatibility - Improve amount parsing robustness in transactions_list_screen.dart with proper locale handling, sign detection, and fallback error handling - Fix dismissible delete handler to prevent UI/backend inconsistency by moving deletion to confirmDismiss and only allowing dismissal on success * Fix mobile app performance and security issues - Eliminate duplicate _getAmountDisplayInfo calls in transactions list by computing display info once per transaction item - Upgrade flutter_secure_storage from 9.0.0 to 10.0.0 for AES-GCM encryption - Update dev dependencies: flutter_lints to 6.0.0 and flutter_launcher_icons to 0.14.4 * Update Android SDK requirements for flutter_secure_storage v10 - Increase compileSdk from 35 to 36 - Increase minSdkVersion from 21 to 24 This is required by flutter_secure_storage v10+ which uses newer Android APIs for AES-GCM encryption. * Fix transaction deletion message not displaying properly The success message was being shown in the onDismissed callback, which executes after the dismissal animation completes. By that time, the context may have become invalid due to widget tree rebuilds, causing the SnackBar to not display. Moved the success message to the confirmDismiss callback where we already have a captured scaffoldMessenger reference, ensuring the message displays reliably before the dismissal animation begins. * Add mounted check before showing SnackBar after async operation * Update mobile/android/app/build.gradle Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Signed-off-by: Lazy Bone <89256478+dwvwdv@users.noreply.github.com> * Fix empty state refresh and auth error feedback in mobile transactions screen - Wrap empty state in RefreshIndicator with CustomScrollView to enable pull-to-refresh when no transactions exist - Wrap error state in RefreshIndicator as well for consistency - Add SnackBar feedback when auth token is null in _loadTransactions instead of silent failure - Ensure mounted check before showing SnackBar to prevent errors after widget disposal * Fix flash of 'No accounts yet' page on app startup Added initialization state tracking to AccountsProvider to prevent the empty state from briefly showing while accounts are being loaded for the first time. Changes: - Add _isInitializing flag to AccountsProvider (starts as true) - Set to false after first fetchAccounts() completes - Reset to true when clearAccounts() is called - Update DashboardScreen to show loading during initialization This ensures a smooth user experience without visual flashing on app launch. * Refactor: Extract transaction deletion logic into dedicated method Improved code readability by extracting the 67-line confirmDismiss callback into a separate _confirmAndDeleteTransaction method. Changes: - Add Transaction model import - Create _confirmAndDeleteTransaction method that handles: - Confirmation dialog - Token retrieval - Deletion API call - Success/failure feedback - Simplify confirmDismiss to single line calling new method This separation of concerns makes the code more maintainable and the Dismissible widget configuration more concise. * Enhance Flutter build workflow with keystore checks Signed-off-by: Lazy Bone <89256478+dwvwdv@users.noreply.github.com> * Implement conditional signing configuration Added a check for keystore properties before configuring signing. Signed-off-by: Lazy Bone <89256478+dwvwdv@users.noreply.github.com> --------- Signed-off-by: Lazy Bone <89256478+dwvwdv@users.noreply.github.com> Co-authored-by: dwvwdv <dwvwdv@protonmail.com> Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Juan José Mata <juanjo.mata@gmail.com> Co-authored-by: Pedro Piñera Buendía <663605+pepicrft@users.noreply.github.com> |