Files
TimeReg/lib/services/sync_service.dart
T

121 lines
3.4 KiB
Dart

import 'dart:async';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:uuid/uuid.dart';
import '../models/sync_operation.dart';
class SyncService {
final FirebaseFirestore _firestore = FirebaseFirestore.instance;
final Connectivity _connectivity = Connectivity();
late Box<Map> _queueBox;
bool _isOnline = true;
bool _isSyncing = false;
final _uuid = const Uuid();
// Stream controller for sync status
final _isSyncingController = StreamController<bool>.broadcast();
Stream<bool> get isSyncingStream => _isSyncingController.stream;
bool get isOnline => _isOnline;
Future<void> init() async {
_queueBox = await Hive.openBox<Map>('sync_queue');
// Sjekk initiell tilkobling
try {
final result = await _connectivity.checkConnectivity();
_updateConnectionStatus(result);
} catch (e) {
print('Kunne ikke sjekke tilkobling: $e');
}
// Lytt etter endringer
_connectivity.onConnectivityChanged.listen(_updateConnectionStatus);
}
void _updateConnectionStatus(ConnectivityResult result) {
_isOnline = result != ConnectivityResult.none;
print('Tilkoblingsstatus endret: $_isOnline ($result)');
if (_isOnline) {
_processQueue();
}
}
// Legg til operasjon i køen
Future<void> addToQueue(SyncOperation operation) async {
await _queueBox.put(operation.id, operation.toMap());
// Prøv å synkronisere umiddelbart hvis vi er online
if (_isOnline) {
_processQueue();
}
}
// Behandle køen
Future<void> _processQueue() async {
if (_isSyncing || _queueBox.isEmpty) return;
_isSyncing = true;
_isSyncingController.add(true);
try {
// Hent alle operasjoner og sorter etter tidsstempel
final operations = _queueBox.values
.map((map) => SyncOperation.fromMap(Map<String, dynamic>.from(map)))
.toList()
..sort((a, b) => a.timestamp.compareTo(b.timestamp));
for (final op in operations) {
try {
await _performOperation(op);
await _queueBox.delete(op.id);
} catch (e) {
print('Feil ved synkronisering av operasjon ${op.id}: $e');
// Vi lar den ligge i køen for å prøve igjen senere
// Men hvis det er en permanent feil, burde vi kanskje flytte den til en "feil-kø"
}
}
} finally {
_isSyncing = false;
_isSyncingController.add(false);
}
}
Future<void> _performOperation(SyncOperation op) async {
final collection = _firestore.collection(op.collection);
final docRef = collection.doc(op.docId);
switch (op.action) {
case SyncAction.create:
await docRef.set(op.data);
break;
case SyncAction.update:
await docRef.update(op.data);
break;
case SyncAction.delete:
await docRef.delete();
break;
}
}
// Hjelpemetode for å opprette operasjon
Future<void> queueOperation({
required String collection,
required String docId,
required SyncAction action,
required Map<String, dynamic> data,
}) async {
final op = SyncOperation(
id: _uuid.v4(),
collection: collection,
docId: docId,
action: action,
data: data,
timestamp: DateTime.now(),
);
await addToQueue(op);
}
}