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>
This commit is contained in:
Lazy Bone
2026-01-11 19:45:33 +08:00
committed by GitHub
parent 38f4c2222c
commit f52b3fceb6
13 changed files with 1869 additions and 8 deletions

View File

@@ -3,9 +3,10 @@ import 'package:provider/provider.dart';
import 'providers/auth_provider.dart';
import 'providers/accounts_provider.dart';
import 'providers/transactions_provider.dart';
import 'providers/chat_provider.dart';
import 'screens/backend_config_screen.dart';
import 'screens/login_screen.dart';
import 'screens/dashboard_screen.dart';
import 'screens/main_navigation_screen.dart';
import 'services/api_config.dart';
import 'services/connectivity_service.dart';
import 'services/log_service.dart';
@@ -30,6 +31,7 @@ class SureApp extends StatelessWidget {
ChangeNotifierProvider(create: (_) => LogService.instance),
ChangeNotifierProvider(create: (_) => ConnectivityService()),
ChangeNotifierProvider(create: (_) => AuthProvider()),
ChangeNotifierProvider(create: (_) => ChatProvider()),
ChangeNotifierProxyProvider<ConnectivityService, AccountsProvider>(
create: (_) => AccountsProvider(),
update: (_, connectivityService, accountsProvider) {
@@ -126,7 +128,7 @@ class SureApp extends StatelessWidget {
routes: {
'/config': (context) => const BackendConfigScreen(),
'/login': (context) => const LoginScreen(),
'/dashboard': (context) => const DashboardScreen(),
'/home': (context) => const MainNavigationScreen(),
},
home: const AppWrapper(),
),
@@ -201,7 +203,7 @@ class _AppWrapperState extends State<AppWrapper> {
}
if (authProvider.isAuthenticated) {
return const DashboardScreen();
return const MainNavigationScreen();
}
return LoginScreen(