121 lines
3.4 KiB
Dart
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);
|
|
}
|
|
}
|