|
|
|
@ -1,5 +1,6 @@ |
|
|
|
import 'dart:async'; |
|
|
|
import 'dart:io'; |
|
|
|
import 'dart:math'; |
|
|
|
import 'package:flutter/material.dart'; |
|
|
|
import 'package:get/get.dart'; |
|
|
|
import '../controllers/agent_controller.dart'; |
|
|
|
@ -61,40 +62,40 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
backgroundColor: backgroundColor, |
|
|
|
leading: IconButton( |
|
|
|
icon: Icon(Icons.arrow_back_ios, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, size: 20), |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, size: 20.sp), |
|
|
|
onPressed: () => Get.back(), |
|
|
|
), |
|
|
|
titleSpacing: 0, |
|
|
|
title: Row( |
|
|
|
children: [ |
|
|
|
Container( |
|
|
|
width: 40, |
|
|
|
height: 40, |
|
|
|
width: 40.w, |
|
|
|
height: 40.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: primaryColor, |
|
|
|
borderRadius: BorderRadius.circular(20), |
|
|
|
borderRadius: BorderRadius.circular(20.w), |
|
|
|
boxShadow: [ |
|
|
|
BoxShadow( |
|
|
|
color: Colors.black.withOpacity(0.1), |
|
|
|
blurRadius: 3, |
|
|
|
blurRadius: 3.w, |
|
|
|
offset: const Offset(0, 1), |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
child: const Icon( |
|
|
|
child: Icon( |
|
|
|
Icons.smart_toy_outlined, |
|
|
|
color: Colors.white, |
|
|
|
size: 22, |
|
|
|
size: 22.sp, |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(width: 12), |
|
|
|
SizedBox(width: 12.w), |
|
|
|
Column( |
|
|
|
crossAxisAlignment: CrossAxisAlignment.start, |
|
|
|
children: [ |
|
|
|
Text( |
|
|
|
'XiaoYan'.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 16, |
|
|
|
fontSize: 16.sp, |
|
|
|
fontWeight: FontWeight.bold, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, |
|
|
|
), |
|
|
|
@ -102,18 +103,18 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
Row( |
|
|
|
children: [ |
|
|
|
Container( |
|
|
|
width: 6, |
|
|
|
height: 6, |
|
|
|
width: 6.w, |
|
|
|
height: 6.w, |
|
|
|
decoration: const BoxDecoration( |
|
|
|
color: Colors.green, |
|
|
|
shape: BoxShape.circle, |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(width: 4), |
|
|
|
SizedBox(width: 4.w), |
|
|
|
Text( |
|
|
|
'online'.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12, |
|
|
|
fontSize: 12.sp, |
|
|
|
color: Colors.green, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
), |
|
|
|
@ -131,6 +132,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
controller.isTtsEnabled.value |
|
|
|
? Icons.volume_up |
|
|
|
: Icons.volume_off, |
|
|
|
size: 24.sp, |
|
|
|
color: controller.isTtsEnabled.value |
|
|
|
? primaryColor |
|
|
|
: isDarkMode |
|
|
|
@ -142,9 +144,9 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
|
|
|
|
// 更多选项 |
|
|
|
Container( |
|
|
|
width: 34, |
|
|
|
height: 34, |
|
|
|
margin: const EdgeInsets.only(right: 8), |
|
|
|
width: 34.w, |
|
|
|
height: 34.w, |
|
|
|
margin: EdgeInsets.only(right: 8.w), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: |
|
|
|
isDarkMode ? Colors.white.withOpacity(0.1) : Colors.grey[100], |
|
|
|
@ -153,25 +155,28 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
if (!isDarkMode) |
|
|
|
BoxShadow( |
|
|
|
color: Colors.black.withOpacity(0.05), |
|
|
|
blurRadius: 2, |
|
|
|
spreadRadius: 0.5, |
|
|
|
blurRadius: 2.w, |
|
|
|
spreadRadius: 0.5.w, |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
child: PopupMenuButton( |
|
|
|
icon: Icon(Icons.more_vert, |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, size: 20), |
|
|
|
color: isDarkMode ? Colors.white : Colors.black87, |
|
|
|
size: 20.sp), |
|
|
|
shape: RoundedRectangleBorder( |
|
|
|
borderRadius: BorderRadius.circular(12), |
|
|
|
borderRadius: BorderRadius.circular(12.w), |
|
|
|
), |
|
|
|
color: isDarkMode ? Colors.grey[800] : Colors.white, |
|
|
|
itemBuilder: (context) => [ |
|
|
|
PopupMenuItem( |
|
|
|
child: Row( |
|
|
|
children: [ |
|
|
|
Icon(Icons.delete_outline, color: primaryColor, size: 20), |
|
|
|
const SizedBox(width: 8), |
|
|
|
Text('clearChatHistory'.tr, style: TextStyle(fontSize: 14)), |
|
|
|
Icon(Icons.delete_outline, |
|
|
|
color: primaryColor, size: 20.sp), |
|
|
|
SizedBox(width: 8.w), |
|
|
|
Text('clearChatHistory'.tr, |
|
|
|
style: TextStyle(fontSize: 14.sp)), |
|
|
|
], |
|
|
|
), |
|
|
|
onTap: () => Future.delayed( |
|
|
|
@ -198,8 +203,8 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
controller: controller.scrollController, |
|
|
|
shrinkWrap: true, |
|
|
|
reverse: true, |
|
|
|
padding: const EdgeInsets.symmetric( |
|
|
|
vertical: 16, horizontal: 16), |
|
|
|
padding: EdgeInsets.symmetric( |
|
|
|
vertical: 16.h, horizontal: 16.w), |
|
|
|
itemCount: controller.messages.length + |
|
|
|
(controller.hasMoreMessages.value ? 1 : 0), |
|
|
|
itemBuilder: (context, index) { |
|
|
|
@ -212,7 +217,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
final message = controller |
|
|
|
.messages[controller.messages.length - 1 - index]; |
|
|
|
return Padding( |
|
|
|
padding: const EdgeInsets.only(bottom: 8), |
|
|
|
padding: EdgeInsets.only(bottom: 8.h), |
|
|
|
child: GestureDetector( |
|
|
|
onLongPressStart: |
|
|
|
(LongPressStartDetails details) { |
|
|
|
@ -237,21 +242,20 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
|
|
|
|
// 输入区域 |
|
|
|
Container( |
|
|
|
padding: |
|
|
|
const EdgeInsets.symmetric(horizontal: 16, vertical: 12), |
|
|
|
padding: EdgeInsets.symmetric(horizontal: 16.w, vertical: 12.h), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: backgroundColor, |
|
|
|
boxShadow: [ |
|
|
|
BoxShadow( |
|
|
|
color: Colors.black.withOpacity(0.06), |
|
|
|
blurRadius: 8, |
|
|
|
blurRadius: 8.w, |
|
|
|
offset: const Offset(0, -1), |
|
|
|
), |
|
|
|
], |
|
|
|
border: Border( |
|
|
|
top: BorderSide( |
|
|
|
color: Colors.grey.withOpacity(0.15), |
|
|
|
width: 1, |
|
|
|
width: 1.w, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
@ -269,29 +273,29 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
Stack( |
|
|
|
children: [ |
|
|
|
ClipRRect( |
|
|
|
borderRadius: BorderRadius.circular(12), |
|
|
|
borderRadius: BorderRadius.circular(12.w), |
|
|
|
child: Image.file( |
|
|
|
File(controller.selectedImagePath.value!), |
|
|
|
height: 150, |
|
|
|
height: 150.h, |
|
|
|
width: double.infinity, |
|
|
|
fit: BoxFit.cover, |
|
|
|
), |
|
|
|
), |
|
|
|
Positioned( |
|
|
|
top: 8, |
|
|
|
right: 8, |
|
|
|
top: 8.h, |
|
|
|
right: 8.w, |
|
|
|
child: GestureDetector( |
|
|
|
onTap: () => controller.clearImageInput(), |
|
|
|
child: Container( |
|
|
|
padding: const EdgeInsets.all(4), |
|
|
|
padding: EdgeInsets.all(4.w), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: Colors.black.withOpacity(0.6), |
|
|
|
shape: BoxShape.circle, |
|
|
|
), |
|
|
|
child: const Icon( |
|
|
|
child: Icon( |
|
|
|
Icons.close, |
|
|
|
color: Colors.white, |
|
|
|
size: 16, |
|
|
|
size: 16.sp, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
@ -300,7 +304,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
), |
|
|
|
|
|
|
|
// 预设提示选项 |
|
|
|
const SizedBox(height: 12), |
|
|
|
SizedBox(height: 12.h), |
|
|
|
SingleChildScrollView( |
|
|
|
scrollDirection: Axis.horizontal, |
|
|
|
child: Row( |
|
|
|
@ -310,14 +314,14 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
label: 'summarizeImageContent'.tr, //总结图片内容 |
|
|
|
onTap: () => controller.summarizeImage(), |
|
|
|
), |
|
|
|
const SizedBox(width: 8), |
|
|
|
SizedBox(width: 8.w), |
|
|
|
_buildPromptChip( |
|
|
|
context: context, |
|
|
|
label: 'extractImageText'.tr, //抽取图像文字 |
|
|
|
onTap: () => |
|
|
|
controller.extractTextFromImage(), |
|
|
|
), |
|
|
|
const SizedBox(width: 8), |
|
|
|
SizedBox(width: 8.w), |
|
|
|
_buildPromptChip( |
|
|
|
context: context, |
|
|
|
label: 'translateImageText'.tr, //翻译图像文字 |
|
|
|
@ -327,7 +331,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(height: 12), |
|
|
|
SizedBox(height: 12.h), |
|
|
|
], |
|
|
|
); |
|
|
|
} else { |
|
|
|
@ -353,8 +357,8 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
controller.toggleInputMode(); |
|
|
|
}, |
|
|
|
child: Container( |
|
|
|
width: 44, |
|
|
|
height: 44, |
|
|
|
width: 44.w, |
|
|
|
height: 44.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isDarkMode |
|
|
|
? Colors.grey[800] |
|
|
|
@ -368,13 +372,13 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
color: isDarkMode |
|
|
|
? Colors.grey[300] |
|
|
|
: Colors.grey[700], |
|
|
|
size: 22, |
|
|
|
size: 22.sp, |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
}), |
|
|
|
|
|
|
|
const SizedBox(width: 8), |
|
|
|
SizedBox(width: 8.w), |
|
|
|
|
|
|
|
// 文本输入框或语音波形图 |
|
|
|
Expanded( |
|
|
|
@ -385,23 +389,23 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
if (controller.isTextInputMode.value) { |
|
|
|
// 文本输入模式 - 限制最大高度并只向上扩展 |
|
|
|
return Container( |
|
|
|
constraints: const BoxConstraints( |
|
|
|
minHeight: 44, // 最小高度 |
|
|
|
maxHeight: 120, // 最大高度限制,防止挤压按钮 |
|
|
|
constraints: BoxConstraints( |
|
|
|
minHeight: 44.h, |
|
|
|
maxHeight: 120.h, |
|
|
|
), |
|
|
|
padding: const EdgeInsets.symmetric( |
|
|
|
horizontal: 16), |
|
|
|
padding: EdgeInsets.symmetric( |
|
|
|
horizontal: 16.w), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isDarkMode |
|
|
|
? Colors.grey[800] |
|
|
|
: Colors.grey[200], |
|
|
|
borderRadius: BorderRadius.circular(22), |
|
|
|
borderRadius: |
|
|
|
BorderRadius.circular(22.w), |
|
|
|
border: Border.all( |
|
|
|
color: isDarkMode |
|
|
|
? Colors.grey[ |
|
|
|
800]! // 修改: 从 Colors.grey[700] 改为 Colors.grey[800] |
|
|
|
? Colors.grey[800]! |
|
|
|
: Colors.grey.withOpacity(0.1), |
|
|
|
width: 1.0, |
|
|
|
width: 1.w, |
|
|
|
), |
|
|
|
), |
|
|
|
child: Row( |
|
|
|
@ -435,7 +439,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
} |
|
|
|
}, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 15, |
|
|
|
fontSize: 15.sp, |
|
|
|
color: isDarkMode |
|
|
|
? Colors.white |
|
|
|
: Colors.grey[800], |
|
|
|
@ -448,7 +452,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
.tr, // 输入消息... |
|
|
|
hintStyle: TextStyle( |
|
|
|
color: Colors.grey[500], |
|
|
|
fontSize: 15, |
|
|
|
fontSize: 15.sp, |
|
|
|
), |
|
|
|
filled: false, |
|
|
|
border: InputBorder.none, |
|
|
|
@ -458,14 +462,15 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
color: isDarkMode |
|
|
|
? Colors.grey[800]! |
|
|
|
: Colors.grey[200]!, |
|
|
|
width: 1.0, |
|
|
|
width: 1.w, |
|
|
|
), |
|
|
|
), |
|
|
|
contentPadding: |
|
|
|
EdgeInsets.symmetric( |
|
|
|
vertical: isImageActive |
|
|
|
? 12 |
|
|
|
: 8), // 调整垂直内边距 |
|
|
|
vertical: |
|
|
|
isImageActive |
|
|
|
? 12.h |
|
|
|
: 8.h), |
|
|
|
), |
|
|
|
onSubmitted: (_) => |
|
|
|
controller.sendMessage(), |
|
|
|
@ -525,9 +530,9 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
controller.isListening.value; |
|
|
|
|
|
|
|
return Container( |
|
|
|
height: 50, |
|
|
|
padding: const EdgeInsets.symmetric( |
|
|
|
horizontal: 16), |
|
|
|
height: 50.h, |
|
|
|
padding: EdgeInsets.symmetric( |
|
|
|
horizontal: 16.w), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isPushToTalkActive |
|
|
|
? (isDarkMode |
|
|
|
@ -537,7 +542,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
? Colors.grey[800] |
|
|
|
: Colors.grey[200]), |
|
|
|
borderRadius: |
|
|
|
BorderRadius.circular(22), |
|
|
|
BorderRadius.circular(22.w), |
|
|
|
border: Border.all( |
|
|
|
color: isPushToTalkActive |
|
|
|
? Colors.blue |
|
|
|
@ -546,8 +551,8 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
: Colors.grey |
|
|
|
.withOpacity(0.1)), |
|
|
|
width: isPushToTalkActive |
|
|
|
? 2.0 |
|
|
|
: 1.0, |
|
|
|
? 2.w |
|
|
|
: 1.w, |
|
|
|
), |
|
|
|
), |
|
|
|
child: Row( |
|
|
|
@ -572,7 +577,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
isPushToTalkActive |
|
|
|
? Icons.mic |
|
|
|
: Icons.mic_none, |
|
|
|
size: 16, |
|
|
|
size: 16.sp, |
|
|
|
color: isPushToTalkActive |
|
|
|
? Colors.blue |
|
|
|
: Colors.grey[500], |
|
|
|
@ -607,7 +612,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
}), |
|
|
|
), |
|
|
|
|
|
|
|
const SizedBox(width: 8), |
|
|
|
SizedBox(width: 8.w), |
|
|
|
|
|
|
|
// 动态按钮区域:展开按钮 + 发送按钮 或 图片选择按钮 |
|
|
|
Obx(() { |
|
|
|
@ -627,7 +632,7 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
if (shouldShowExpand && hasText) |
|
|
|
Padding( |
|
|
|
padding: |
|
|
|
const EdgeInsets.only(bottom: 40), |
|
|
|
EdgeInsets.only(bottom: 40.h), |
|
|
|
child: GestureDetector( |
|
|
|
onTap: () { |
|
|
|
// 打开底部弹出编辑模式 |
|
|
|
@ -646,21 +651,21 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
}); |
|
|
|
}, |
|
|
|
child: Container( |
|
|
|
width: 32, |
|
|
|
height: 32, |
|
|
|
width: 32.w, |
|
|
|
height: 32.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isDarkMode |
|
|
|
? Colors.grey[700] |
|
|
|
: Colors.grey[300], |
|
|
|
borderRadius: |
|
|
|
BorderRadius.circular(16), |
|
|
|
BorderRadius.circular(16.w), |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
Icons.expand_less, |
|
|
|
color: isDarkMode |
|
|
|
? Colors.grey[300] |
|
|
|
: Colors.grey[700], |
|
|
|
size: 20, |
|
|
|
size: 20.sp, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
@ -669,17 +674,17 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
GestureDetector( |
|
|
|
onTap: () => controller.sendMessage(), |
|
|
|
child: Container( |
|
|
|
width: 44, |
|
|
|
height: 44, |
|
|
|
width: 44.w, |
|
|
|
height: 44.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: primaryColor, |
|
|
|
borderRadius: |
|
|
|
BorderRadius.circular(22), |
|
|
|
BorderRadius.circular(22.w), |
|
|
|
), |
|
|
|
child: const Icon( |
|
|
|
child: Icon( |
|
|
|
Icons.send, |
|
|
|
color: Colors.white, |
|
|
|
size: 22, |
|
|
|
size: 22.sp, |
|
|
|
), |
|
|
|
), |
|
|
|
), |
|
|
|
@ -695,21 +700,21 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
controller.togglePlusOptions(); |
|
|
|
}, |
|
|
|
child: Container( |
|
|
|
width: 44, |
|
|
|
height: 44, |
|
|
|
width: 44.w, |
|
|
|
height: 44.w, |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isDarkMode |
|
|
|
? Colors.grey[800] |
|
|
|
: Colors.grey[200], |
|
|
|
borderRadius: |
|
|
|
BorderRadius.circular(22), |
|
|
|
BorderRadius.circular(22.w), |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
isExpanded ? Icons.close : Icons.add, |
|
|
|
color: isDarkMode |
|
|
|
? Colors.grey[300] |
|
|
|
: Colors.grey[700], |
|
|
|
size: 22, |
|
|
|
size: 22.sp, |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
@ -727,15 +732,27 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
return AnimatedContainer( |
|
|
|
duration: const Duration(milliseconds: 300), |
|
|
|
curve: Curves.easeInOut, |
|
|
|
height: isExpanded ? 120.h : 0, // 调整高度以适应按钮尺寸 |
|
|
|
height: isExpanded ? 100.h : 0, // 调整高度以适应按钮尺寸 |
|
|
|
child: isExpanded |
|
|
|
? Container( |
|
|
|
margin: EdgeInsets.only(top: 8.h), |
|
|
|
? LayoutBuilder( |
|
|
|
// 添加LayoutBuilder获取实际约束 |
|
|
|
builder: (context, constraints) { |
|
|
|
return SingleChildScrollView( |
|
|
|
// 确保内容可滚动 |
|
|
|
scrollDirection: |
|
|
|
Axis.horizontal, // 水平滚动 |
|
|
|
child: Container( |
|
|
|
margin: EdgeInsets.only(top: 16.h), |
|
|
|
padding: EdgeInsets.symmetric( |
|
|
|
horizontal: 16.w), // 添加左右边距 |
|
|
|
child: Row( |
|
|
|
mainAxisAlignment: MainAxisAlignment |
|
|
|
.spaceEvenly, // 改为均匀分布 |
|
|
|
horizontal: 16.w), |
|
|
|
// 根据可用宽度调整容器宽度 |
|
|
|
width: max(constraints.maxWidth, |
|
|
|
300.w), // 最小300宽 |
|
|
|
child: Wrap( |
|
|
|
// 使用Wrap替代Row,自动换行 |
|
|
|
alignment: WrapAlignment.center, |
|
|
|
spacing: 26.w, // 按钮水平间距 |
|
|
|
runSpacing: 8.h, // 按钮垂直间距 |
|
|
|
children: [ |
|
|
|
// 相机按钮 |
|
|
|
_buildPlusOptionButton( |
|
|
|
@ -783,6 +800,9 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
), |
|
|
|
); |
|
|
|
}, |
|
|
|
) |
|
|
|
: const SizedBox.shrink(), |
|
|
|
); |
|
|
|
@ -813,25 +833,24 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
required String label, |
|
|
|
required VoidCallback onTap, |
|
|
|
}) { |
|
|
|
final theme = Theme.of(context); |
|
|
|
final primaryColor = theme.primaryColor; |
|
|
|
final primaryColor = Theme.of(context).primaryColor; |
|
|
|
|
|
|
|
return GestureDetector( |
|
|
|
onTap: onTap, |
|
|
|
child: Container( |
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), |
|
|
|
padding: EdgeInsets.symmetric(horizontal: 12.w, vertical: 8.h), |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: primaryColor.withOpacity(0.08), |
|
|
|
borderRadius: BorderRadius.circular(16), |
|
|
|
borderRadius: BorderRadius.circular(16.w), |
|
|
|
border: Border.all( |
|
|
|
color: primaryColor.withOpacity(0.2), |
|
|
|
width: 1, |
|
|
|
width: 1.w, |
|
|
|
), |
|
|
|
), |
|
|
|
child: Text( |
|
|
|
label, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 13, |
|
|
|
fontSize: 13.sp, |
|
|
|
color: primaryColor, |
|
|
|
fontWeight: FontWeight.w500, |
|
|
|
), |
|
|
|
@ -865,10 +884,10 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
height: 50.w, // 调整为44.w以适应布局 |
|
|
|
decoration: BoxDecoration( |
|
|
|
color: isDarkMode ? Colors.grey[800] : Colors.grey[100], |
|
|
|
borderRadius: BorderRadius.circular(12.r), // 调整为10.r |
|
|
|
borderRadius: BorderRadius.circular(12.w), |
|
|
|
border: Border.all( |
|
|
|
color: isDarkMode ? Colors.grey[700]! : Colors.grey[300]!, |
|
|
|
width: 1, |
|
|
|
width: 1.w, |
|
|
|
), |
|
|
|
), |
|
|
|
child: Icon( |
|
|
|
@ -1085,8 +1104,8 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
BoxShadow( |
|
|
|
color: (isActive ? Colors.red : Colors.green) |
|
|
|
.withOpacity(0.3), |
|
|
|
blurRadius: 12.r, |
|
|
|
spreadRadius: 2.r, |
|
|
|
blurRadius: 12.w, |
|
|
|
spreadRadius: 2.w, |
|
|
|
), |
|
|
|
], |
|
|
|
), |
|
|
|
@ -1148,23 +1167,23 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
if (controller.isLoadingMore.value) { |
|
|
|
// 正在加载状态 |
|
|
|
return Container( |
|
|
|
padding: const EdgeInsets.symmetric(vertical: 16), |
|
|
|
padding: EdgeInsets.symmetric(vertical: 16.h), |
|
|
|
child: Center( |
|
|
|
child: Row( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: [ |
|
|
|
const SizedBox( |
|
|
|
width: 16, |
|
|
|
height: 16, |
|
|
|
SizedBox( |
|
|
|
width: 16.w, |
|
|
|
height: 16.h, |
|
|
|
child: CircularProgressIndicator( |
|
|
|
strokeWidth: 2, |
|
|
|
strokeWidth: 2.w, |
|
|
|
), |
|
|
|
), |
|
|
|
const SizedBox(width: 8), |
|
|
|
SizedBox(width: 8.w), |
|
|
|
Text( |
|
|
|
'loadMoreMessages'.tr, // 加载更多消息... |
|
|
|
style: const TextStyle( |
|
|
|
fontSize: 14, |
|
|
|
'loadMoreMessages'.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 14.sp, |
|
|
|
color: Colors.grey, |
|
|
|
), |
|
|
|
), |
|
|
|
@ -1175,23 +1194,23 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
} else if (controller.isLoadingMoreError.value) { |
|
|
|
// 加载失败状态 |
|
|
|
return Container( |
|
|
|
padding: const EdgeInsets.symmetric(vertical: 16), |
|
|
|
padding: EdgeInsets.symmetric(vertical: 16.h), |
|
|
|
child: Center( |
|
|
|
child: GestureDetector( |
|
|
|
onTap: () => controller.loadMoreMessages(), |
|
|
|
child: Row( |
|
|
|
mainAxisSize: MainAxisSize.min, |
|
|
|
children: [ |
|
|
|
const Icon( |
|
|
|
Icon( |
|
|
|
Icons.refresh, |
|
|
|
size: 16, |
|
|
|
size: 16.sp, |
|
|
|
color: Colors.grey, |
|
|
|
), |
|
|
|
const SizedBox(width: 8), |
|
|
|
SizedBox(width: 8.w), |
|
|
|
Text( |
|
|
|
'loadFailedClickRetry'.tr, // 加载失败,点击重试 |
|
|
|
style: const TextStyle( |
|
|
|
fontSize: 14, |
|
|
|
'loadFailedClickRetry'.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 14.sp, |
|
|
|
color: Colors.grey, |
|
|
|
), |
|
|
|
), |
|
|
|
@ -1203,12 +1222,12 @@ class _AgentViewState extends State<AgentView> with WidgetsBindingObserver { |
|
|
|
} else { |
|
|
|
// 默认状态(有更多消息但未加载) |
|
|
|
return Container( |
|
|
|
padding: const EdgeInsets.symmetric(vertical: 8), |
|
|
|
padding: EdgeInsets.symmetric(vertical: 8.h), |
|
|
|
child: Center( |
|
|
|
child: Text( |
|
|
|
'swipeUpForMore'.tr, // 向上滑动查看更多 |
|
|
|
style: const TextStyle( |
|
|
|
fontSize: 12, |
|
|
|
'swipeUpForMore'.tr, |
|
|
|
style: TextStyle( |
|
|
|
fontSize: 12.sp, |
|
|
|
color: Colors.grey, |
|
|
|
), |
|
|
|
), |
|
|
|
|