fix(player): 评论聚焦态改为展开输入面板

This commit is contained in:
Zhou Weidong committed 2026-10-21 12:21:17 +08:00
1 parent 8b51a7c18e
commit 519cab20fe
3 files changed
+225 -6

No files matched your search

@@ -31,6 +31,8 @@ const double _headerHeight = 44;
const double _replyIndent = 52;
const double _composerTopGap = 8;
const double _replyBannerHeight = 46;
const double _expandedInputRadius = 12;
const double _postButtonHeight = 32;
/// 服务端评论底部弹窗:匿名列表、游标翻页、回复、举报和本人删除。
class DramaCommentsSheet extends StatefulWidget {
@@ -54,6 +56,8 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
@override
void initState() {
super.initState();
_inputFocus.addListener(_onFocusChanged);
_input.addListener(_onInputChanged);
_comments = context.read<CommentRepository>();
_controller = CommentController(
comments: _comments,
@@ -66,12 +70,22 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
@override
void dispose() {
_inputFocus.removeListener(_onFocusChanged);
_input.removeListener(_onInputChanged);
_controller.dispose();
_input.dispose();
_inputFocus.dispose();
super.dispose();
}
void _onFocusChanged() {
if (mounted) setState(() {});
}
void _onInputChanged() {
if (mounted) setState(() {});
}
Future<void> _post() async {
if (_controller.submitting) return;
if (!await ensureSignedIn(context) || !mounted) return;
@@ -82,7 +96,7 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
if (result.isSuccess) {
_input.clear();
setState(() => _replyTo = null);
FocusScope.of(context).unfocus();
_inputFocus.requestFocus();
await _refreshCount();
return;
}
@@ -184,6 +198,9 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
final maxHeight = screenLimit < _maxSheetHeight
? screenLimit
: _maxSheetHeight;
if (_inputFocus.hasFocus) {
return _expandedComposer(context, maxHeight);
}
return Container(
key: const Key('player-comments-sheet'),
decoration: const BoxDecoration(
@@ -215,6 +232,115 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
);
}
Widget _expandedComposer(BuildContext context, double maxHeight) {
final l10n = AppLocalizations.of(context)!;
final signedIn = context.watch<AuthController>().isSignedIn;
final hasContent = _input.text.trim().isNotEmpty;
final canPost = signedIn && hasContent && !_controller.submitting;
return AnimatedPadding(
duration: const Duration(milliseconds: 150),
curve: Curves.easeOut,
padding: EdgeInsets.only(bottom: MediaQuery.viewInsetsOf(context).bottom),
child: Container(
key: const Key('player-comments-sheet'),
decoration: const BoxDecoration(
color: AppColors.card,
borderRadius: BorderRadius.vertical(
top: Radius.circular(_sheetRadius),
),
),
child: SafeArea(
top: false,
child: ConstrainedBox(
constraints: BoxConstraints(maxHeight: maxHeight),
child: Padding(
padding: const EdgeInsets.fromLTRB(16, 12, 16, 12),
child: Column(
key: const Key('comment-expanded-composer'),
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
if (_replyTo != null) _replyBanner(l10n, _replyTo!),
Container(
decoration: BoxDecoration(
color: AppColors.commentInput,
borderRadius: BorderRadius.circular(_expandedInputRadius),
),
child: TextField(
key: const Key('comment-input'),
controller: _input,
focusNode: _inputFocus,
autofocus: true,
readOnly: !signedIn,
canRequestFocus: signedIn,
minLines: 1,
maxLines: 4,
maxLength: _maxCommentLength,
textAlignVertical: TextAlignVertical.top,
style: const TextStyle(
color: AppColors.cream,
fontSize: 15,
),
cursorColor: AppColors.blue,
decoration: InputDecoration(
hintText: l10n.writeComment,
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 : _authenticateForComment,
),
),
const SizedBox(height: 12),
Align(
alignment: Alignment.centerRight,
child: SizedBox(
height: _postButtonHeight,
child: TextButton(
key: const Key('comment-post'),
onPressed: canPost ? _post : 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,
),
),
),
),
),
],
),
),
),
),
),
);
}
Widget _content(BuildContext context, double maxHeight) {
final l10n = AppLocalizations.of(context)!;
final count = _serverCount ?? _controller.exactCount;
@@ -277,9 +403,7 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
child: _list(l10n),
),
if (_replyTo != null) _replyBanner(l10n, _replyTo!),
const SizedBox(
height: _composerHeight + _composerTopGap,
),
const SizedBox(height: _composerHeight + _composerTopGap),
],
),
Positioned(