feat(interaction): 支持游客点赞收藏评论

This commit is contained in:
Zhou Weidong committed 2026-10-26 22:33:14 +08:00
1 parent 188811fde6
commit a3d50eb935
18 files changed
+364 -121

No files matched your search

@@ -9,7 +9,6 @@ import 'package:flutter/services.dart';
import 'package:provider/provider.dart';
import '../../../core/data/models/comment.dart';
import '../../../core/data/services/auth_controller.dart';
import '../../../core/data/services/comment_controller.dart';
import '../../../core/platform/haptics.dart';
import '../../../core/platform/keyboard_inset.dart';
@@ -196,23 +195,20 @@ class _CommentComposerSheetState extends State<CommentComposerSheet> {
return;
}
final l10n = AppLocalizations.of(context)!;
if (result.errorCode == 200007) {
await ensureSignedIn(context);
return;
}
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(result.errorMessage ?? l10n.commentPostFailed)),
);
}
Future<void> _authenticate() async {
await ensureSignedIn(context);
if (!mounted || !context.read<AuthController>().isSignedIn) return;
_inputFocus.requestFocus();
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
final signedIn = context.watch<AuthController>().isSignedIn;
final hasContent = _input.text.trim().isNotEmpty;
final canPost = signedIn && hasContent && !widget.controller.submitting;
final canPost = hasContent && !widget.controller.submitting;
final multiline = _input.text.contains('\n');
final bottomInset = _isAndroid
? _pinnedKeyboardInset
@@ -247,8 +243,8 @@ class _CommentComposerSheetState extends State<CommentComposerSheet> {
key: const Key('comment-composer-input'),
controller: _input,
focusNode: _inputFocus,
readOnly: !signedIn,
canRequestFocus: signedIn,
readOnly: false,
canRequestFocus: true,
minLines: 1,
maxLines: 4,
maxLength: _maxCommentLength,
@@ -262,9 +258,7 @@ class _CommentComposerSheetState extends State<CommentComposerSheet> {
),
cursorColor: AppColors.blue,
decoration: InputDecoration(
hintText: signedIn
? l10n.writeComment
: l10n.commentLoginHint,
hintText: l10n.writeComment,
hintStyle: const TextStyle(
color: AppColors.muted,
fontSize: 14,
@@ -278,7 +272,7 @@ class _CommentComposerSheetState extends State<CommentComposerSheet> {
enabledBorder: InputBorder.none,
focusedBorder: InputBorder.none,
),
onTap: signedIn ? null : _authenticate,
onTap: null,
),
),
const SizedBox(height: 12),
@@ -11,11 +11,9 @@ import '../../../core/data/models/comment.dart';
import '../../../core/data/models/drama.dart';
import '../../../core/data/repositories/comment_repository.dart';
import '../../../core/data/repositories/interaction_repository.dart';
import '../../../core/data/services/auth_controller.dart';
import '../../../core/data/services/comment_controller.dart';
import '../../../core/formatting/error_text.dart';
import '../../../core/theme/app_colors.dart';
import '../../../core/widgets/auth_gate.dart';
import '../../../core/widgets/empty_state.dart';
import '../../../l10n/app_localizations.dart';
import 'comment_composer_sheet.dart';
@@ -29,7 +27,7 @@ const double _sheetRadius = 20;
const double _headerHeight = 44;
const double _composerTopGap = 8;
/// 服务端评论底部弹窗:匿名列表、游标翻页、回复与登录发布。
/// 服务端评论底部弹窗:匿名列表、游标翻页、回复与设备身份发布。
class DramaCommentsSheet extends StatefulWidget {
const DramaCommentsSheet({super.key, required this.drama, this.episodeId});
@@ -92,8 +90,7 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
}
Future<void> _openComposer({DramaComment? replyTo}) async {
await ensureSignedIn(context);
if (!mounted || !context.read<AuthController>().isSignedIn) return;
if (!mounted) return;
_removeComposerOverlay();
final entry = OverlayEntry(
builder: (_) => CommentComposerSheet(
@@ -222,7 +219,6 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
Widget _content(BuildContext context) {
final l10n = AppLocalizations.of(context)!;
final count = _serverCount ?? _controller.exactCount;
final signedIn = context.watch<AuthController>().isSignedIn;
final composerReserve = _composerHeight + _composerTopGap;
return Column(
key: const Key('comment-sheet-content'),
@@ -269,7 +265,7 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
Padding(
key: const Key('comment-composer-area'),
padding: const EdgeInsets.only(top: _composerTopGap),
child: _fakeComposer(l10n, signedIn: signedIn),
child: _fakeComposer(l10n),
),
],
);
@@ -352,7 +348,7 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
return const SizedBox(height: 8);
}
Widget _fakeComposer(AppLocalizations l10n, {required bool signedIn}) {
Widget _fakeComposer(AppLocalizations l10n) {
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: _openComposer,
@@ -372,7 +368,7 @@ class _DramaCommentsSheetState extends State<DramaCommentsSheet> {
child: Padding(
padding: const EdgeInsets.only(left: 16),
child: Text(
signedIn ? l10n.writeComment : l10n.commentLoginHint,
l10n.writeComment,
key: const Key('comment-input-placeholder-label'),
maxLines: 1,
overflow: TextOverflow.ellipsis,
@@ -49,7 +49,8 @@ class PlayerBlockedNotice extends StatelessWidget {
bool get _needsUnlock =>
accessType == PlayTicket.coinRequired ||
accessType == PlayTicket.vipRequired;
accessType == PlayTicket.vipRequired ||
(accessType == null && episode.locked);
@override
Widget build(BuildContext context) {