重构录制页面,更新对话框逻辑,优化赛事信息粘贴功能,调整相关文本标签。
This commit is contained in:
234
lib/features/dialog/dialog-record.dart
Normal file
234
lib/features/dialog/dialog-record.dart
Normal file
@@ -0,0 +1,234 @@
|
|||||||
|
// ignore_for_file: file_names
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:recording_tool/gen/assets.gen.dart';
|
||||||
|
|
||||||
|
/// 录制页统一弹窗,支持单按钮和双按钮。
|
||||||
|
class RecordDialog extends StatelessWidget {
|
||||||
|
const RecordDialog({super.key, required this.title, required this.actions});
|
||||||
|
|
||||||
|
final String title;
|
||||||
|
final List<RecordDialogAction> actions;
|
||||||
|
|
||||||
|
static Future<void> showSingle(
|
||||||
|
BuildContext context, {
|
||||||
|
required String title,
|
||||||
|
required String buttonText,
|
||||||
|
VoidCallback? onPressed,
|
||||||
|
bool barrierDismissible = true,
|
||||||
|
}) {
|
||||||
|
return showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: barrierDismissible,
|
||||||
|
builder: (dialogContext) {
|
||||||
|
return RecordDialog(
|
||||||
|
title: title,
|
||||||
|
actions: [
|
||||||
|
RecordDialogAction.primary(
|
||||||
|
text: buttonText,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(dialogContext).pop();
|
||||||
|
onPressed?.call();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static Future<void> showDouble(
|
||||||
|
BuildContext context, {
|
||||||
|
required String title,
|
||||||
|
required String leftText,
|
||||||
|
required String rightText,
|
||||||
|
VoidCallback? onLeftPressed,
|
||||||
|
VoidCallback? onRightPressed,
|
||||||
|
bool barrierDismissible = false,
|
||||||
|
}) {
|
||||||
|
return showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
barrierDismissible: barrierDismissible,
|
||||||
|
builder: (dialogContext) {
|
||||||
|
return RecordDialog(
|
||||||
|
title: title,
|
||||||
|
actions: [
|
||||||
|
RecordDialogAction.secondary(
|
||||||
|
text: leftText,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(dialogContext).pop();
|
||||||
|
onLeftPressed?.call();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
RecordDialogAction.primary(
|
||||||
|
text: rightText,
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(dialogContext).pop();
|
||||||
|
onRightPressed?.call();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final actionWidgets = actions
|
||||||
|
.map((action) => Expanded(child: _RecordDialogButton(action: action)))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return Dialog(
|
||||||
|
elevation: 0,
|
||||||
|
backgroundColor: Colors.transparent,
|
||||||
|
insetPadding: EdgeInsets.symmetric(horizontal: 37.w),
|
||||||
|
child: ClipRRect(
|
||||||
|
clipBehavior: Clip.none,
|
||||||
|
|
||||||
|
borderRadius: BorderRadius.circular(18.r),
|
||||||
|
child: Container(
|
||||||
|
width: 315.w,
|
||||||
|
// height: 188.r,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.white,
|
||||||
|
|
||||||
|
borderRadius: BorderRadius.circular(18.r),
|
||||||
|
),
|
||||||
|
child: Stack(
|
||||||
|
clipBehavior: Clip.none,
|
||||||
|
children: [
|
||||||
|
Positioned(
|
||||||
|
top: -88.r,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: Image.asset(
|
||||||
|
Assets.images.imageDialogBg.path,
|
||||||
|
width: double.maxFinite,
|
||||||
|
height: 155.h,
|
||||||
|
fit: BoxFit.cover,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.fromLTRB(24.w, 44.h, 24.w, 26.h),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: const Color(0xFF333333),
|
||||||
|
fontSize: 19.sp,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
height: 1.35,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SizedBox(height: 22.h),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
for (
|
||||||
|
var index = 0;
|
||||||
|
index < actionWidgets.length;
|
||||||
|
index++
|
||||||
|
) ...[
|
||||||
|
if (index > 0) SizedBox(width: 16.w),
|
||||||
|
actionWidgets[index],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class RecordDialogAction {
|
||||||
|
const RecordDialogAction._({
|
||||||
|
required this.text,
|
||||||
|
required this.onPressed,
|
||||||
|
required this.isPrimary,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory RecordDialogAction.primary({
|
||||||
|
required String text,
|
||||||
|
required VoidCallback onPressed,
|
||||||
|
}) {
|
||||||
|
return RecordDialogAction._(
|
||||||
|
text: text,
|
||||||
|
onPressed: onPressed,
|
||||||
|
isPrimary: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory RecordDialogAction.secondary({
|
||||||
|
required String text,
|
||||||
|
required VoidCallback onPressed,
|
||||||
|
}) {
|
||||||
|
return RecordDialogAction._(
|
||||||
|
text: text,
|
||||||
|
onPressed: onPressed,
|
||||||
|
isPrimary: false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final String text;
|
||||||
|
final VoidCallback onPressed;
|
||||||
|
final bool isPrimary;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _RecordDialogButton extends StatelessWidget {
|
||||||
|
const _RecordDialogButton({required this.action});
|
||||||
|
|
||||||
|
final RecordDialogAction action;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final child = Center(
|
||||||
|
child: Text(
|
||||||
|
action.text,
|
||||||
|
style: TextStyle(
|
||||||
|
color: action.isPrimary ? Colors.white : const Color(0xFF333333),
|
||||||
|
fontSize: 18.sp,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return SizedBox(
|
||||||
|
height: 48.h,
|
||||||
|
child: TextButton(
|
||||||
|
onPressed: action.onPressed,
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(24.r),
|
||||||
|
),
|
||||||
|
backgroundColor: action.isPrimary ? null : const Color(0xFFF2F2F2),
|
||||||
|
),
|
||||||
|
child: action.isPrimary
|
||||||
|
? DecoratedBox(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: const LinearGradient(
|
||||||
|
colors: [Color(0xFF2F85FF), Color(0xFF5DCCF4)],
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.circular(24.r),
|
||||||
|
),
|
||||||
|
child: SizedBox.expand(child: child),
|
||||||
|
)
|
||||||
|
: child,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:recording_tool/core/platform/app_platform_info.dart';
|
import 'package:recording_tool/core/platform/app_platform_info.dart';
|
||||||
import 'package:recording_tool/core/platform/device_health_checker.dart';
|
import 'package:recording_tool/core/platform/device_health_checker.dart';
|
||||||
|
import 'package:recording_tool/features/dialog/dialog-record.dart';
|
||||||
import 'package:recording_tool/features/recording/model/model_recording.dart';
|
import 'package:recording_tool/features/recording/model/model_recording.dart';
|
||||||
import 'package:recording_tool/features/recording/platform/recording_platform.dart';
|
import 'package:recording_tool/features/recording/platform/recording_platform.dart';
|
||||||
import 'package:recording_tool/features/recording/utils/recording_display_name.dart';
|
import 'package:recording_tool/features/recording/utils/recording_display_name.dart';
|
||||||
@@ -46,7 +47,11 @@ class _RecordingPageState extends ConsumerState<RecordingPage> {
|
|||||||
final lines = DeviceHealthChecker.warningLines(snapshot);
|
final lines = DeviceHealthChecker.warningLines(snapshot);
|
||||||
if (lines.isEmpty) return;
|
if (lines.isEmpty) return;
|
||||||
|
|
||||||
await AppDialog.deviceHealthAlert(context, lines: lines);
|
await RecordDialog.showSingle(
|
||||||
|
context,
|
||||||
|
title: lines.join('\n'),
|
||||||
|
buttonText: '确定',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 页面启动:健康检查、读剪贴板、进入录制模式、准备相机会话
|
/// 页面启动:健康检查、读剪贴板、进入录制模式、准备相机会话
|
||||||
@@ -92,21 +97,24 @@ class _RecordingPageState extends ConsumerState<RecordingPage> {
|
|||||||
return '录制完成';
|
return '录制完成';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 从剪贴板粘贴赛事信息(与 header「粘贴赛事信息」一致)。
|
||||||
|
Future<void> _pasteEventInfo() async {
|
||||||
|
final result = await ref
|
||||||
|
.read(recordingViewModelProvider.notifier)
|
||||||
|
.getClipboardContent();
|
||||||
|
if (!mounted) return;
|
||||||
|
if (result != ClipboardReadResult.success) {
|
||||||
|
AppToast.show('无选手信息');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 无选手信息时弹窗提示
|
/// 无选手信息时弹窗提示
|
||||||
Future<void> _showNoPlayerInfoDialog() {
|
Future<void> _showNoPlayerInfoDialog() {
|
||||||
return showDialog<void>(
|
return RecordDialog.showSingle(
|
||||||
context: context,
|
context,
|
||||||
builder: (dialogContext) {
|
title: '无选手信息!',
|
||||||
return AlertDialog(
|
buttonText: '粘贴',
|
||||||
content: const Text('无选手信息'),
|
onPressed: _pasteEventInfo,
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.of(dialogContext).pop(),
|
|
||||||
child: const Text('确定'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,15 +216,7 @@ class _RecordingPageState extends ConsumerState<RecordingPage> {
|
|||||||
eventTitle: showClipboardInfo ? clipboard.title : null,
|
eventTitle: showClipboardInfo ? clipboard.title : null,
|
||||||
isRecording: state.isRecording,
|
isRecording: state.isRecording,
|
||||||
elapsedLabel: state.elapsedLabel,
|
elapsedLabel: state.elapsedLabel,
|
||||||
onPasteEventInfo: () async {
|
onPasteEventInfo: _pasteEventInfo,
|
||||||
final result = await ref
|
|
||||||
.read(recordingViewModelProvider.notifier)
|
|
||||||
.getClipboardContent();
|
|
||||||
if (!context.mounted) return;
|
|
||||||
if (result != ClipboardReadResult.success) {
|
|
||||||
AppToast.show('无赛事信息');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onClearEventInfo: _clearClipboardForNewRound,
|
onClearEventInfo: _clearClipboardForNewRound,
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
|
|||||||
@@ -133,9 +133,9 @@ class _HeaderPasteActions extends StatelessWidget {
|
|||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
// _HeaderActionButton(label: '模拟复制赛事信息', onPressed: onMockCopy),
|
_HeaderActionButton(label: '模拟复制赛事信息', onPressed: onMockCopy),
|
||||||
_HeaderActionButton(
|
_HeaderActionButton(
|
||||||
label: '粘贴赛事信息',
|
label: '粘贴选手信息',
|
||||||
onPressed: () => onPasteEventInfo(),
|
onPressed: () => onPasteEventInfo(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
import 'package:recording_tool/features/dialog/dialog-record.dart';
|
||||||
|
|
||||||
/// 录制结束并保存到相册后的后续操作弹窗。
|
/// 录制结束并保存到相册后的后续操作弹窗。
|
||||||
Future<void> showRecordingSavedDialog(
|
Future<void> showRecordingSavedDialog(
|
||||||
@@ -8,112 +8,13 @@ Future<void> showRecordingSavedDialog(
|
|||||||
required VoidCallback onContinueRound,
|
required VoidCallback onContinueRound,
|
||||||
required VoidCallback onRecordNewRound,
|
required VoidCallback onRecordNewRound,
|
||||||
}) {
|
}) {
|
||||||
return showDialog<void>(
|
return RecordDialog.showDouble(
|
||||||
context: context,
|
context,
|
||||||
|
title: '本轮比赛视频已保存到相册\n请选择后续录制信息',
|
||||||
|
leftText: '继续本轮',
|
||||||
|
rightText: '录制新轮',
|
||||||
|
onLeftPressed: onContinueRound,
|
||||||
|
onRightPressed: onRecordNewRound,
|
||||||
barrierDismissible: false,
|
barrierDismissible: false,
|
||||||
builder: (dialogContext) {
|
|
||||||
return RecordingSavedDialogWidget(
|
|
||||||
sessionTitle: sessionTitle,
|
|
||||||
onContinueRound: () {
|
|
||||||
Navigator.of(dialogContext).pop();
|
|
||||||
onContinueRound();
|
|
||||||
},
|
|
||||||
onRecordNewRound: () {
|
|
||||||
Navigator.of(dialogContext).pop();
|
|
||||||
onRecordNewRound();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class RecordingSavedDialogWidget extends StatelessWidget {
|
|
||||||
const RecordingSavedDialogWidget({
|
|
||||||
super.key,
|
|
||||||
required this.sessionTitle,
|
|
||||||
required this.onContinueRound,
|
|
||||||
required this.onRecordNewRound,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String sessionTitle;
|
|
||||||
final VoidCallback onContinueRound;
|
|
||||||
final VoidCallback onRecordNewRound;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Dialog(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(4.r),
|
|
||||||
side: const BorderSide(color: Colors.black, width: 1),
|
|
||||||
),
|
|
||||||
insetPadding: EdgeInsets.symmetric(horizontal: 32.w),
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.fromLTRB(20.w, 20.h, 20.w, 16.h),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
sessionTitle,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 15.sp,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
color: Colors.black87,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
SizedBox(height: 16.h),
|
|
||||||
Text(
|
|
||||||
'本轮比赛视频已保存到相册',
|
|
||||||
style: TextStyle(fontSize: 14.sp, color: Colors.black87),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
SizedBox(height: 8.h),
|
|
||||||
SizedBox(height: 20.h),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: _RecordingDialogActionButton(
|
|
||||||
label: '继续本轮',
|
|
||||||
onPressed: onContinueRound,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SizedBox(width: 12.w),
|
|
||||||
Expanded(
|
|
||||||
child: _RecordingDialogActionButton(
|
|
||||||
label: '录制新轮',
|
|
||||||
onPressed: onRecordNewRound,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _RecordingDialogActionButton extends StatelessWidget {
|
|
||||||
const _RecordingDialogActionButton({
|
|
||||||
required this.label,
|
|
||||||
required this.onPressed,
|
|
||||||
});
|
|
||||||
|
|
||||||
final String label;
|
|
||||||
final VoidCallback onPressed;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return TextButton(
|
|
||||||
onPressed: onPressed,
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
backgroundColor: const Color(0xFFE8E8E8),
|
|
||||||
foregroundColor: Colors.black87,
|
|
||||||
padding: EdgeInsets.symmetric(vertical: 10.h),
|
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6.r)),
|
|
||||||
),
|
|
||||||
child: Text(label, style: TextStyle(fontSize: 14.sp)),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
130
test/features/dialog/record_dialog_test.dart
Normal file
130
test/features/dialog/record_dialog_test.dart
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_screenutil/flutter_screenutil.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:recording_tool/features/dialog/dialog-record.dart';
|
||||||
|
import 'package:recording_tool/features/recording/widgets/widget_recording_saved_dialog.dart';
|
||||||
|
import 'package:recording_tool/gen/assets.gen.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
Future<void> pumpDialogHost(WidgetTester tester, Widget child) async {
|
||||||
|
await tester.pumpWidget(
|
||||||
|
ScreenUtilInit(
|
||||||
|
designSize: const Size(375, 812),
|
||||||
|
builder: (context, _) {
|
||||||
|
return MaterialApp(home: Scaffold(body: child));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
testWidgets('single button dialog shows configured content and closes', (
|
||||||
|
tester,
|
||||||
|
) async {
|
||||||
|
var tapped = false;
|
||||||
|
|
||||||
|
await pumpDialogHost(
|
||||||
|
tester,
|
||||||
|
Builder(
|
||||||
|
builder: (context) {
|
||||||
|
return TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
RecordDialog.showSingle(
|
||||||
|
context,
|
||||||
|
title: '无选手信息!',
|
||||||
|
buttonText: '粘贴',
|
||||||
|
onPressed: () => tapped = true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('show'),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.tap(find.text('show'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.byType(Image), findsOneWidget);
|
||||||
|
expect(find.image(AssetImage(Assets.images.imageDialogBg.path)), findsOne);
|
||||||
|
expect(find.text('无选手信息!'), findsOneWidget);
|
||||||
|
expect(find.text('粘贴'), findsOneWidget);
|
||||||
|
|
||||||
|
await tester.tap(find.text('粘贴'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(tapped, isTrue);
|
||||||
|
expect(find.text('无选手信息!'), findsNothing);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('double button dialog dispatches each action', (tester) async {
|
||||||
|
var leftTapped = false;
|
||||||
|
var rightTapped = false;
|
||||||
|
|
||||||
|
await pumpDialogHost(
|
||||||
|
tester,
|
||||||
|
Builder(
|
||||||
|
builder: (context) {
|
||||||
|
return TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
RecordDialog.showDouble(
|
||||||
|
context,
|
||||||
|
title: '本轮比赛视频已保存到相册\n请选择后续录制信息',
|
||||||
|
leftText: '继续本轮',
|
||||||
|
rightText: '录制新轮',
|
||||||
|
onLeftPressed: () => leftTapped = true,
|
||||||
|
onRightPressed: () => rightTapped = true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('show'),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.tap(find.text('show'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.tap(find.text('继续本轮'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(leftTapped, isTrue);
|
||||||
|
expect(rightTapped, isFalse);
|
||||||
|
|
||||||
|
await tester.tap(find.text('show'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.tap(find.text('录制新轮'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(rightTapped, isTrue);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('recording saved dialog follows design title only', (
|
||||||
|
tester,
|
||||||
|
) async {
|
||||||
|
await pumpDialogHost(
|
||||||
|
tester,
|
||||||
|
Builder(
|
||||||
|
builder: (context) {
|
||||||
|
return TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
showRecordingSavedDialog(
|
||||||
|
context,
|
||||||
|
sessionTitle: '王东方 丨李想 空中格斗赛',
|
||||||
|
onContinueRound: () {},
|
||||||
|
onRecordNewRound: () {},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('show'),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
await tester.tap(find.text('show'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.text('王东方 丨李想 空中格斗赛'), findsNothing);
|
||||||
|
expect(find.text('本轮比赛视频已保存到相册\n请选择后续录制信息'), findsOneWidget);
|
||||||
|
expect(find.text('继续本轮'), findsOneWidget);
|
||||||
|
expect(find.text('录制新轮'), findsOneWidget);
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -34,7 +34,7 @@ void main() {
|
|||||||
await tester.pumpWidget(const ProviderScope(child: FlutterTemplateApp()));
|
await tester.pumpWidget(const ProviderScope(child: FlutterTemplateApp()));
|
||||||
await tester.pump();
|
await tester.pump();
|
||||||
await tester.pump(const Duration(milliseconds: 500));
|
await tester.pump(const Duration(milliseconds: 500));
|
||||||
await tester.pumpAndSettle();
|
await tester.pump(const Duration(seconds: 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
testWidgets('recording app renders recording page', (tester) async {
|
testWidgets('recording app renders recording page', (tester) async {
|
||||||
@@ -66,7 +66,7 @@ void main() {
|
|||||||
|
|
||||||
clipboardText = validClipboardText;
|
clipboardText = validClipboardText;
|
||||||
await tester.tap(find.text('粘贴赛事信息'));
|
await tester.tap(find.text('粘贴赛事信息'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pump(const Duration(milliseconds: 500));
|
||||||
|
|
||||||
expect(find.text('王东方 丨李想 空中格斗赛'), findsOneWidget);
|
expect(find.text('王东方 丨李想 空中格斗赛'), findsOneWidget);
|
||||||
expect(find.text('粘贴赛事信息'), findsNothing);
|
expect(find.text('粘贴赛事信息'), findsNothing);
|
||||||
@@ -84,7 +84,7 @@ void main() {
|
|||||||
await tester.pump();
|
await tester.pump();
|
||||||
|
|
||||||
expect(find.text('王东方 丨李想 空中格斗赛'), findsNothing);
|
expect(find.text('王东方 丨李想 空中格斗赛'), findsNothing);
|
||||||
expect(find.text('无赛事信息'), findsOneWidget);
|
expect(find.text('无选手信息'), findsOneWidget);
|
||||||
|
|
||||||
await tester.pump(const Duration(seconds: 2));
|
await tester.pump(const Duration(seconds: 2));
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user