Add automatic Google calendar sync

This commit is contained in:
zsolt
2026-08-13 14:26:55 +02:00
parent bab318797a
commit 17e83c032a
+48 -5
View File
@@ -28,21 +28,30 @@ class AccountsPage extends StatefulWidget {
class _AccountsPageState extends State<AccountsPage> class _AccountsPageState extends State<AccountsPage>
with WidgetsBindingObserver { with WidgetsBindingObserver {
static const googleAutoSyncInterval = Duration(minutes: 5);
static const googleResumeSyncInterval = Duration(minutes: 2);
List<GoogleCalendarInfo> googleCalendars = []; List<GoogleCalendarInfo> googleCalendars = [];
bool loadingCalendars = false; bool loadingCalendars = false;
bool syncing = false; bool syncing = false;
bool waitingForGoogleAuthReturn = false; bool waitingForGoogleAuthReturn = false;
Timer? googleAutoSyncTimer;
String? statusMessage; String? statusMessage;
@override @override
void initState() { void initState() {
super.initState(); super.initState();
WidgetsBinding.instance.addObserver(this); WidgetsBinding.instance.addObserver(this);
googleAutoSyncTimer = Timer.periodic(
googleAutoSyncInterval,
(_) => _autoSyncSelectedCalendars(),
);
_loadGoogleConnectionStatus(); _loadGoogleConnectionStatus();
} }
@override @override
void dispose() { void dispose() {
googleAutoSyncTimer?.cancel();
WidgetsBinding.instance.removeObserver(this); WidgetsBinding.instance.removeObserver(this);
super.dispose(); super.dispose();
} }
@@ -66,6 +75,10 @@ class _AccountsPageState extends State<AccountsPage>
if (state == AppLifecycleState.resumed && waitingForGoogleAuthReturn) { if (state == AppLifecycleState.resumed && waitingForGoogleAuthReturn) {
waitingForGoogleAuthReturn = false; waitingForGoogleAuthReturn = false;
_loadGoogleConnectionStatus(); _loadGoogleConnectionStatus();
return;
}
if (state == AppLifecycleState.resumed) {
_autoSyncSelectedCalendars(minAge: googleResumeSyncInterval);
} }
} }
@@ -106,6 +119,30 @@ class _AccountsPageState extends State<AccountsPage>
return null; return null;
} }
bool _canAutoSync() {
final current = connection;
return current != null &&
current.accountEmail.isNotEmpty &&
current.enabledCalendarIds.isNotEmpty &&
!syncing &&
!loadingCalendars &&
_jarvisConfigError() == null;
}
Future<void> _autoSyncSelectedCalendars({
Duration minAge = googleAutoSyncInterval,
}) async {
final current = connection;
if (!_canAutoSync() || current == null) return;
final lastSync = current.lastSync;
if (lastSync != null && DateTime.now().difference(lastSync) < minAge) {
return;
}
await _syncSelectedCalendars(automatic: true);
}
Future<void> _loadGoogleConnectionStatus() async { Future<void> _loadGoogleConnectionStatus() async {
setState(() { setState(() {
loadingCalendars = true; loadingCalendars = true;
@@ -287,9 +324,10 @@ class _AccountsPageState extends State<AccountsPage>
} }
} }
Future<void> _syncSelectedCalendars() async { Future<void> _syncSelectedCalendars({bool automatic = false}) async {
final current = connection; final current = connection;
if (current == null || current.enabledCalendarIds.isEmpty) { if (current == null || current.enabledCalendarIds.isEmpty) {
if (automatic) return;
setState( setState(
() => statusMessage = () => statusMessage =
'V\u00e1lassz ki legal\u00e1bb egy Google napt\u00e1rat.', 'V\u00e1lassz ki legal\u00e1bb egy Google napt\u00e1rat.',
@@ -299,7 +337,9 @@ class _AccountsPageState extends State<AccountsPage>
setState(() { setState(() {
syncing = true; syncing = true;
statusMessage = 'Google esem\u00e9nyek beolvas\u00e1sa...'; statusMessage = automatic
? 'Automatikus Google szinkron fut...'
: 'Google esem\u00e9nyek beolvas\u00e1sa...';
}); });
try { try {
@@ -377,14 +417,17 @@ class _AccountsPageState extends State<AccountsPage>
]); ]);
setState(() { setState(() {
syncing = false; syncing = false;
statusMessage = statusMessage = automatic
'${synced.length} Google esem\u00e9ny szinkroniz\u00e1lva \u00e9s JSON cache-be mentve.' ? '${synced.length} Google esem\u00e9ny automatikusan friss\u00edtve.'
: '${synced.length} Google esem\u00e9ny szinkroniz\u00e1lva \u00e9s JSON cache-be mentve.'
'${syncDetails.isEmpty ? '' : ' R\u00e9szletek: ${syncDetails.join('; ')}.'}'; '${syncDetails.isEmpty ? '' : ' R\u00e9szletek: ${syncDetails.join('; ')}.'}';
}); });
} catch (error) { } catch (error) {
setState(() { setState(() {
syncing = false; syncing = false;
statusMessage = 'A Google szinkron nem siker\u00fclt: $error'; statusMessage = automatic
? 'Az automatikus Google szinkron most nem siker\u00fclt, a kor\u00e1bbi cache marad: $error'
: 'A Google szinkron nem siker\u00fclt: $error';
}); });
} }
} }