You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

195 lines
7.7 KiB

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import '../../controllers/translation_controller.dart';
import '../../models/translation_models.dart';
import '../dialogs/translation_long_press_menu.dart';
class TranslationItemWidget extends GetView<TranslationController> {
// 传入的翻译条目
final TranslationItem item;
// 传入用于控制操作按钮显隐的时间戳状态
final Rx<DateTime?> activeActionTimestamp;
// 点击气泡时切换操作按钮显隐
final void Function(TranslationItem item) onToggleActionItem;
// 长按时弹出菜单(需要上下文、暗色模式、手势详情、条目)
final void Function(
BuildContext context,
bool isDarkMode,
LongPressStartDetails details,
TranslationItem item,
) onLongPressStart;
// 删除按钮点击时的确认对话框
final void Function(TranslationItem item) onDeleteItemConfirm;
const TranslationItemWidget({
Key? key,
required this.item,
required this.activeActionTimestamp,
required this.onToggleActionItem,
required this.onLongPressStart,
required this.onDeleteItemConfirm,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final isDarkMode = Theme.of(context).brightness == Brightness.dark;
// 定义自适应颜色(与原实现保持一致)
final selfColor =
isDarkMode ? Colors.blue[800]!.withOpacity(0.15) : Colors.blue[50]!;
final otherColor =
isDarkMode ? Colors.green[800]!.withOpacity(0.15) : Colors.green[50]!;
// 判断是否是己方的翻译项(依据控制器当前源语言)
final bool isSelf =
item.sourceLanguageCode == controller.sourceLanguageCode.value;
// 新增:通话模式标记,用于控制右侧显示与隐藏中间态
final bool isCallMode = controller.currentMode.value == 'call';
return GestureDetector(
onTap: () => onToggleActionItem(item), // 触碰气泡时切换按钮显隐
onLongPressStart: (details) =>
onLongPressStart(context, isDarkMode, details, item),
child: Align(
alignment: isCallMode
? (isSelf ? Alignment.centerLeft : Alignment.centerRight)
: item.isIntermediate
? Alignment.center
: (isSelf ? Alignment.centerLeft : Alignment.centerRight),
child: Container(
margin: EdgeInsets.only(bottom: 8.h),
padding: EdgeInsets.all(12.w),
constraints: BoxConstraints(maxWidth: 0.8.sw, minWidth: 0.35.sw),
decoration: BoxDecoration(
color: item.isIntermediate
? Colors.grey.withOpacity(isDarkMode ? 0.15 : 0.1) // 中间结果
: (isSelf ? selfColor : otherColor), // 自己 / 对方
borderRadius: BorderRadius.circular(12.r),
border: Border.all(
color: item.isIntermediate
? Colors.grey.withOpacity(isDarkMode ? 0.3 : 0.2)
: Colors.transparent,
width: 1,
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// 源文本
Text(
item.sourceText,
style: TextStyle(
fontSize: 16.sp,
color: Theme.of(context).textTheme.bodyLarge?.color,
),
),
SizedBox(height: 8.h),
// 分隔线 + 译文
Container(
padding: EdgeInsets.only(top: 8.h),
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: item.isIntermediate
? (isDarkMode
? Colors.grey[400]!.withOpacity(0.15)
: Colors.grey[400]!.withOpacity(0.25))
: (isSelf
? (isDarkMode
? Colors.blue[300]!.withOpacity(0.15)
: Colors.blue[300]!.withOpacity(0.25))
: (isDarkMode
? Colors.green[300]!.withOpacity(0.15)
: Colors.green[300]!.withOpacity(0.25))),
width: 1,
),
),
),
child: Text(
item.translatedText,
style: TextStyle(
fontSize: 16.sp,
color: Theme.of(context).textTheme.bodyMedium?.color,
fontWeight: FontWeight.w500,
),
),
),
// 操作按钮:复制 / 播放 / 删除(仅非中间态且显隐状态为激活时显示)
Obx(() {
final bool isActive = activeActionTimestamp.value
?.isAtSameMomentAs(item.timestamp) ??
false;
if (!item.isIntermediate && isActive) {
return Column(
children: [
SizedBox(height: 8.h),
Row(
mainAxisSize: MainAxisSize.min,
children: [
// 复制按钮(复用长按菜单的复制逻辑)
GestureDetector(
onTap: () =>
TranslationLongPressMenu.copyTranslationItem(
item),
child: Container(
padding: EdgeInsets.all(4.w),
child: Tooltip(
message: 'copy'.tr, // 复制
child: Icon(
Icons.copy,
size: 20.sp,
color: Theme.of(context).colorScheme.primary,
),
),
),
),
SizedBox(width: 8.w),
// 播放按钮(调用控制器原有方法)
GestureDetector(
onTap: () => controller.playTranslationItem(item),
child: Container(
padding: EdgeInsets.all(4.w),
child: Icon(
Icons.volume_up,
size: 20.sp,
color: Theme.of(context).colorScheme.primary,
),
),
),
SizedBox(width: 8.w),
// 删除按钮(弹出确认)
GestureDetector(
onTap: () => onDeleteItemConfirm(item),
child: Container(
padding: EdgeInsets.all(4.w),
child: Tooltip(
message: 'delete'.tr, // 删除
child: Icon(
Icons.delete_outline,
size: 20.sp,
color: Colors.grey[500],
),
),
),
),
],
)
],
);
} else {
return const SizedBox.shrink();
}
}),
],
),
),
),
);
}
}