feat(flutter): 接入互动评论点赞举报
This commit is contained in:
1 parent
45f5f25640
commit
d361034226
39 files changed
+3298
-462
No files matched your search
@@ -0,0 +1,125 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../../core/data/models/interaction.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
|
||||
const int _maxDescriptionLength = 300;
|
||||
|
||||
/// 举报弹窗收集的结果。
|
||||
class ReportDialogResult {
|
||||
const ReportDialogResult({
|
||||
required this.reason,
|
||||
required this.description,
|
||||
});
|
||||
|
||||
final ReportReason reason;
|
||||
final String description;
|
||||
}
|
||||
|
||||
/// 打开举报原因单选弹窗;取消时返回 null。
|
||||
Future<ReportDialogResult?> showReportDialog(
|
||||
BuildContext context, {
|
||||
required String title,
|
||||
}) => showDialog<ReportDialogResult>(
|
||||
context: context,
|
||||
builder: (_) => _ReportDialog(title: title),
|
||||
);
|
||||
|
||||
class _ReportDialog extends StatefulWidget {
|
||||
const _ReportDialog({required this.title});
|
||||
|
||||
final String title;
|
||||
|
||||
@override
|
||||
State<_ReportDialog> createState() => _ReportDialogState();
|
||||
}
|
||||
|
||||
class _ReportDialogState extends State<_ReportDialog> {
|
||||
final _description = TextEditingController();
|
||||
ReportReason _reason = ReportReason.spam;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_description.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _submit() {
|
||||
Navigator.of(context).pop(
|
||||
ReportDialogResult(
|
||||
reason: _reason,
|
||||
description: _description.text.trim(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _reasonLabel(AppLocalizations l10n, ReportReason reason) =>
|
||||
switch (reason) {
|
||||
ReportReason.spam => l10n.reportReasonSpam,
|
||||
ReportReason.abuse => l10n.reportReasonAbuse,
|
||||
ReportReason.porn => l10n.reportReasonPorn,
|
||||
ReportReason.ad => l10n.reportReasonAd,
|
||||
ReportReason.other => l10n.reportReasonOther,
|
||||
};
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = AppLocalizations.of(context)!;
|
||||
return AlertDialog(
|
||||
title: Text(widget.title),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(l10n.reportReason),
|
||||
RadioGroup<ReportReason>(
|
||||
groupValue: _reason,
|
||||
onChanged: (value) {
|
||||
if (value == null) return;
|
||||
setState(() => _reason = value);
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
for (final reason in ReportReason.values)
|
||||
RadioListTile<ReportReason>(
|
||||
key: Key('report-reason-${reason.apiValue}'),
|
||||
value: reason,
|
||||
contentPadding: EdgeInsets.zero,
|
||||
dense: true,
|
||||
title: Text(_reasonLabel(l10n, reason)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
key: const Key('report-description'),
|
||||
controller: _description,
|
||||
maxLength: _maxDescriptionLength,
|
||||
maxLines: 3,
|
||||
minLines: 2,
|
||||
decoration: InputDecoration(
|
||||
hintText: l10n.reportDescriptionHint,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: Text(l10n.cancel),
|
||||
),
|
||||
FilledButton(
|
||||
key: const Key('report-submit'),
|
||||
onPressed: _submit,
|
||||
child: Text(l10n.reportSubmit),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user