main
dart 119 lines 3.76 KB
Raw
1 import 'package:device_calendar_plus/device_calendar_plus.dart';
2
3 /// Thin wrapper around [DeviceCalendar] for the built-in calendar tools.
4 ///
5 /// All methods return plain Dart types (strings / maps) so tool results can be
6 /// serialised without leaking platform model classes into the tool layer.
7 class CalendarService {
8 CalendarService._();
9 static final instance = CalendarService._();
10
11 final _plugin = DeviceCalendar.instance;
12
13 // ---------------------------------------------------------------------------
14 // Permissions
15 // ---------------------------------------------------------------------------
16
17 /// Request full calendar access. Returns `true` when granted.
18 Future<bool> requestAccess() async {
19 final status = await _plugin.requestPermissions();
20 return status == CalendarPermissionStatus.granted;
21 }
22
23 /// Check current permission status without prompting.
24 Future<bool> hasAccess() async {
25 final status = await _plugin.hasPermissions();
26 return status == CalendarPermissionStatus.granted;
27 }
28
29 // ---------------------------------------------------------------------------
30 // Calendars
31 // ---------------------------------------------------------------------------
32
33 /// Returns a JSON-friendly list of available calendars.
34 Future<List<Map<String, dynamic>>> listCalendars() async {
35 final calendars = await _plugin.listCalendars();
36 return calendars
37 .map(
38 (c) => {
39 'id': c.id,
40 'name': c.name,
41 'is_read_only': c.readOnly,
42 'is_primary': c.isPrimary,
43 'account_name': c.accountName,
44 },
45 )
46 .toList();
47 }
48
49 // ---------------------------------------------------------------------------
50 // Events – read
51 // ---------------------------------------------------------------------------
52
53 /// Lists events in [start]..[end]. Both default to "today → +7 days".
54 Future<List<Map<String, dynamic>>> listEvents({
55 DateTime? start,
56 DateTime? end,
57 }) async {
58 final from = start ?? _todayStart();
59 final to = end ?? from.add(const Duration(days: 7));
60
61 final events = await _plugin.listEvents(from, to);
62 return events
63 .map(
64 (e) => {
65 'id': e.eventId,
66 'title': e.title,
67 'start': e.startDate.toIso8601String(),
68 'end': e.endDate.toIso8601String(),
69 'all_day': e.isAllDay,
70 'location': e.location,
71 'description': e.description,
72 'calendar_id': e.calendarId,
73 },
74 )
75 .toList();
76 }
77
78 // ---------------------------------------------------------------------------
79 // Events – write
80 // ---------------------------------------------------------------------------
81
82 /// Creates a new event and returns a result map with the event ID.
83 Future<Map<String, dynamic>> createEvent({
84 required String title,
85 required DateTime startDate,
86 required DateTime endDate,
87 String? description,
88 String? location,
89 String? calendarId,
90 }) async {
91 try {
92 final eventId = await _plugin.createEvent(
93 title: title,
94 startDate: startDate,
95 endDate: endDate,
96 description: description,
97 location: location,
98 calendarId: calendarId,
99 );
100
101 return {
102 'success': true,
103 'event_id': eventId,
104 'message': 'Event "$title" created successfully.',
105 };
106 } on DeviceCalendarException catch (e) {
107 return {'success': false, 'error': e.toString()};
108 }
109 }
110
111 // ---------------------------------------------------------------------------
112 // Helpers
113 // ---------------------------------------------------------------------------
114
115 DateTime _todayStart() {
116 final now = DateTime.now();
117 return DateTime(now.year, now.month, now.day);
118 }
119 }