merge: 合并 K86.15 评论发布成功提示
This commit is contained in:
commit
c3e6e02e47
10 files changed
+138
-47
No files matched your search
@@ -211,6 +211,7 @@
|
|||||||
"writeComment": "Write a comment",
|
"writeComment": "Write a comment",
|
||||||
"commentLoginHint": "Sign in to comment",
|
"commentLoginHint": "Sign in to comment",
|
||||||
"postComment": "Post",
|
"postComment": "Post",
|
||||||
|
"commentPostSuccess": "Comment posted",
|
||||||
"loadMore": "Load more",
|
"loadMore": "Load more",
|
||||||
"commentsLoadFailed": "Comments could not be loaded.",
|
"commentsLoadFailed": "Comments could not be loaded.",
|
||||||
"commentPostFailed": "Could not post your comment.",
|
"commentPostFailed": "Could not post your comment.",
|
||||||
|
|||||||
@@ -185,6 +185,7 @@
|
|||||||
"writeComment": "Tulis komentar",
|
"writeComment": "Tulis komentar",
|
||||||
"commentLoginHint": "Masuk untuk berkomentar",
|
"commentLoginHint": "Masuk untuk berkomentar",
|
||||||
"postComment": "Kirim",
|
"postComment": "Kirim",
|
||||||
|
"commentPostSuccess": "Komentar terkirim",
|
||||||
"loadMore": "Muat lebih banyak",
|
"loadMore": "Muat lebih banyak",
|
||||||
"commentsLoadFailed": "Komentar tidak dapat dimuat.",
|
"commentsLoadFailed": "Komentar tidak dapat dimuat.",
|
||||||
"commentPostFailed": "Komentar tidak dapat dikirim.",
|
"commentPostFailed": "Komentar tidak dapat dikirim.",
|
||||||
|
|||||||
@@ -946,6 +946,12 @@ abstract class AppLocalizations {
|
|||||||
/// **'Post'**
|
/// **'Post'**
|
||||||
String get postComment;
|
String get postComment;
|
||||||
|
|
||||||
|
/// No description provided for @commentPostSuccess.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Comment posted'**
|
||||||
|
String get commentPostSuccess;
|
||||||
|
|
||||||
/// No description provided for @loadMore.
|
/// No description provided for @loadMore.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|||||||
@@ -462,6 +462,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get postComment => 'Post';
|
String get postComment => 'Post';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get commentPostSuccess => 'Comment posted';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get loadMore => 'Load more';
|
String get loadMore => 'Load more';
|
||||||
|
|
||||||
|
|||||||
@@ -463,6 +463,9 @@ class AppLocalizationsId extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get postComment => 'Kirim';
|
String get postComment => 'Kirim';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get commentPostSuccess => 'Komentar terkirim';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get loadMore => 'Muat lebih banyak';
|
String get loadMore => 'Muat lebih banyak';
|
||||||
|
|
||||||
|
|||||||
@@ -457,6 +457,9 @@ class AppLocalizationsZh extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get postComment => '发布';
|
String get postComment => '发布';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get commentPostSuccess => '发表成功';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get loadMore => '加载更多';
|
String get loadMore => '加载更多';
|
||||||
|
|
||||||
|
|||||||
@@ -185,6 +185,7 @@
|
|||||||
"writeComment": "写评论",
|
"writeComment": "写评论",
|
||||||
"commentLoginHint": "登录后参与评论",
|
"commentLoginHint": "登录后参与评论",
|
||||||
"postComment": "发布",
|
"postComment": "发布",
|
||||||
|
"commentPostSuccess": "发表成功",
|
||||||
"loadMore": "加载更多",
|
"loadMore": "加载更多",
|
||||||
"commentsLoadFailed": "评论加载失败,请重试。",
|
"commentsLoadFailed": "评论加载失败,请重试。",
|
||||||
"commentPostFailed": "评论发布失败,请重试。",
|
"commentPostFailed": "评论发布失败,请重试。",
|
||||||
|
|||||||
@@ -129,6 +129,7 @@ class _CommentComposerSheetState extends State<CommentComposerSheet>
|
|||||||
);
|
);
|
||||||
if (!mounted) return;
|
if (!mounted) return;
|
||||||
if (result.isSuccess) {
|
if (result.isSuccess) {
|
||||||
|
_input.clear();
|
||||||
_closing = true;
|
_closing = true;
|
||||||
Navigator.pop(context, true);
|
Navigator.pop(context, true);
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ class DramaCommentsSheet extends StatefulWidget {
|
|||||||
class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
|
class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
|
||||||
late final CommentRepository _comments;
|
late final CommentRepository _comments;
|
||||||
late final CommentController _controller;
|
late final CommentController _controller;
|
||||||
|
final _messengerKey = GlobalKey<ScaffoldMessengerState>();
|
||||||
int? _serverCount;
|
int? _serverCount;
|
||||||
int _countRequest = 0;
|
int _countRequest = 0;
|
||||||
|
|
||||||
@@ -91,65 +92,110 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
|
|||||||
builder: (_) =>
|
builder: (_) =>
|
||||||
CommentComposerSheet(controller: _controller, replyTo: replyTo),
|
CommentComposerSheet(controller: _controller, replyTo: replyTo),
|
||||||
);
|
);
|
||||||
if (published == true && mounted) await _refreshCount();
|
if (published == true && mounted) {
|
||||||
|
_showPostSuccess();
|
||||||
|
await _refreshCount();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleDismissLayerTap() {
|
void _handleDismissLayerTap() {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
void _showPostSuccess() {
|
||||||
Widget build(BuildContext context) {
|
final messenger = _messengerKey.currentState;
|
||||||
|
if (messenger == null) return;
|
||||||
|
final l10n = AppLocalizations.of(context)!;
|
||||||
|
messenger
|
||||||
|
..hideCurrentSnackBar()
|
||||||
|
..showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
key: const Key('comment-post-success-snackbar'),
|
||||||
|
content: Text(
|
||||||
|
l10n.commentPostSuccess,
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
behavior: SnackBarBehavior.floating,
|
||||||
|
duration: const Duration(milliseconds: 1500),
|
||||||
|
backgroundColor: AppColors.ink,
|
||||||
|
elevation: 6,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(10),
|
||||||
|
),
|
||||||
|
margin: EdgeInsets.fromLTRB(16, 0, 16, _sheetHeight(context) + 12),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
double _sheetHeight(BuildContext context) {
|
||||||
final screenHeight = MediaQuery.sizeOf(context).height;
|
final screenHeight = MediaQuery.sizeOf(context).height;
|
||||||
final topSafeArea = MediaQuery.paddingOf(context).top;
|
final topSafeArea = MediaQuery.paddingOf(context).top;
|
||||||
final halfHeight = (screenHeight * 0.5).roundToDouble();
|
final halfHeight = (screenHeight * 0.5).roundToDouble();
|
||||||
final maxHeight = math.max(0.0, screenHeight - topSafeArea);
|
final maxHeight = math.max(0.0, screenHeight - topSafeArea);
|
||||||
final sheetHeight = math.min(halfHeight, maxHeight);
|
return math.min(halfHeight, maxHeight);
|
||||||
return Stack(
|
}
|
||||||
fit: StackFit.expand,
|
|
||||||
children: [
|
@override
|
||||||
Positioned.fill(
|
Widget build(BuildContext context) {
|
||||||
child: GestureDetector(
|
final sheetHeight = _sheetHeight(context);
|
||||||
key: const Key('player-comments-dismiss-layer'),
|
return ScaffoldMessenger(
|
||||||
behavior: HitTestBehavior.opaque,
|
key: _messengerKey,
|
||||||
onTap: _handleDismissLayerTap,
|
child: Scaffold(
|
||||||
),
|
backgroundColor: Colors.transparent,
|
||||||
),
|
resizeToAvoidBottomInset: false,
|
||||||
Align(
|
body: Stack(
|
||||||
alignment: Alignment.bottomCenter,
|
fit: StackFit.expand,
|
||||||
child: GestureDetector(
|
children: [
|
||||||
behavior: HitTestBehavior.opaque,
|
Positioned.fill(
|
||||||
onTap: () {},
|
child: GestureDetector(
|
||||||
child: KeyedSubtree(
|
key: const Key('player-comments-dismiss-layer'),
|
||||||
key: const Key('player-comments-sheet'),
|
behavior: HitTestBehavior.opaque,
|
||||||
child: SizedBox(
|
onTap: _handleDismissLayerTap,
|
||||||
key: const Key('comment-sheet-constraints'),
|
),
|
||||||
height: sheetHeight,
|
),
|
||||||
child: Container(
|
Align(
|
||||||
decoration: const BoxDecoration(
|
alignment: Alignment.bottomCenter,
|
||||||
color: AppColors.card,
|
child: GestureDetector(
|
||||||
borderRadius: BorderRadius.vertical(
|
behavior: HitTestBehavior.opaque,
|
||||||
top: Radius.circular(_sheetRadius),
|
onTap: () {},
|
||||||
),
|
child: KeyedSubtree(
|
||||||
),
|
key: const Key('player-comments-sheet'),
|
||||||
child: SafeArea(
|
child: SizedBox(
|
||||||
top: false,
|
key: const Key('comment-sheet-constraints'),
|
||||||
child: ListenableBuilder(
|
height: sheetHeight,
|
||||||
listenable: _controller,
|
child: Container(
|
||||||
builder: (context, _) {
|
decoration: const BoxDecoration(
|
||||||
return Padding(
|
color: AppColors.card,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
borderRadius: BorderRadius.vertical(
|
||||||
child: _content(context),
|
top: Radius.circular(_sheetRadius),
|
||||||
);
|
),
|
||||||
},
|
),
|
||||||
|
child: SafeArea(
|
||||||
|
top: false,
|
||||||
|
child: ListenableBuilder(
|
||||||
|
listenable: _controller,
|
||||||
|
builder: (context, _) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16,
|
||||||
|
),
|
||||||
|
child: _content(context),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -234,7 +234,11 @@ void main() {
|
|||||||
publishError: const ApiException(400, '评论包含敏感词'),
|
publishError: const ApiException(400, '评论包含敏感词'),
|
||||||
);
|
);
|
||||||
|
|
||||||
await _pumpSheet(tester, repository: repository);
|
await _pumpSheet(
|
||||||
|
tester,
|
||||||
|
repository: repository,
|
||||||
|
locale: const Locale('zh'),
|
||||||
|
);
|
||||||
await tester.tap(find.byKey(const Key('comment-input-placeholder')));
|
await tester.tap(find.byKey(const Key('comment-input-placeholder')));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
await tester.enterText(
|
await tester.enterText(
|
||||||
@@ -250,6 +254,7 @@ void main() {
|
|||||||
find.byKey(const Key('comment-composer-input')),
|
find.byKey(const Key('comment-composer-input')),
|
||||||
);
|
);
|
||||||
expect(field.controller?.text, 'blocked text');
|
expect(field.controller?.text, 'blocked text');
|
||||||
|
expect(find.text('发表成功'), findsNothing);
|
||||||
// 发送失败时保留输入与焦点,用户可以直接改完再发。
|
// 发送失败时保留输入与焦点,用户可以直接改完再发。
|
||||||
expect(field.focusNode?.hasFocus, isTrue);
|
expect(field.focusNode?.hasFocus, isTrue);
|
||||||
},
|
},
|
||||||
@@ -263,7 +268,11 @@ void main() {
|
|||||||
countResult: 1,
|
countResult: 1,
|
||||||
);
|
);
|
||||||
|
|
||||||
await _pumpSheet(tester, repository: repository);
|
await _pumpSheet(
|
||||||
|
tester,
|
||||||
|
repository: repository,
|
||||||
|
locale: const Locale('zh'),
|
||||||
|
);
|
||||||
final input = find.byKey(const Key('comment-composer-input'));
|
final input = find.byKey(const Key('comment-composer-input'));
|
||||||
tester.view.viewInsets = const FakeViewPadding(bottom: 180);
|
tester.view.viewInsets = const FakeViewPadding(bottom: 180);
|
||||||
await tester.tap(find.byKey(const Key('comment-input-placeholder')));
|
await tester.tap(find.byKey(const Key('comment-input-placeholder')));
|
||||||
@@ -278,9 +287,25 @@ void main() {
|
|||||||
isNotNull,
|
isNotNull,
|
||||||
);
|
);
|
||||||
await tester.tap(find.byKey(const Key('comment-composer-post')));
|
await tester.tap(find.byKey(const Key('comment-composer-post')));
|
||||||
await tester.pumpAndSettle();
|
await tester.pump();
|
||||||
|
await tester.pump(const Duration(milliseconds: 500));
|
||||||
|
|
||||||
expect(find.byKey(const Key('comment-composer-sheet')), findsNothing);
|
expect(find.byKey(const Key('comment-composer-sheet')), findsNothing);
|
||||||
|
final successSnackBar = find.byKey(
|
||||||
|
const Key('comment-post-success-snackbar'),
|
||||||
|
);
|
||||||
|
expect(successSnackBar, findsOneWidget);
|
||||||
|
expect(find.text('发表成功'), findsOneWidget);
|
||||||
|
final snackBar = tester.widget<SnackBar>(successSnackBar);
|
||||||
|
expect(snackBar.action, isNull);
|
||||||
|
expect(snackBar.behavior, SnackBarBehavior.floating);
|
||||||
|
expect(snackBar.duration, const Duration(milliseconds: 1500));
|
||||||
|
expect(
|
||||||
|
tester.getRect(find.text('发表成功')).bottom,
|
||||||
|
lessThanOrEqualTo(
|
||||||
|
tester.getRect(find.byKey(const Key('player-comments-sheet'))).top,
|
||||||
|
),
|
||||||
|
);
|
||||||
expect(find.byKey(const Key('comment-list')), findsOneWidget);
|
expect(find.byKey(const Key('comment-list')), findsOneWidget);
|
||||||
expect(find.byKey(const Key('comment-count-label')), findsOneWidget);
|
expect(find.byKey(const Key('comment-count-label')), findsOneWidget);
|
||||||
expect(find.byKey(const Key('comment-input-placeholder')), findsOneWidget);
|
expect(find.byKey(const Key('comment-input-placeholder')), findsOneWidget);
|
||||||
@@ -669,6 +694,7 @@ Future<AuthController> _pumpSheet(
|
|||||||
WidgetTester tester, {
|
WidgetTester tester, {
|
||||||
required FakeCommentRepository repository,
|
required FakeCommentRepository repository,
|
||||||
FakeHaptics? haptics,
|
FakeHaptics? haptics,
|
||||||
|
Locale locale = const Locale('en'),
|
||||||
}) async {
|
}) async {
|
||||||
final auth = await _auth();
|
final auth = await _auth();
|
||||||
await tester.pumpWidget(
|
await tester.pumpWidget(
|
||||||
@@ -682,7 +708,7 @@ Future<AuthController> _pumpSheet(
|
|||||||
Provider<Haptics>.value(value: haptics ?? FakeHaptics()),
|
Provider<Haptics>.value(value: haptics ?? FakeHaptics()),
|
||||||
],
|
],
|
||||||
child: MaterialApp(
|
child: MaterialApp(
|
||||||
locale: const Locale('en'),
|
locale: locale,
|
||||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||||
supportedLocales: AppLocalizations.supportedLocales,
|
supportedLocales: AppLocalizations.supportedLocales,
|
||||||
initialRoute: '/comments',
|
initialRoute: '/comments',
|
||||||
|
|||||||
Reference in new issue
Block a user