mirror of
https://github.com/immich-app/immich.git
synced 2026-04-11 03:32:01 -04:00
wip
This commit is contained in:
parent
6ef7d2bb47
commit
dd215ec758
@ -249,13 +249,14 @@ class BackgroundWorkerBgService extends BackgroundWorkerFlutterApi {
|
||||
final networkCapabilities = await _ref?.read(connectivityApiProvider).getCapabilities() ?? [];
|
||||
return _ref
|
||||
?.read(uploadServiceProvider)
|
||||
.startForegroundUpload(
|
||||
.startUploadWithHttp(
|
||||
currentUser.id,
|
||||
networkCapabilities.isUnmetered,
|
||||
_cancellationToken,
|
||||
(_, __, ___, ____) {}, // onProgress - not needed for background
|
||||
(_, __) {}, // onSuccess - not needed for background
|
||||
(_) {}, // onError - not needed for background
|
||||
onProgress: (_, __, ___, ____) {},
|
||||
onSuccess: (_, __) {},
|
||||
onError: (_) {},
|
||||
onICloudProgress: (_, __) {},
|
||||
);
|
||||
},
|
||||
(error, stack) {
|
||||
|
||||
@ -93,7 +93,7 @@ class _DriftBackupPageState extends ConsumerState<DriftBackupPage> {
|
||||
Logger("DriftBackupPage").warning("Remote sync did not complete successfully, skipping backup");
|
||||
return;
|
||||
}
|
||||
await backupNotifier.startBackup(currentUser.id);
|
||||
await backupNotifier.startForegroundBackup(currentUser.id);
|
||||
}
|
||||
|
||||
Future<void> stopBackup() async {
|
||||
|
||||
@ -116,7 +116,7 @@ class _DriftBackupAlbumSelectionPageState extends ConsumerState<DriftBackupAlbum
|
||||
backupNotifier.stopBackup().whenComplete(
|
||||
() => backgroundSync.syncRemote().then((success) {
|
||||
if (success) {
|
||||
return backupNotifier.startBackup(user.id);
|
||||
return backupNotifier.startForegroundBackup(user.id);
|
||||
} else {
|
||||
Logger('DriftBackupAlbumSelectionPage').warning('Background sync failed, not starting backup');
|
||||
}
|
||||
|
||||
@ -63,7 +63,7 @@ class DriftBackupOptionsPage extends ConsumerWidget {
|
||||
backupNotifier.stopBackup().whenComplete(
|
||||
() => backgroundSync.syncRemote().then((success) {
|
||||
if (success) {
|
||||
return backupNotifier.startBackup(currentUser.id);
|
||||
return backupNotifier.startForegroundBackup(currentUser.id);
|
||||
} else {
|
||||
Logger('DriftBackupOptionsPage').warning('Background sync failed, not starting backup');
|
||||
}
|
||||
|
||||
@ -132,7 +132,7 @@ class SplashScreenPageState extends ConsumerState<SplashScreenPage> {
|
||||
if (isEnableBackup) {
|
||||
final currentUser = Store.tryGet(StoreKey.currentUser);
|
||||
if (currentUser != null) {
|
||||
unawaited(notifier.startBackup(currentUser.id));
|
||||
unawaited(notifier.startForegroundBackup(currentUser.id));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -179,7 +179,10 @@ class AppLifeCycleNotifier extends StateNotifier<AppLifeCycleEnum> {
|
||||
if (isEnableBackup) {
|
||||
final currentUser = Store.tryGet(StoreKey.currentUser);
|
||||
if (currentUser != null) {
|
||||
await _safeRun(_ref.read(driftBackupProvider.notifier).startBackup(currentUser.id), "handleBackupResume");
|
||||
await _safeRun(
|
||||
_ref.read(driftBackupProvider.notifier).startForegroundBackup(currentUser.id),
|
||||
"handleBackupResume",
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -393,7 +393,7 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||
state = state.copyWith(isSyncing: isSyncing);
|
||||
}
|
||||
|
||||
Future<void> startBackup(String userId) async {
|
||||
Future<void> startForegroundBackup(String userId) async {
|
||||
state = state.copyWith(error: BackupError.none);
|
||||
|
||||
final cancelToken = CancellationToken();
|
||||
@ -403,13 +403,13 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||
final hasWifi = networkCapabilities.isUnmetered;
|
||||
_logger.info('Network capabilities: $networkCapabilities, hasWifi/isUnmetered: $hasWifi');
|
||||
|
||||
return _uploadService.startForegroundUpload(
|
||||
return _uploadService.startUploadWithHttp(
|
||||
userId,
|
||||
hasWifi,
|
||||
cancelToken,
|
||||
_handleForegroundBackupProgress,
|
||||
_handleForegroundBackupSuccess,
|
||||
_handleForegroundBackupError,
|
||||
onProgress: _handleForegroundBackupProgress,
|
||||
onSuccess: _handleForegroundBackupSuccess,
|
||||
onError: _handleForegroundBackupError,
|
||||
onICloudProgress: _handleICloudProgress,
|
||||
);
|
||||
}
|
||||
@ -497,7 +497,7 @@ class DriftBackupNotifier extends StateNotifier<DriftBackupState> {
|
||||
|
||||
if (tasks.isEmpty) {
|
||||
_logger.info("Start backup with URLSession");
|
||||
return _uploadService.startBackupWithURLSession(userId);
|
||||
return _uploadService.startUploadWithURLSession(userId);
|
||||
}
|
||||
|
||||
_logger.info("Tasks to resume: ${tasks.length}");
|
||||
|
||||
@ -94,56 +94,7 @@ class UploadRepository {
|
||||
);
|
||||
}
|
||||
|
||||
Future<UploadResult> uploadSingleAsset({
|
||||
required File file,
|
||||
required String originalFileName,
|
||||
required Map<String, String> headers,
|
||||
required Map<String, String> fields,
|
||||
required Client httpClient,
|
||||
required CancellationToken cancelToken,
|
||||
required void Function(int bytes, int totalBytes) onProgress,
|
||||
}) async {
|
||||
return _uploadFile(
|
||||
file: file,
|
||||
originalFileName: originalFileName,
|
||||
headers: headers,
|
||||
fields: fields,
|
||||
httpClient: httpClient,
|
||||
cancelToken: cancelToken,
|
||||
onProgress: onProgress,
|
||||
logContext: 'assetUpload',
|
||||
);
|
||||
}
|
||||
|
||||
/// Upload live photo video part and return the video asset ID
|
||||
Future<String?> uploadLivePhotoVideo({
|
||||
required File livePhotoFile,
|
||||
required String originalFileName,
|
||||
required Map<String, String> headers,
|
||||
required Map<String, String> fields,
|
||||
required Client httpClient,
|
||||
required CancellationToken cancelToken,
|
||||
required void Function(int bytes, int totalBytes) onProgress,
|
||||
}) async {
|
||||
final result = await _uploadFile(
|
||||
file: livePhotoFile,
|
||||
originalFileName: originalFileName,
|
||||
headers: headers,
|
||||
fields: fields,
|
||||
httpClient: httpClient,
|
||||
cancelToken: cancelToken,
|
||||
onProgress: onProgress,
|
||||
logContext: 'livePhotoVideoUpload',
|
||||
);
|
||||
|
||||
if (result.isSuccess && result.remoteAssetId != null) {
|
||||
return result.remoteAssetId;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<UploadResult> _uploadFile({
|
||||
Future<UploadResult> uploadFile({
|
||||
required File file,
|
||||
required String originalFileName,
|
||||
required Map<String, String> headers,
|
||||
|
||||
@ -121,7 +121,7 @@ class UploadService {
|
||||
/// Find backup candidates
|
||||
/// Build the upload tasks
|
||||
/// Enqueue the tasks
|
||||
Future<void> startBackupWithURLSession(String userId) async {
|
||||
Future<void> startUploadWithURLSession(String userId) async {
|
||||
await _storageRepository.clearCache();
|
||||
|
||||
shouldAbortQueuingTasks = false;
|
||||
@ -146,14 +146,14 @@ class UploadService {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> startForegroundUpload(
|
||||
Future<void> startUploadWithHttp(
|
||||
String userId,
|
||||
bool hasWifi,
|
||||
CancellationToken cancelToken,
|
||||
void Function(String localAssetId, String filename, int bytes, int totalBytes) onProgress,
|
||||
void Function(String localAssetId, String remoteAssetId) onSuccess,
|
||||
void Function(String errorMessage) onError, {
|
||||
void Function(String localAssetId, double progress)? onICloudProgress,
|
||||
CancellationToken cancelToken, {
|
||||
required void Function(String localAssetId, String filename, int bytes, int totalBytes) onProgress,
|
||||
required void Function(String localAssetId, String remoteAssetId) onSuccess,
|
||||
required void Function(String errorMessage) onError,
|
||||
required void Function(String localAssetId, double progress) onICloudProgress,
|
||||
}) async {
|
||||
const concurrentUploads = 3;
|
||||
final httpClients = List.generate(concurrentUploads, (_) => Client());
|
||||
@ -186,7 +186,6 @@ class UploadService {
|
||||
|
||||
final requireWifi = _shouldRequireWiFi(asset);
|
||||
if (requireWifi && !hasWifi) {
|
||||
_logger.warning('Skipping upload for ${asset.id} because it requires WiFi');
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -194,9 +193,9 @@ class UploadService {
|
||||
asset,
|
||||
httpClient,
|
||||
cancelToken,
|
||||
onProgress,
|
||||
onSuccess,
|
||||
onError,
|
||||
onProgress: onProgress,
|
||||
onSuccess: onSuccess,
|
||||
onError: onError,
|
||||
onICloudProgress: onICloudProgress,
|
||||
);
|
||||
}
|
||||
@ -220,11 +219,11 @@ class UploadService {
|
||||
Future<void> _uploadSingleAsset(
|
||||
LocalAsset asset,
|
||||
Client httpClient,
|
||||
CancellationToken cancelToken,
|
||||
void Function(String id, String filename, int bytes, int totalBytes) onProgress,
|
||||
void Function(String localAssetId, String remoteAssetId) onSuccess,
|
||||
void Function(String errorMessage) onError, {
|
||||
void Function(String localAssetId, double progress)? onICloudProgress,
|
||||
CancellationToken cancelToken, {
|
||||
required void Function(String id, String filename, int bytes, int totalBytes) onProgress,
|
||||
required void Function(String localAssetId, String remoteAssetId) onSuccess,
|
||||
required void Function(String errorMessage) onError,
|
||||
required void Function(String localAssetId, double progress) onICloudProgress,
|
||||
}) async {
|
||||
File? file;
|
||||
File? livePhotoFile;
|
||||
@ -244,12 +243,10 @@ class UploadService {
|
||||
PMProgressHandler? progressHandler;
|
||||
StreamSubscription? progressSubscription;
|
||||
|
||||
if (onICloudProgress != null) {
|
||||
progressHandler = PMProgressHandler();
|
||||
progressSubscription = progressHandler.stream.listen((event) {
|
||||
onICloudProgress(asset.localId!, event.progress);
|
||||
});
|
||||
}
|
||||
progressHandler = PMProgressHandler();
|
||||
progressSubscription = progressHandler.stream.listen((event) {
|
||||
onICloudProgress(asset.localId!, event.progress);
|
||||
});
|
||||
|
||||
try {
|
||||
file = await _storageRepository.loadFileFromCloud(asset.id, progressHandler: progressHandler);
|
||||
@ -260,7 +257,7 @@ class UploadService {
|
||||
);
|
||||
}
|
||||
} finally {
|
||||
await progressSubscription?.cancel();
|
||||
await progressSubscription.cancel();
|
||||
}
|
||||
} else {
|
||||
// Get files locally
|
||||
@ -300,23 +297,28 @@ class UploadService {
|
||||
String? livePhotoVideoId;
|
||||
if (entity.isLivePhoto && livePhotoFile != null) {
|
||||
final livePhotoTitle = p.setExtension(originalFileName, p.extension(livePhotoFile.path));
|
||||
livePhotoVideoId = await _uploadRepository.uploadLivePhotoVideo(
|
||||
livePhotoFile: livePhotoFile,
|
||||
|
||||
final livePhotoResult = await _uploadRepository.uploadFile(
|
||||
file: livePhotoFile,
|
||||
originalFileName: livePhotoTitle,
|
||||
headers: headers,
|
||||
fields: fields,
|
||||
httpClient: httpClient,
|
||||
cancelToken: cancelToken,
|
||||
onProgress: (bytes, totalBytes) => onProgress(asset.localId!, livePhotoTitle, bytes, totalBytes),
|
||||
logContext: 'livePhotoVideo[${asset.localId}]',
|
||||
);
|
||||
|
||||
if (livePhotoResult.isSuccess && livePhotoResult.remoteAssetId != null) {
|
||||
livePhotoVideoId = livePhotoResult.remoteAssetId;
|
||||
}
|
||||
}
|
||||
|
||||
// Add livePhotoVideoId to fields if available
|
||||
if (livePhotoVideoId != null) {
|
||||
fields['livePhotoVideoId'] = livePhotoVideoId;
|
||||
}
|
||||
|
||||
final result = await _uploadRepository.uploadSingleAsset(
|
||||
final result = await _uploadRepository.uploadFile(
|
||||
file: file,
|
||||
originalFileName: originalFileName,
|
||||
headers: headers,
|
||||
@ -324,6 +326,7 @@ class UploadService {
|
||||
httpClient: httpClient,
|
||||
cancelToken: cancelToken,
|
||||
onProgress: (bytes, totalBytes) => onProgress(asset.localId!, originalFileName, bytes, totalBytes),
|
||||
logContext: 'asset[${asset.localId}]',
|
||||
);
|
||||
|
||||
if (result.isSuccess && result.remoteAssetId != null) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user