offline_first_sync 1.1.3
offline_first_sync: ^1.1.3 copied to clipboard
Intelligent offline-first data management with automatic sync, conflict resolution, and visual status indicators
offline_first_sync #
An intelligent offline-first data management package for Flutter that automatically syncs when online, handles conflicts, and provides visual indicators of sync status.
Features #
- 🔄 Automatic Sync: Intelligent syncing when network becomes available
- 📱 Offline-First: All operations work offline with local storage
- ⚡ Conflict Resolution: Multiple strategies for handling sync conflicts
- 🎨 Visual Indicators: Beautiful UI components for sync status
- 🗄️ Local Storage: SQLite-based local persistence
- 🌐 Network Aware: Automatic network connectivity detection
- 🔧 Customizable: Flexible sync intervals and strategies
Installation #
Add this to your package's pubspec.yaml file:
dependencies:
offline_first_sync: ^1.0.0
Quick Start #
1. Initialize SyncManager #
import 'package:offline_first_sync/offline_first_sync.dart';
final syncClient = HttpSyncClient(
baseUrl: 'https://your-api.com/api',
headers: {'Authorization': 'Bearer your-token'},
);
final syncManager = SyncManager(
client: syncClient,
syncInterval: Duration(minutes: 5),
);
2. Add Sync Items #
// Create a new item
await syncManager.addSyncItem(
entityType: 'todos',
entityId: 'todo-123',
data: {'title': 'Buy groceries', 'completed': false},
action: SyncAction.create,
);
// Update an existing item
await syncManager.addSyncItem(
entityType: 'todos',
entityId: 'todo-123',
data: {'title': 'Buy groceries', 'completed': true},
action: SyncAction.update,
);
// Delete an item
await syncManager.addSyncItem(
entityType: 'todos',
entityId: 'todo-123',
data: {},
action: SyncAction.delete,
);
3. Monitor Sync Status #
StreamBuilder<SyncStatus>(
stream: syncManager.statusStream,
builder: (context, snapshot) {
final status = snapshot.data;
return SyncStatusIndicator(
status: status,
onTap: () => showSyncDetails(),
);
},
)
4. Handle Conflicts #
syncManager.conflictsStream.listen((conflicts) {
for (final conflict in conflicts) {
// Show conflict resolution UI
showConflictResolutionDialog(conflict);
}
});
// Resolve conflict
await syncManager.resolveConflict(
conflictItem.id,
ConflictResolutionStrategy.clientWins,
);
UI Components #
SyncStatusIndicator #
A compact status indicator showing current sync state:
SyncStatusIndicator(
status: syncStatus,
showText: true,
onTap: () => showSyncDetails(),
)
SyncFab #
A floating action button for manual sync:
SyncFab(
status: syncStatus,
onPressed: () => syncManager.sync(),
tooltip: 'Sync now',
)
Conflict Resolution Strategies #
- ClientWins: Always use local data
- ServerWins: Always use server data
- LastWriteWins: Use most recently modified data
- Merge: Automatically merge both versions
- Manual: Let user manually resolve conflicts
Custom Sync Client #
Implement your own sync client:
class CustomSyncClient implements SyncClient {
@override
Future<SyncResponse> syncItem(SyncItem item) async {
// Your custom sync logic
return SyncResponse(success: true);
}
@override
Future<Map<String, dynamic>?> fetchLatestData(
String entityType,
String entityId
) async {
// Fetch latest data from your backend
return {'data': 'from server'};
}
}
Advanced Usage #
Custom Storage #
final customStorage = LocalStorage();
final syncManager = SyncManager(
client: syncClient,
storage: customStorage,
);
Retry Failed Items #
await syncManager.retryFailed();
Clear Sync Queue #
await syncManager.clearSyncQueue();
Manual Sync #
await syncManager.sync();
Example #
See the /example folder for a complete todo app implementation using offline_first_sync.
Contributing #
Contributions are welcome! Please read our contributing guidelines and submit pull requests to our repository.
License #
This project is licensed under the MIT License - see the LICENSE file for details.