Files
social-app/apps/lib/features/calendar/ui/widgets/calendar_share_dialog.dart
T

208 lines
6.1 KiB
Dart

import 'package:flutter/material.dart' hide BackButton;
import '../../../../core/di/injection.dart';
import '../../../../core/theme/design_tokens.dart';
import '../../../../shared/widgets/app_button.dart';
import '../../../../shared/widgets/toast/toast.dart';
import '../../../../shared/widgets/toast/toast_type.dart';
import '../../data/calendar_api.dart';
class CalendarShareDialog extends StatefulWidget {
final String eventId;
final String eventTitle;
final bool canInvite;
final bool canEdit;
const CalendarShareDialog({
super.key,
required this.eventId,
required this.eventTitle,
this.canInvite = false,
this.canEdit = false,
});
static Future<void> show(
BuildContext context,
String eventId,
String eventTitle, {
bool canInvite = false,
bool canEdit = false,
}) {
return showModalBottomSheet(
context: context,
isScrollControlled: true,
backgroundColor: Colors.transparent,
builder: (context) => CalendarShareDialog(
eventId: eventId,
eventTitle: eventTitle,
canInvite: canInvite,
canEdit: canEdit,
),
);
}
@override
State<CalendarShareDialog> createState() => _CalendarShareDialogState();
}
class _CalendarShareDialogState extends State<CalendarShareDialog> {
final _emailController = TextEditingController();
bool _permissionView = true;
bool _permissionEdit = false;
bool _permissionInvite = false;
bool _isLoading = false;
@override
void dispose() {
_emailController.dispose();
super.dispose();
}
Future<void> _handleShare() async {
final email = _emailController.text.trim();
if (email.isEmpty) {
Toast.show(context, '请输入邮箱地址', type: ToastType.error);
return;
}
setState(() => _isLoading = true);
try {
final api = sl<CalendarApi>();
await api.share(
widget.eventId,
email: email,
view: _permissionView,
edit: _permissionEdit,
invite: _permissionInvite,
);
if (mounted) {
Toast.show(context, '邀请已发送', type: ToastType.success);
Navigator.of(context).pop();
}
} catch (e) {
if (mounted) {
Toast.show(context, '发送邀请失败', type: ToastType.error);
}
} finally {
if (mounted) {
setState(() => _isLoading = false);
}
}
}
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
decoration: BoxDecoration(
color: AppColors.background,
borderRadius: const BorderRadius.vertical(
top: Radius.circular(AppRadius.lg),
),
),
child: SafeArea(
child: Padding(
padding: const EdgeInsets.all(AppSpacing.lg),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
'分享日历',
style: TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
),
IconButton(
onPressed: () => Navigator.of(context).pop(),
icon: const Icon(Icons.close),
),
],
),
const SizedBox(height: AppSpacing.md),
Text(widget.eventTitle, style: const TextStyle(fontSize: 16)),
const SizedBox(height: AppSpacing.lg),
TextField(
controller: _emailController,
decoration: InputDecoration(
labelText: '邮箱地址',
hintText: '输入对方的邮箱',
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(AppRadius.md),
),
),
keyboardType: TextInputType.emailAddress,
),
const SizedBox(height: AppSpacing.lg),
const Text('权限设置', style: TextStyle(fontWeight: FontWeight.w600)),
const SizedBox(height: AppSpacing.sm),
_buildPermissionSwitch('查看', '可以查看此日历事件(必选)', true, null),
_buildPermissionSwitch(
'编辑',
'可以编辑此日历事件',
_permissionEdit,
widget.canEdit
? (v) => setState(() => _permissionEdit = v)
: null,
),
_buildPermissionSwitch(
'邀请',
'可以邀请其他人',
_permissionInvite,
widget.canInvite
? (v) => setState(() => _permissionInvite = v)
: null,
),
const SizedBox(height: AppSpacing.lg),
AppButton(
text: '发送邀请',
onPressed: _isLoading ? null : _handleShare,
isLoading: _isLoading,
),
],
),
),
),
);
}
Widget _buildPermissionSwitch(
String title,
String description,
bool value,
ValueChanged<bool>? onChanged,
) {
final enabled = onChanged != null;
return Padding(
padding: const EdgeInsets.symmetric(vertical: AppSpacing.xs),
child: Row(
children: [
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: TextStyle(color: enabled ? null : Colors.grey),
),
Text(
description,
style: TextStyle(
fontSize: 12,
color: enabled ? Colors.grey : Colors.grey.shade400,
),
),
],
),
),
Switch(value: value, onChanged: enabled ? onChanged : null),
],
),
);
}
}