fix(player): 评论成功提示改黑色浮层并去除输入弹窗遮罩
This commit is contained in:
1 parent
c3e6e02e47
commit
5d459dd08a
3 files changed
+274
-200
No files matched your search
@@ -155,130 +155,160 @@ class _CommentComposerSheetState extends State<CommentComposerSheet>
|
||||
final canPost = signedIn && hasContent && !widget.controller.submitting;
|
||||
final multiline = _input.text.contains('\n');
|
||||
|
||||
return AnimatedPadding(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.easeOut,
|
||||
padding: EdgeInsets.only(bottom: keyboardHeight),
|
||||
child: SizedBox(
|
||||
key: const Key('comment-composer-sheet'),
|
||||
width: double.infinity,
|
||||
child: Material(
|
||||
color: AppColors.card,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(_sheetRadius),
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: GestureDetector(
|
||||
key: const Key('comment-composer-dismiss-layer'),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () {
|
||||
_inputFocus.unfocus();
|
||||
_closeSheet();
|
||||
},
|
||||
),
|
||||
child: SafeArea(
|
||||
top: false,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 12),
|
||||
child: TextFieldTapRegion(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
if (widget.replyTo != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: Text(
|
||||
l10n.replyingTo(
|
||||
widget.replyTo!.nickname.isEmpty
|
||||
? l10n.anonymousUser
|
||||
: widget.replyTo!.nickname,
|
||||
),
|
||||
style: const TextStyle(
|
||||
color: AppColors.muted,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.commentInput,
|
||||
borderRadius: BorderRadius.circular(_inputRadius),
|
||||
),
|
||||
child: TextField(
|
||||
key: const Key('comment-composer-input'),
|
||||
autofocus: true,
|
||||
controller: _input,
|
||||
focusNode: _inputFocus,
|
||||
readOnly: !signedIn,
|
||||
canRequestFocus: signedIn,
|
||||
minLines: 1,
|
||||
maxLines: 4,
|
||||
maxLength: _maxCommentLength,
|
||||
textAlignVertical: multiline
|
||||
? TextAlignVertical.top
|
||||
: TextAlignVertical.center,
|
||||
style: TextStyle(
|
||||
color: AppColors.cream,
|
||||
fontSize: 15,
|
||||
height: multiline ? 1.4 : null,
|
||||
),
|
||||
cursorColor: AppColors.blue,
|
||||
decoration: InputDecoration(
|
||||
hintText: signedIn
|
||||
? l10n.writeComment
|
||||
: l10n.commentLoginHint,
|
||||
hintStyle: const TextStyle(
|
||||
color: AppColors.muted,
|
||||
fontSize: 14,
|
||||
),
|
||||
counterText: '',
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 12,
|
||||
),
|
||||
border: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
),
|
||||
onTap: signedIn ? null : _authenticate,
|
||||
onTapOutside: (_) {
|
||||
_inputFocus.unfocus();
|
||||
_closeSheet();
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: SizedBox(
|
||||
height: _postButtonHeight,
|
||||
child: TextButton(
|
||||
key: const Key('comment-composer-post'),
|
||||
onPressed: canPost ? _submit : null,
|
||||
style: TextButton.styleFrom(
|
||||
minimumSize: const Size(0, _postButtonHeight),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||
backgroundColor: hasContent
|
||||
? AppColors.blue.withValues(alpha: 0.12)
|
||||
: AppColors.raised,
|
||||
foregroundColor: AppColors.blue,
|
||||
disabledForegroundColor: AppColors.muted,
|
||||
disabledBackgroundColor: AppColors.raised,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: AnimatedPadding(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
curve: Curves.easeOut,
|
||||
padding: EdgeInsets.only(bottom: keyboardHeight),
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () {},
|
||||
child: SizedBox(
|
||||
key: const Key('comment-composer-sheet'),
|
||||
width: double.infinity,
|
||||
child: Material(
|
||||
color: AppColors.card,
|
||||
clipBehavior: Clip.antiAlias,
|
||||
borderRadius: const BorderRadius.vertical(
|
||||
top: Radius.circular(_sheetRadius),
|
||||
),
|
||||
child: SafeArea(
|
||||
top: false,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 12),
|
||||
child: TextFieldTapRegion(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
if (widget.replyTo != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8),
|
||||
child: Text(
|
||||
l10n.replyingTo(
|
||||
widget.replyTo!.nickname.isEmpty
|
||||
? l10n.anonymousUser
|
||||
: widget.replyTo!.nickname,
|
||||
),
|
||||
style: const TextStyle(
|
||||
color: AppColors.muted,
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: AppColors.commentInput,
|
||||
borderRadius: BorderRadius.circular(
|
||||
_inputRadius,
|
||||
),
|
||||
),
|
||||
child: TextField(
|
||||
key: const Key('comment-composer-input'),
|
||||
autofocus: true,
|
||||
controller: _input,
|
||||
focusNode: _inputFocus,
|
||||
readOnly: !signedIn,
|
||||
canRequestFocus: signedIn,
|
||||
minLines: 1,
|
||||
maxLines: 4,
|
||||
maxLength: _maxCommentLength,
|
||||
textAlignVertical: multiline
|
||||
? TextAlignVertical.top
|
||||
: TextAlignVertical.center,
|
||||
style: TextStyle(
|
||||
color: AppColors.cream,
|
||||
fontSize: 15,
|
||||
height: multiline ? 1.4 : null,
|
||||
),
|
||||
cursorColor: AppColors.blue,
|
||||
decoration: InputDecoration(
|
||||
hintText: signedIn
|
||||
? l10n.writeComment
|
||||
: l10n.commentLoginHint,
|
||||
hintStyle: const TextStyle(
|
||||
color: AppColors.muted,
|
||||
fontSize: 14,
|
||||
),
|
||||
counterText: '',
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 12,
|
||||
),
|
||||
border: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
),
|
||||
onTap: signedIn ? null : _authenticate,
|
||||
onTapOutside: (_) {
|
||||
_inputFocus.unfocus();
|
||||
_closeSheet();
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
l10n.postComment,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
const SizedBox(height: 12),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: SizedBox(
|
||||
height: _postButtonHeight,
|
||||
child: TextButton(
|
||||
key: const Key('comment-composer-post'),
|
||||
onPressed: canPost ? _submit : null,
|
||||
style: TextButton.styleFrom(
|
||||
minimumSize: const Size(
|
||||
0,
|
||||
_postButtonHeight,
|
||||
),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
),
|
||||
tapTargetSize:
|
||||
MaterialTapTargetSize.shrinkWrap,
|
||||
backgroundColor: hasContent
|
||||
? AppColors.blue.withValues(alpha: 0.12)
|
||||
: AppColors.raised,
|
||||
foregroundColor: AppColors.blue,
|
||||
disabledForegroundColor: AppColors.muted,
|
||||
disabledBackgroundColor: AppColors.raised,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
l10n.postComment,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,8 @@ class DramaCommentsSheet extends StatefulWidget {
|
||||
class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
|
||||
late final CommentRepository _comments;
|
||||
late final CommentController _controller;
|
||||
final _messengerKey = GlobalKey<ScaffoldMessengerState>();
|
||||
OverlayEntry? _successOverlay;
|
||||
Timer? _successOverlayTimer;
|
||||
int? _serverCount;
|
||||
int _countRequest = 0;
|
||||
|
||||
@@ -60,6 +61,8 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_successOverlayTimer?.cancel();
|
||||
_successOverlay?.remove();
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
@@ -88,6 +91,7 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
|
||||
isScrollControlled: true,
|
||||
isDismissible: true,
|
||||
backgroundColor: Colors.transparent,
|
||||
barrierColor: Colors.transparent,
|
||||
showDragHandle: false,
|
||||
builder: (_) =>
|
||||
CommentComposerSheet(controller: _controller, replyTo: replyTo),
|
||||
@@ -103,32 +107,19 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
|
||||
}
|
||||
|
||||
void _showPostSuccess() {
|
||||
final messenger = _messengerKey.currentState;
|
||||
if (messenger == null) return;
|
||||
_successOverlayTimer?.cancel();
|
||||
_successOverlay?.remove();
|
||||
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),
|
||||
),
|
||||
);
|
||||
final entry = OverlayEntry(
|
||||
builder: (_) =>
|
||||
_CommentPostSuccessOverlay(message: l10n.commentPostSuccess),
|
||||
);
|
||||
_successOverlay = entry;
|
||||
Overlay.of(context, rootOverlay: true).insert(entry);
|
||||
_successOverlayTimer = Timer(const Duration(milliseconds: 1200), () {
|
||||
if (entry.mounted) entry.remove();
|
||||
if (identical(_successOverlay, entry)) _successOverlay = null;
|
||||
});
|
||||
}
|
||||
|
||||
double _sheetHeight(BuildContext context) {
|
||||
@@ -142,60 +133,51 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final sheetHeight = _sheetHeight(context);
|
||||
return ScaffoldMessenger(
|
||||
key: _messengerKey,
|
||||
child: Scaffold(
|
||||
backgroundColor: Colors.transparent,
|
||||
resizeToAvoidBottomInset: false,
|
||||
body: Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: GestureDetector(
|
||||
key: const Key('player-comments-dismiss-layer'),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: _handleDismissLayerTap,
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () {},
|
||||
child: KeyedSubtree(
|
||||
key: const Key('player-comments-sheet'),
|
||||
child: SizedBox(
|
||||
key: const Key('comment-sheet-constraints'),
|
||||
height: sheetHeight,
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: AppColors.card,
|
||||
borderRadius: BorderRadius.vertical(
|
||||
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),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
return Stack(
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Positioned.fill(
|
||||
child: GestureDetector(
|
||||
key: const Key('player-comments-dismiss-layer'),
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: _handleDismissLayerTap,
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () {},
|
||||
child: KeyedSubtree(
|
||||
key: const Key('player-comments-sheet'),
|
||||
child: SizedBox(
|
||||
key: const Key('comment-sheet-constraints'),
|
||||
height: sheetHeight,
|
||||
child: Container(
|
||||
decoration: const BoxDecoration(
|
||||
color: AppColors.card,
|
||||
borderRadius: BorderRadius.vertical(
|
||||
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),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@@ -372,6 +354,44 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
|
||||
}
|
||||
}
|
||||
|
||||
class _CommentPostSuccessOverlay extends StatelessWidget {
|
||||
const _CommentPostSuccessOverlay({required this.message});
|
||||
|
||||
final String message;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Positioned.fill(
|
||||
child: IgnorePointer(
|
||||
child: SafeArea(
|
||||
child: Align(
|
||||
alignment: const Alignment(0, 0.55),
|
||||
child: Semantics(
|
||||
liveRegion: true,
|
||||
child: Container(
|
||||
key: const Key('comment-post-success-snackbar'),
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 10,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.black.withValues(alpha: 0.82),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Text(
|
||||
message,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(color: Colors.white, fontSize: 14),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _CommentThread extends StatelessWidget {
|
||||
const _CommentThread({
|
||||
required this.comment,
|
||||
|
||||
Reference in new issue
Block a user