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
+72
View File
@@ -41,6 +41,15 @@ const personColors = [
Color(0xFF6A9F58),
];
const appCalendarColors = [
Color(0xFF4C9BCF),
Color(0xFFD6A74D),
Color(0xFFD65A6F),
Color(0xFF9B78B4),
Color(0xFF6A9F58),
Color(0xFFE89552),
];
class AvatarPreset {
const AvatarPreset(this.id, this.label, this.symbol);
@@ -121,6 +130,7 @@ class AppJsonStore {
if (!await file.exists()) {
final settings = AppSettings(
people: defaultPeople(),
appCalendars: defaultAppCalendars(),
themeId: 'sage',
languageCode: defaultLanguageCode,
googleConnections: defaultGoogleConnections(),
@@ -139,6 +149,7 @@ class AppJsonStore {
} catch (_) {
return AppSettings(
people: defaultPeople(),
appCalendars: defaultAppCalendars(),
themeId: 'sage',
languageCode: defaultLanguageCode,
googleConnections: defaultGoogleConnections(),
@@ -161,6 +172,7 @@ class AppJsonStore {
class AppSettings {
AppSettings({
required this.people,
required this.appCalendars,
required this.themeId,
required this.languageCode,
required this.googleConnections,
@@ -171,6 +183,7 @@ class AppSettings {
});
final List<Person> people;
final List<AppCalendar> appCalendars;
final String themeId;
final String languageCode;
final List<GoogleCalendarConnection> googleConnections;
@@ -181,6 +194,7 @@ class AppSettings {
factory AppSettings.fromJson(Map<String, dynamic> json) {
final rawPeople = json['people'];
final rawAppCalendars = json['appCalendars'];
final rawConnections = json['googleConnections'];
final rawSyncedEvents = json['syncedEvents'];
final rawTodoSuggestions = json['todoSuggestions'];
@@ -194,6 +208,12 @@ class AppSettings {
.toList(),
)
: defaultPeople(),
appCalendars: rawAppCalendars is List
? rawAppCalendars
.whereType<Map<String, dynamic>>()
.map(AppCalendar.fromJson)
.toList()
: defaultAppCalendars(),
themeId: json['themeId'] as String? ?? 'sage',
languageCode: json['languageCode'] == 'en' ? 'en' : defaultLanguageCode,
googleConnections: rawConnections is List
@@ -223,6 +243,7 @@ class AppSettings {
Map<String, dynamic> toJson() => {
'themeId': themeId,
'appCalendars': appCalendars.map((calendar) => calendar.toJson()).toList(),
'languageCode': languageCode,
'people': people.map((person) => person.toJson()).toList(),
'googleConnections': googleConnections
@@ -310,6 +331,7 @@ class GoogleCalendarConnection {
required this.accountEmail,
required this.enabledCalendarIds,
this.calendarPersonIds = const {},
this.calendarAppCalendarIds = const {},
this.eventPersonIds = const {},
required this.lastSync,
});
@@ -318,6 +340,7 @@ class GoogleCalendarConnection {
final String accountEmail;
final List<String> enabledCalendarIds;
final Map<String, String> calendarPersonIds;
final Map<String, String> calendarAppCalendarIds;
final Map<String, String> eventPersonIds;
final DateTime? lastSync;
@@ -325,6 +348,7 @@ class GoogleCalendarConnection {
String? accountEmail,
List<String>? enabledCalendarIds,
Map<String, String>? calendarPersonIds,
Map<String, String>? calendarAppCalendarIds,
Map<String, String>? eventPersonIds,
DateTime? lastSync,
}) {
@@ -333,6 +357,8 @@ class GoogleCalendarConnection {
accountEmail: accountEmail ?? this.accountEmail,
enabledCalendarIds: enabledCalendarIds ?? this.enabledCalendarIds,
calendarPersonIds: calendarPersonIds ?? this.calendarPersonIds,
calendarAppCalendarIds:
calendarAppCalendarIds ?? this.calendarAppCalendarIds,
eventPersonIds: eventPersonIds ?? this.eventPersonIds,
lastSync: lastSync ?? this.lastSync,
);
@@ -341,6 +367,7 @@ class GoogleCalendarConnection {
factory GoogleCalendarConnection.fromJson(Map<String, dynamic> json) {
final rawCalendarIds = json['enabledCalendarIds'];
final rawCalendarPersonIds = json['calendarPersonIds'];
final rawCalendarAppCalendarIds = json['calendarAppCalendarIds'];
final rawEventPersonIds = json['eventPersonIds'];
return GoogleCalendarConnection(
id: json['id'] as String? ?? uniqueId(),
@@ -353,6 +380,11 @@ class GoogleCalendarConnection {
(key, value) => MapEntry(key.toString(), value.toString()),
)
: const {},
calendarAppCalendarIds: rawCalendarAppCalendarIds is Map
? rawCalendarAppCalendarIds.map(
(key, value) => MapEntry(key.toString(), value.toString()),
)
: const {},
eventPersonIds: rawEventPersonIds is Map
? rawEventPersonIds.map(
(key, value) => MapEntry(key.toString(), value.toString()),
@@ -367,11 +399,41 @@ class GoogleCalendarConnection {
'accountEmail': accountEmail,
'enabledCalendarIds': enabledCalendarIds,
'calendarPersonIds': calendarPersonIds,
'calendarAppCalendarIds': calendarAppCalendarIds,
'eventPersonIds': eventPersonIds,
'lastSync': lastSync?.toIso8601String(),
};
}
class AppCalendar {
const AppCalendar({
required this.id,
required this.name,
required this.colorValue,
});
final String id;
final String name;
final int colorValue;
Color get color => Color(colorValue);
factory AppCalendar.fromJson(Map<String, dynamic> json) => AppCalendar(
id: json['id'] as String? ?? uniqueId(),
name: json['name'] as String? ?? 'Napt\u00e1r',
colorValue:
json['colorValue'] as int? ?? appCalendarColors.first.toARGB32(),
);
Map<String, dynamic> toJson() => {
'id': id,
'name': name,
'colorValue': colorValue,
};
}
List<AppCalendar> defaultAppCalendars() => [];
class GoogleCalendarInfo {
const GoogleCalendarInfo({
required this.id,
@@ -478,6 +540,7 @@ class CalendarEvent {
this.externalId,
this.calendarId,
this.calendarName,
this.appCalendarId,
this.note = '',
this.hasTodos = false,
this.todos = const [],
@@ -494,6 +557,7 @@ class CalendarEvent {
final String? externalId;
final String? calendarId;
final String? calendarName;
final String? appCalendarId;
final String note;
final bool hasTodos;
final List<String> todos;
@@ -514,7 +578,9 @@ class CalendarEvent {
String? note,
bool? hasTodos,
List<String>? todos,
String? appCalendarId,
bool clearPerson = false,
bool clearAppCalendar = false,
}) {
return CalendarEvent(
title ?? this.title,
@@ -527,6 +593,9 @@ class CalendarEvent {
externalId: externalId,
calendarId: calendarId,
calendarName: calendarName,
appCalendarId: clearAppCalendar
? null
: appCalendarId ?? this.appCalendarId,
note: note ?? this.note,
hasTodos: hasTodos ?? this.hasTodos,
todos: todos ?? this.todos,
@@ -546,6 +615,7 @@ class CalendarEvent {
externalId: json['externalId'] as String?,
calendarId: json['calendarId'] as String?,
calendarName: json['calendarName'] as String?,
appCalendarId: json['appCalendarId'] as String?,
note: json['note'] as String? ?? '',
hasTodos: json['hasTodos'] as bool? ?? false,
todos: json['todos'] is List
@@ -586,6 +656,7 @@ class CalendarEvent {
externalId: event['id'] as String?,
calendarId: calendar.id,
calendarName: calendar.name,
appCalendarId: null,
personId: personId,
note: description ?? '',
source: EventSource.googleCalendar,
@@ -603,6 +674,7 @@ class CalendarEvent {
'externalId': externalId,
'calendarId': calendarId,
'calendarName': calendarName,
'appCalendarId': appCalendarId,
'note': note,
'hasTodos': hasTodos,
'todos': todos,