feat: 添加日历事件订阅者功能及权限重构
This commit is contained in:
@@ -149,6 +149,10 @@ class _CalendarEventDetailScreenState extends State<CalendarEventDetailScreen> {
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
_buildExtraSurface(event),
|
||||
],
|
||||
if (event.subscribers.isNotEmpty) ...[
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
_buildSubscribersSurface(event),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
@@ -465,6 +469,131 @@ class _CalendarEventDetailScreenState extends State<CalendarEventDetailScreen> {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSubscribersSurface(ScheduleItemModel event) {
|
||||
if (event.subscribers.isEmpty) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(AppSpacing.lg),
|
||||
decoration: BoxDecoration(
|
||||
color: _colorScheme.surface,
|
||||
borderRadius: BorderRadius.circular(AppRadius.xl),
|
||||
border: Border.all(color: _colorScheme.outlineVariant),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
context.l10n.calendarDetailSubscribers(event.subscribers.length),
|
||||
style: TextStyle(
|
||||
fontSize: 13,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: _colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: AppSpacing.md),
|
||||
...event.subscribers.map(
|
||||
(sub) => _buildSubscriberRow(sub, event.ownerId),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildSubscriberRow(Subscriber subscriber, String ownerId) {
|
||||
final palette = Theme.of(context).extension<AppColorPalette>()!;
|
||||
final avatarColor =
|
||||
palette.avatarColors[subscriber.userId.hashCode.abs() %
|
||||
palette.avatarColors.length];
|
||||
final isOwner = subscriber.userId == ownerId;
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: AppSpacing.xs),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 32,
|
||||
height: 32,
|
||||
decoration: BoxDecoration(
|
||||
color: _colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
),
|
||||
child: subscriber.avatarUrl != null
|
||||
? ClipRRect(
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
child: Image.network(
|
||||
subscriber.avatarUrl!,
|
||||
width: 32,
|
||||
height: 32,
|
||||
fit: BoxFit.cover,
|
||||
errorBuilder: (context, error, stackTrace) =>
|
||||
Icon(Icons.person, size: 16, color: avatarColor),
|
||||
),
|
||||
)
|
||||
: Icon(Icons.person, size: 16, color: avatarColor),
|
||||
),
|
||||
const SizedBox(width: AppSpacing.sm),
|
||||
Expanded(
|
||||
child: Row(
|
||||
children: [
|
||||
Flexible(
|
||||
child: Text(
|
||||
subscriber.phone ??
|
||||
subscriber.username ??
|
||||
subscriber.userId.substring(0, 8),
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: _colorScheme.onSurface,
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
if (isOwner) ...[
|
||||
const SizedBox(width: AppSpacing.xs),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: AppSpacing.xs,
|
||||
vertical: 2,
|
||||
),
|
||||
decoration: BoxDecoration(
|
||||
color: _colorScheme.primaryContainer,
|
||||
borderRadius: BorderRadius.circular(AppRadius.full),
|
||||
),
|
||||
child: Text(
|
||||
context.l10n.calendarOwnerBadge,
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
fontWeight: FontWeight.w700,
|
||||
color: _colorScheme.onPrimaryContainer,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
if (subscriber.canEdit)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: AppSpacing.xs),
|
||||
child: Icon(
|
||||
LucideIcons.pencil,
|
||||
size: 14,
|
||||
color: _colorScheme.primary,
|
||||
),
|
||||
),
|
||||
if (subscriber.canInvite)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: AppSpacing.xs),
|
||||
child: Icon(
|
||||
LucideIcons.userPlus,
|
||||
size: 14,
|
||||
color: _colorScheme.primary,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String _formatReminderText(int? reminderMinutes) {
|
||||
if (reminderMinutes == null) {
|
||||
return context.l10n.calendarDetailReminderNone;
|
||||
|
||||
Reference in New Issue
Block a user