diff --git a/.fvmrc b/.fvmrc new file mode 100644 index 0000000..c2783c6 --- /dev/null +++ b/.fvmrc @@ -0,0 +1,3 @@ +{ + "flutter": "3.27.4" +} \ No newline at end of file diff --git a/.gitignore b/.gitignore index 642ebc8..1cc7945 100644 --- a/.gitignore +++ b/.gitignore @@ -44,4 +44,7 @@ app.*.map.json /android/app/profile /android/app/release -.vscode/ \ No newline at end of file +.vscode/ + +# FVM Version Cache +.fvm/ \ No newline at end of file diff --git a/lib/ai_chat_assistant.dart b/lib/ai_chat_assistant.dart index 0d0a5f8..42f1ea9 100644 --- a/lib/ai_chat_assistant.dart +++ b/lib/ai_chat_assistant.dart @@ -23,4 +23,7 @@ export 'models/vehicle_status_info.dart'; export 'enums/vehicle_command_type.dart'; export 'enums/message_status.dart'; -export 'enums/message_service_state.dart'; \ No newline at end of file +export 'enums/message_service_state.dart'; + +// utils +export 'utils/assets_util.dart'; \ No newline at end of file diff --git a/lib/manager.dart b/lib/manager.dart index 53106d2..e913c61 100644 --- a/lib/manager.dart +++ b/lib/manager.dart @@ -8,6 +8,7 @@ import 'models/vehicle_cmd.dart'; /// 车辆命令处理器抽象类 abstract class VehicleCommandHandler { AIChatCommandCubit? commandCubit; + /// 执行车辆控制命令 Future<(bool, Map?)> executeCommand(VehicleCommand command); } @@ -48,5 +49,4 @@ class AIChatAssistantManager { _commandCubit?.close(); _commandCubit = null; } - } diff --git a/lib/screens/main_screen.dart b/lib/screens/main_screen.dart index 80e2425..79fb72e 100644 --- a/lib/screens/main_screen.dart +++ b/lib/screens/main_screen.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import '../widgets/floating_icon.dart'; +import '../utils/assets_util.dart'; class MainScreen extends StatefulWidget { const MainScreen({super.key}); @@ -26,9 +27,9 @@ class _MainScreenState extends State { body: Stack( children: [ Container( - decoration: const BoxDecoration( + decoration: BoxDecoration( image: DecorationImage( - image: AssetImage('assets/images/bg.jpg', package: 'ai_chat_assistant'), + image: AssetsUtil.getImage('bg.jpg'), fit: BoxFit.cover, ), ), diff --git a/lib/screens/part_screen.dart b/lib/screens/part_screen.dart index e6b1909..485dc3f 100644 --- a/lib/screens/part_screen.dart +++ b/lib/screens/part_screen.dart @@ -5,6 +5,7 @@ import '../screens/full_screen.dart'; import 'package:provider/provider.dart'; import '../services/message_service.dart'; import '../widgets/gradient_background.dart'; +import '../utils/assets_util.dart'; class PartScreen extends StatefulWidget { final VoidCallback? onHide; @@ -202,11 +203,10 @@ class _PartScreenState extends State { top: 6, right: 6, child: IconButton( - icon: Image.asset( - 'assets/images/open_in_full.png', + icon: AssetsUtil.getImageWidget( + 'open_in_full.png', width: 24, height: 24, - package: 'ai_chat_assistant', ), onPressed: _openFullScreen, padding: EdgeInsets.zero, diff --git a/lib/widgets/assistant_avatar.dart b/lib/widgets/assistant_avatar.dart index 8b90ee1..70e7a98 100644 --- a/lib/widgets/assistant_avatar.dart +++ b/lib/widgets/assistant_avatar.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import '../utils/assets_util.dart'; class AssistantAvatar extends StatelessWidget { final double width; @@ -15,10 +16,9 @@ class AssistantAvatar extends StatelessWidget { return SizedBox( width: width, height: height, - child: Image.asset( - 'assets/images/avatar.png', + child: AssetsUtil.getImageWidget( + 'avatar.png', fit: BoxFit.contain, - package: 'ai_chat_assistant', ), ); } diff --git a/lib/widgets/chat_bubble.dart b/lib/widgets/chat_bubble.dart index f7e027f..dc52ee3 100644 --- a/lib/widgets/chat_bubble.dart +++ b/lib/widgets/chat_bubble.dart @@ -9,6 +9,7 @@ import 'package:provider/provider.dart'; import '../services/message_service.dart'; import 'package:flutter/services.dart'; import 'package:fluttertoast/fluttertoast.dart'; +import '../utils/assets_util.dart'; class ChatBubble extends StatefulWidget { final ChatMessage message; @@ -108,7 +109,7 @@ class _ChatBubbleState extends State { case MessageStatus.listening: case MessageStatus.recognizing: case MessageStatus.thinking: - icon = RotatingImage(imagePath: 'assets/images/thinking_circle.png'); + icon = RotatingImage(imagePath: 'thinking_circle.png'); color = Colors.white; break; case MessageStatus.executing: @@ -123,11 +124,10 @@ class _ChatBubbleState extends State { break; case MessageStatus.completed: case MessageStatus.success: - icon = Image.asset( - 'assets/images/checked.png', + icon = AssetsUtil.getImageWidget( + 'checked.png', width: 20, height: 20, - package: 'ai_chat_assistant', ); color = Colors.white; break; @@ -306,8 +306,7 @@ class _ChatBubbleState extends State { }, child: Padding( padding: const EdgeInsets.only(left: 12), - child: Image.asset('assets/images/copy.png', - package: 'ai_chat_assistant', + child: AssetsUtil.getImageWidget('copy.png', width: 22, height: 22), ), @@ -322,12 +321,10 @@ class _ChatBubbleState extends State { child: Padding( padding: const EdgeInsets.only(left: 12), child: _liked - ? Image.asset('assets/images/liked2.png', - package: 'ai_chat_assistant', + ? AssetsUtil.getImageWidget('liked2.png', width: 22, height: 22) - : Image.asset('assets/images/liked1.png', - package: 'ai_chat_assistant', + : AssetsUtil.getImageWidget('liked1.png', width: 22, height: 22), ), @@ -342,12 +339,10 @@ class _ChatBubbleState extends State { child: Padding( padding: const EdgeInsets.only(left: 12), child: _disliked - ? Image.asset('assets/images/disliked2.png', - package: 'ai_chat_assistant', + ? AssetsUtil.getImageWidget('disliked2.png', width: 22, height: 22) - : Image.asset('assets/images/disliked1.png', - package: 'ai_chat_assistant', + : AssetsUtil.getImageWidget('disliked1.png', width: 22, height: 22)), ), diff --git a/lib/widgets/chat_footer.dart b/lib/widgets/chat_footer.dart index e0d969d..71b013a 100644 --- a/lib/widgets/chat_footer.dart +++ b/lib/widgets/chat_footer.dart @@ -5,6 +5,7 @@ import 'package:provider/provider.dart'; import '../services/message_service.dart'; import '../utils/common_util.dart'; import 'large_audio_wave.dart'; +import '../utils/assets_util.dart'; class ChatFooter extends StatefulWidget { final VoidCallback? onClear; @@ -48,8 +49,8 @@ class _ChatFooterState extends State padding: const EdgeInsets.only(left: 16, bottom: 12), child: GestureDetector( onTap: widget.onClear, - child: Image.asset( - 'assets/images/delete.png',package: 'ai_chat_assistant', + child: AssetsUtil.getImageWidget( + 'delete.png', width: 24, height: 24, ), @@ -138,8 +139,8 @@ class _ChatFooterState extends State onTap: () { }, - child: Image.asset( - 'assets/images/keyboard_mini.png',package: 'ai_chat_assistant', + child: AssetsUtil.getImageWidget( + 'keyboard_mini.png', width: 24, height: 24, ), diff --git a/lib/widgets/floating_icon.dart b/lib/widgets/floating_icon.dart index d83c1ed..a5bd55f 100644 --- a/lib/widgets/floating_icon.dart +++ b/lib/widgets/floating_icon.dart @@ -6,6 +6,7 @@ import '../screens/part_screen.dart'; import 'floating_icon_with_wave.dart'; import 'dart:async'; import 'package:basic_intl/intl.dart'; +import '../utils/assets_util.dart'; class FloatingIcon extends StatefulWidget { const FloatingIcon({super.key}); @@ -35,13 +36,13 @@ class _FloatingIconState extends State with TickerProviderStateMix // 图片切换相关 int _imageIndex = 0; late final List _iconImages = [ - 'assets/images/ai1_hd.png', - 'assets/images/ai0_hd.png', + 'ai1_hd.png', + 'ai0_hd.png', ]; late final List _iconImagesEn = [ - 'assets/images/ai1_hd_en.png', - 'assets/images/ai0_hd_en.png', + 'ai1_hd_en.png', + 'ai0_hd_en.png', ]; @override @@ -96,7 +97,7 @@ class _FloatingIconState extends State with TickerProviderStateMix // 显示全屏界面 void _showFullScreen() async { _hidePartScreen(); - final messageService = context.read(); + final messageService = MessageService.instance; await Navigator.of(context).push( MaterialPageRoute( @@ -170,7 +171,10 @@ class _FloatingIconState extends State with TickerProviderStateMix // } // }); - return ChangeNotifierProvider(create: (_) => MessageService(), child: _buildFloatingIcon()); + return ChangeNotifierProvider.value( + value: MessageService.instance, + child: _buildFloatingIcon(), + ); } Widget _buildFloatingIcon() { @@ -249,13 +253,12 @@ class _FloatingIconState extends State with TickerProviderStateMix iconSize: iconSize, waveColor: Colors.white, ) - : Image.asset( + : AssetsUtil.getImageWidget( Intl.getCurrentLocale().startsWith('zh') ? _iconImages[_imageIndex] : _iconImagesEn[_imageIndex], width: iconSize, height: iconSize, - package: 'ai_chat_assistant', ), ), ); diff --git a/lib/widgets/floating_icon_with_wave.dart b/lib/widgets/floating_icon_with_wave.dart index f4764a4..18c20ff 100644 --- a/lib/widgets/floating_icon_with_wave.dart +++ b/lib/widgets/floating_icon_with_wave.dart @@ -32,12 +32,11 @@ class FloatingIconWithWave extends StatelessWidget { alignment: Alignment.center, children: [ // 背景图片 - Image.asset( - 'assets/images/ai_hd_clean.png', + AssetsUtil.getImageWidget( + 'ai_hd_clean.png', width: iconSize, height: iconSize, fit: BoxFit.contain, - package: AssetsUtil.packageName ), // 声波动画,距离底部13px的位置 Positioned( diff --git a/lib/widgets/rotating_image.dart b/lib/widgets/rotating_image.dart index f383e2f..b793df9 100644 --- a/lib/widgets/rotating_image.dart +++ b/lib/widgets/rotating_image.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import '../utils/assets_util.dart'; class RotatingImage extends StatefulWidget { final String imagePath; @@ -42,11 +43,10 @@ class _RotatingImageState extends State Widget build(BuildContext context) { return RotationTransition( turns: _controller, - child: Image.asset( + child: AssetsUtil.getImageWidget( widget.imagePath, width: widget.size, height: widget.size, - package: widget.package, // 使用传入的package参数 ), ); }