a940f2ea47
- 通知静态配置支持 title/body i18n - 前端通知列表和详情页展示本地化内容 - 新增数据库迁移脚本 - 更新通知协议文档
116 lines
3.4 KiB
Dart
116 lines
3.4 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import '../../../features/notifications/data/models/notification_item.dart';
|
|
import '../../theme/design_tokens.dart';
|
|
import '../../utils/time_format.dart';
|
|
|
|
class NotificationDetailBottomSheet extends StatefulWidget {
|
|
const NotificationDetailBottomSheet({
|
|
super.key,
|
|
required this.item,
|
|
required this.onMarkRead,
|
|
});
|
|
|
|
final NotificationItem item;
|
|
final Future<void> Function() onMarkRead;
|
|
|
|
@override
|
|
State<NotificationDetailBottomSheet> createState() =>
|
|
_NotificationDetailBottomSheetState();
|
|
}
|
|
|
|
class _NotificationDetailBottomSheetState
|
|
extends State<NotificationDetailBottomSheet> {
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
widget.onMarkRead();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final colors = Theme.of(context).colorScheme;
|
|
final textTheme = Theme.of(context).textTheme;
|
|
|
|
return Container(
|
|
height: MediaQuery.of(context).size.height * 0.5,
|
|
decoration: BoxDecoration(
|
|
color: colors.surface,
|
|
borderRadius: const BorderRadius.vertical(
|
|
top: Radius.circular(AppRadius.lg),
|
|
),
|
|
),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Center(
|
|
child: Container(
|
|
margin: const EdgeInsets.only(top: AppSpacing.sm),
|
|
width: 40,
|
|
height: 4,
|
|
decoration: BoxDecoration(
|
|
color: colors.outlineVariant,
|
|
borderRadius: BorderRadius.circular(2),
|
|
),
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.all(AppSpacing.lg),
|
|
child: Row(
|
|
children: [
|
|
Expanded(
|
|
child: Text(
|
|
widget.item.title,
|
|
style: textTheme.titleMedium?.copyWith(
|
|
fontWeight: FontWeight.w600,
|
|
color: colors.onSurface,
|
|
),
|
|
),
|
|
),
|
|
IconButton(
|
|
onPressed: () => Navigator.pop(context),
|
|
icon: Icon(Icons.close, color: colors.onSurfaceVariant),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.lg),
|
|
child: Text(
|
|
formatRelativeTime(context, widget.item.createdAt),
|
|
style: textTheme.labelSmall?.copyWith(color: colors.outline),
|
|
),
|
|
),
|
|
const SizedBox(height: AppSpacing.md),
|
|
Expanded(
|
|
child: SingleChildScrollView(
|
|
padding: const EdgeInsets.symmetric(horizontal: AppSpacing.lg),
|
|
child: Text(
|
|
widget.item.body,
|
|
style: textTheme.bodyMedium?.copyWith(
|
|
color: colors.onSurfaceVariant,
|
|
height: 1.6,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
Future<void> showNotificationDetailBottomSheet({
|
|
required BuildContext context,
|
|
required NotificationItem item,
|
|
required Future<void> Function() onMarkRead,
|
|
}) {
|
|
return showModalBottomSheet<void>(
|
|
context: context,
|
|
isScrollControlled: true,
|
|
backgroundColor: Colors.transparent,
|
|
builder: (context) =>
|
|
NotificationDetailBottomSheet(item: item, onMarkRead: onMarkRead),
|
|
);
|
|
}
|