|
@@ -2,8 +2,11 @@ import 'dart:async';
|
|
import 'dart:io';
|
|
import 'dart:io';
|
|
|
|
|
|
import 'package:logger/logger.dart';
|
|
import 'package:logger/logger.dart';
|
|
|
|
+import 'package:myapp/core/event_bus.dart';
|
|
import 'package:myapp/db/db_helper.dart';
|
|
import 'package:myapp/db/db_helper.dart';
|
|
|
|
+import 'package:myapp/events/user_authenticated_event.dart';
|
|
import 'package:myapp/photo_loader.dart';
|
|
import 'package:myapp/photo_loader.dart';
|
|
|
|
+import 'package:myapp/photo_provider.dart';
|
|
import 'package:path/path.dart';
|
|
import 'package:path/path.dart';
|
|
import 'package:path_provider/path_provider.dart';
|
|
import 'package:path_provider/path_provider.dart';
|
|
import 'package:photo_manager/photo_manager.dart';
|
|
import 'package:photo_manager/photo_manager.dart';
|
|
@@ -12,25 +15,33 @@ import 'package:dio/dio.dart';
|
|
import 'package:myapp/models/photo.dart';
|
|
import 'package:myapp/models/photo.dart';
|
|
import 'package:myapp/core/constants.dart' as Constants;
|
|
import 'package:myapp/core/constants.dart' as Constants;
|
|
|
|
|
|
|
|
+import 'events/remote_sync_event.dart';
|
|
|
|
+
|
|
class PhotoSyncManager {
|
|
class PhotoSyncManager {
|
|
final _logger = Logger();
|
|
final _logger = Logger();
|
|
final _dio = Dio();
|
|
final _dio = Dio();
|
|
- bool _isLoadInProgress = false;
|
|
|
|
|
|
+ bool _isSyncInProgress = false;
|
|
|
|
|
|
static final _lastSyncTimestampKey = "last_sync_timestamp_0";
|
|
static final _lastSyncTimestampKey = "last_sync_timestamp_0";
|
|
static final _lastDBUpdateTimestampKey = "last_db_update_timestamp";
|
|
static final _lastDBUpdateTimestampKey = "last_db_update_timestamp";
|
|
|
|
|
|
- PhotoSyncManager._privateConstructor();
|
|
|
|
|
|
+ PhotoSyncManager._privateConstructor() {
|
|
|
|
+ Bus.instance.on<UserAuthenticatedEvent>().listen((event) {
|
|
|
|
+ sync();
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
static final PhotoSyncManager instance =
|
|
static final PhotoSyncManager instance =
|
|
PhotoSyncManager._privateConstructor();
|
|
PhotoSyncManager._privateConstructor();
|
|
|
|
|
|
- Future<void> load(List<AssetPathEntity> pathEntities) async {
|
|
|
|
- if (_isLoadInProgress) {
|
|
|
|
- _logger.w("Load already in progress, skipping.");
|
|
|
|
|
|
+ Future<void> sync() async {
|
|
|
|
+ if (_isSyncInProgress) {
|
|
|
|
+ _logger.w("Sync already in progress, skipping.");
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- _isLoadInProgress = true;
|
|
|
|
- _logger.i("Loading...");
|
|
|
|
|
|
+ _isSyncInProgress = true;
|
|
|
|
+ _logger.i("Syncing...");
|
|
|
|
+
|
|
final prefs = await SharedPreferences.getInstance();
|
|
final prefs = await SharedPreferences.getInstance();
|
|
var lastDBUpdateTimestamp = prefs.getInt(_lastDBUpdateTimestampKey);
|
|
var lastDBUpdateTimestamp = prefs.getInt(_lastDBUpdateTimestampKey);
|
|
if (lastDBUpdateTimestamp == null) {
|
|
if (lastDBUpdateTimestamp == null) {
|
|
@@ -38,6 +49,8 @@ class PhotoSyncManager {
|
|
await _initializeDirectories();
|
|
await _initializeDirectories();
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ await PhotoProvider.instance.refreshGalleryList();
|
|
|
|
+ final pathEntities = PhotoProvider.instance.list;
|
|
final photos = List<Photo>();
|
|
final photos = List<Photo>();
|
|
for (AssetPathEntity pathEntity in pathEntities) {
|
|
for (AssetPathEntity pathEntity in pathEntities) {
|
|
if (Platform.isIOS || pathEntity.name != "Recent") {
|
|
if (Platform.isIOS || pathEntity.name != "Recent") {
|
|
@@ -56,16 +69,15 @@ class PhotoSyncManager {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (photos.isEmpty) {
|
|
if (photos.isEmpty) {
|
|
- _isLoadInProgress = false;
|
|
|
|
- return;
|
|
|
|
|
|
+ _isSyncInProgress = false;
|
|
|
|
+ _syncPhotos().then((_) {
|
|
|
|
+ _deletePhotos();
|
|
|
|
+ });
|
|
} else {
|
|
} else {
|
|
photos.sort((first, second) =>
|
|
photos.sort((first, second) =>
|
|
first.createTimestamp.compareTo(second.createTimestamp));
|
|
first.createTimestamp.compareTo(second.createTimestamp));
|
|
_updateDatabase(photos, prefs, lastDBUpdateTimestamp).then((_) {
|
|
_updateDatabase(photos, prefs, lastDBUpdateTimestamp).then((_) {
|
|
- _isLoadInProgress = false;
|
|
|
|
- _syncPhotos().then((_) {
|
|
|
|
- _deletePhotos();
|
|
|
|
- });
|
|
|
|
|
|
+ _isSyncInProgress = false;
|
|
});
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -91,9 +103,11 @@ class PhotoSyncManager {
|
|
_logger.i("Last sync timestamp: " + lastSyncTimestamp.toString());
|
|
_logger.i("Last sync timestamp: " + lastSyncTimestamp.toString());
|
|
|
|
|
|
_getDiff(lastSyncTimestamp).then((diff) {
|
|
_getDiff(lastSyncTimestamp).then((diff) {
|
|
- _downloadDiff(diff, prefs).then((_) {
|
|
|
|
- _uploadDiff(prefs);
|
|
|
|
- });
|
|
|
|
|
|
+ if (diff != null) {
|
|
|
|
+ _downloadDiff(diff, prefs).then((_) {
|
|
|
|
+ _uploadDiff(prefs);
|
|
|
|
+ });
|
|
|
|
+ }
|
|
});
|
|
});
|
|
|
|
|
|
// TODO: Fix race conditions triggered due to concurrent syncs.
|
|
// TODO: Fix race conditions triggered due to concurrent syncs.
|
|
@@ -121,7 +135,7 @@ class PhotoSyncManager {
|
|
var localPath = path + basename(photo.remotePath);
|
|
var localPath = path + basename(photo.remotePath);
|
|
await _dio
|
|
await _dio
|
|
.download(Constants.ENDPOINT + "/" + photo.remotePath, localPath)
|
|
.download(Constants.ENDPOINT + "/" + photo.remotePath, localPath)
|
|
- .catchError(_onError);
|
|
|
|
|
|
+ .catchError((e) => _logger.e(e));
|
|
// TODO: Save path
|
|
// TODO: Save path
|
|
photo.pathName = localPath;
|
|
photo.pathName = localPath;
|
|
await DatabaseHelper.instance.insertPhoto(photo);
|
|
await DatabaseHelper.instance.insertPhoto(photo);
|
|
@@ -135,14 +149,15 @@ class PhotoSyncManager {
|
|
queryParameters: {
|
|
queryParameters: {
|
|
"user": Constants.USER,
|
|
"user": Constants.USER,
|
|
"lastSyncTimestamp": lastSyncTimestamp
|
|
"lastSyncTimestamp": lastSyncTimestamp
|
|
- }).catchError(_onError);
|
|
|
|
- _logger.i(response.toString());
|
|
|
|
|
|
+ }).catchError((e) => _logger.e(e));
|
|
if (response != null) {
|
|
if (response != null) {
|
|
|
|
+ Bus.instance.fire(RemoteSyncEvent(true));
|
|
return (response.data["diff"] as List)
|
|
return (response.data["diff"] as List)
|
|
.map((photo) => new Photo.fromJson(photo))
|
|
.map((photo) => new Photo.fromJson(photo))
|
|
.toList();
|
|
.toList();
|
|
} else {
|
|
} else {
|
|
- return List<Photo>();
|
|
|
|
|
|
+ Bus.instance.fire(RemoteSyncEvent(false));
|
|
|
|
+ return null;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
@@ -158,7 +173,7 @@ class PhotoSyncManager {
|
|
_logger.i(response.toString());
|
|
_logger.i(response.toString());
|
|
var photo = Photo.fromJson(response.data);
|
|
var photo = Photo.fromJson(response.data);
|
|
return photo;
|
|
return photo;
|
|
- }).catchError(_onError);
|
|
|
|
|
|
+ }).catchError((e) => _logger.e(e));
|
|
}
|
|
}
|
|
|
|
|
|
Future<void> _deletePhotos() async {
|
|
Future<void> _deletePhotos() async {
|
|
@@ -174,11 +189,7 @@ class PhotoSyncManager {
|
|
return _dio.post(Constants.ENDPOINT + "/delete", queryParameters: {
|
|
return _dio.post(Constants.ENDPOINT + "/delete", queryParameters: {
|
|
"user": Constants.USER,
|
|
"user": Constants.USER,
|
|
"fileID": photo.uploadedFileId
|
|
"fileID": photo.uploadedFileId
|
|
- }).catchError((e) => _onError(e));
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- void _onError(error) {
|
|
|
|
- _logger.e(error);
|
|
|
|
|
|
+ }).catchError((e) => _logger.e(e));
|
|
}
|
|
}
|
|
|
|
|
|
Future _initializeDirectories() async {
|
|
Future _initializeDirectories() async {
|