Add multi calendar support and protected web app

This commit is contained in:
zsolt
2026-08-13 14:49:00 +02:00
parent 17e83c032a
commit a6403bf9bb
51 changed files with 220126 additions and 31 deletions
+88 -24
View File
@@ -6,6 +6,7 @@ class AccountsPage extends StatefulWidget {
required this.connections,
required this.cachedEvents,
required this.people,
required this.appCalendars,
required this.jarvisSettings,
required this.serverClientId,
required this.languageCode,
@@ -16,6 +17,7 @@ class AccountsPage extends StatefulWidget {
final List<GoogleCalendarConnection> connections;
final List<CalendarEvent> cachedEvents;
final List<Person> people;
final List<AppCalendar> appCalendars;
final JarvisSettings jarvisSettings;
final String serverClientId;
final String languageCode;
@@ -180,6 +182,7 @@ class _AccountsPageState extends State<AccountsPage>
accountEmail: email ?? current?.accountEmail ?? 'Google fi\u00f3k',
enabledCalendarIds: current?.enabledCalendarIds ?? const [],
calendarPersonIds: current?.calendarPersonIds ?? const {},
calendarAppCalendarIds: current?.calendarAppCalendarIds ?? const {},
eventPersonIds: current?.eventPersonIds ?? const {},
lastSync: current?.lastSync,
),
@@ -300,6 +303,7 @@ class _AccountsPageState extends State<AccountsPage>
accountEmail: 'Google Calendar',
enabledCalendarIds: const [],
calendarPersonIds: const {},
calendarAppCalendarIds: const {},
eventPersonIds: const {},
lastSync: null,
),
@@ -357,10 +361,8 @@ class _AccountsPageState extends State<AccountsPage>
final defaultPersonId =
current.calendarPersonIds[cachedEvent.calendarId];
if (cachedEvent.personId == defaultPersonId) continue;
eventPersonOverrides.putIfAbsent(
importedEventKey(cachedEvent),
() => cachedEvent.personId!,
);
eventPersonOverrides[importedEventKey(cachedEvent)] =
cachedEvent.personId!;
}
final now = DateTime.now();
final start = DateTime(
@@ -399,7 +401,12 @@ class _AccountsPageState extends State<AccountsPage>
final assignedPersonId =
eventPersonOverrides[eventKey] ??
current.calendarPersonIds[calendar.id];
synced.add(imported.copyWith(personId: assignedPersonId));
synced.add(
imported.copyWith(
personId: assignedPersonId,
appCalendarId: current.calendarAppCalendarIds[calendar.id],
),
);
}
}
@@ -479,10 +486,16 @@ class _AccountsPageState extends State<AccountsPage>
calendar: calendar,
enabled: current.enabledCalendarIds.contains(calendar.id),
people: widget.people,
appCalendars: widget.appCalendars,
selectedPersonId: current.calendarPersonIds[calendar.id],
selectedAppCalendarId:
current.calendarAppCalendarIds[calendar.id],
onChanged: (enabled) {
final nextIds = [...current.enabledCalendarIds];
final nextPersonIds = {...current.calendarPersonIds};
final nextAppCalendarIds = {
...current.calendarAppCalendarIds,
};
if (enabled) {
if (!nextIds.contains(calendar.id)) {
nextIds.add(calendar.id);
@@ -490,11 +503,13 @@ class _AccountsPageState extends State<AccountsPage>
} else {
nextIds.remove(calendar.id);
nextPersonIds.remove(calendar.id);
nextAppCalendarIds.remove(calendar.id);
}
widget.onChanged([
current.copyWith(
enabledCalendarIds: nextIds,
calendarPersonIds: nextPersonIds,
calendarAppCalendarIds: nextAppCalendarIds,
lastSync: current.lastSync,
),
]);
@@ -513,6 +528,22 @@ class _AccountsPageState extends State<AccountsPage>
),
]);
},
onAppCalendarChanged: (appCalendarId) {
final nextAppCalendarIds = {
...current.calendarAppCalendarIds,
};
if (appCalendarId == null) {
nextAppCalendarIds.remove(calendar.id);
} else {
nextAppCalendarIds[calendar.id] = appCalendarId;
}
widget.onChanged([
current.copyWith(
calendarAppCalendarIds: nextAppCalendarIds,
lastSync: current.lastSync,
),
]);
},
),
),
const SizedBox(height: 16),
@@ -694,17 +725,23 @@ class GoogleCalendarToggleCard extends StatelessWidget {
required this.calendar,
required this.enabled,
required this.people,
required this.appCalendars,
required this.selectedPersonId,
required this.selectedAppCalendarId,
required this.onChanged,
required this.onPersonChanged,
required this.onAppCalendarChanged,
});
final GoogleCalendarInfo calendar;
final bool enabled;
final List<Person> people;
final List<AppCalendar> appCalendars;
final String? selectedPersonId;
final String? selectedAppCalendarId;
final ValueChanged<bool> onChanged;
final ValueChanged<String?> onPersonChanged;
final ValueChanged<String?> onAppCalendarChanged;
@override
Widget build(BuildContext context) {
@@ -738,28 +775,55 @@ class GoogleCalendarToggleCard extends StatelessWidget {
if (enabled)
Padding(
padding: const EdgeInsets.fromLTRB(72, 0, 16, 0),
child: DropdownButtonFormField<String?>(
initialValue: selectedPersonId,
decoration: const InputDecoration(
labelText: 'Kihez tartozzanak az esem\u00e9nyek?',
),
items: [
const DropdownMenuItem<String?>(
value: null,
child: Text('Kategoriz\u00e1latlan'),
),
const DropdownMenuItem<String?>(
value: everyonePersonId,
child: Text('Mindenki'),
),
...people.map(
(person) => DropdownMenuItem<String?>(
value: person.id,
child: Text('${person.avatar} ${person.name}'),
child: Column(
children: [
DropdownButtonFormField<String?>(
initialValue: selectedPersonId,
decoration: const InputDecoration(
labelText: 'Kihez tartozzanak az esem\u00e9nyek?',
),
items: [
const DropdownMenuItem<String?>(
value: null,
child: Text('Kategoriz\u00e1latlan'),
),
const DropdownMenuItem<String?>(
value: everyonePersonId,
child: Text('Mindenki'),
),
...people.map(
(person) => DropdownMenuItem<String?>(
value: person.id,
child: Text('${person.avatar} ${person.name}'),
),
),
],
onChanged: onPersonChanged,
),
if (appCalendars.isNotEmpty) ...[
const SizedBox(height: 10),
DropdownButtonFormField<String?>(
initialValue: selectedAppCalendarId,
decoration: const InputDecoration(
labelText:
'Melyik K\u00f6z\u00f6sT\u00e9r napt\u00e1rba import\u00e1ljon?',
),
items: [
const DropdownMenuItem<String?>(
value: null,
child: Text('F\u0151 csal\u00e1di napt\u00e1r'),
),
...appCalendars.map(
(calendar) => DropdownMenuItem<String?>(
value: calendar.id,
child: Text(calendar.name),
),
),
],
onChanged: onAppCalendarChanged,
),
],
],
onChanged: onPersonChanged,
),
),
],