使用 assets_util 来管理 assets

This commit is contained in:
2025-09-19 11:40:38 +08:00
parent b84899ece3
commit 0509096925
12 changed files with 50 additions and 42 deletions

3
.fvmrc Normal file
View File

@@ -0,0 +1,3 @@
{
"flutter": "3.27.4"
}

5
.gitignore vendored
View File

@@ -44,4 +44,7 @@ app.*.map.json
/android/app/profile
/android/app/release
.vscode/
.vscode/
# FVM Version Cache
.fvm/

View File

@@ -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';
export 'enums/message_service_state.dart';
// utils
export 'utils/assets_util.dart';

View File

@@ -8,6 +8,7 @@ import 'models/vehicle_cmd.dart';
/// 车辆命令处理器抽象类
abstract class VehicleCommandHandler {
AIChatCommandCubit? commandCubit;
/// 执行车辆控制命令
Future<(bool, Map<String, dynamic>?)> executeCommand(VehicleCommand command);
}
@@ -48,5 +49,4 @@ class AIChatAssistantManager {
_commandCubit?.close();
_commandCubit = null;
}
}

View File

@@ -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<MainScreen> {
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,
),
),

View File

@@ -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<PartScreen> {
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,

View File

@@ -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',
),
);
}

View File

@@ -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<ChatBubble> {
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<ChatBubble> {
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<ChatBubble> {
},
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<ChatBubble> {
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<ChatBubble> {
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)),
),

View File

@@ -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<ChatFooter>
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<ChatFooter>
onTap: () {
},
child: Image.asset(
'assets/images/keyboard_mini.png',package: 'ai_chat_assistant',
child: AssetsUtil.getImageWidget(
'keyboard_mini.png',
width: 24,
height: 24,
),

View File

@@ -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<FloatingIcon> with TickerProviderStateMix
// 图片切换相关
int _imageIndex = 0;
late final List<String> _iconImages = [
'assets/images/ai1_hd.png',
'assets/images/ai0_hd.png',
'ai1_hd.png',
'ai0_hd.png',
];
late final List<String> _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<FloatingIcon> with TickerProviderStateMix
// 显示全屏界面
void _showFullScreen() async {
_hidePartScreen();
final messageService = context.read<MessageService>();
final messageService = MessageService.instance;
await Navigator.of(context).push(
MaterialPageRoute(
@@ -170,7 +171,10 @@ class _FloatingIconState extends State<FloatingIcon> 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<FloatingIcon> 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',
),
),
);

View File

@@ -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(

View File

@@ -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<RotatingImage>
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参数
),
);
}