2022-07-13 14:23:48 +02:00
|
|
|
import 'dart:async';
|
2022-02-03 18:06:44 +02:00
|
|
|
|
|
|
|
import 'package:flutter/material.dart';
|
2022-11-08 19:00:24 +02:00
|
|
|
import 'package:hive/hive.dart';
|
2022-06-25 20:46:51 +02:00
|
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
2022-11-08 19:00:24 +02:00
|
|
|
import 'package:immich_mobile/constants/hive_box.dart';
|
|
|
|
import 'package:immich_mobile/modules/backup/background_service/background.service.dart';
|
|
|
|
import 'package:immich_mobile/modules/backup/models/hive_backup_albums.model.dart';
|
|
|
|
import 'package:immich_mobile/modules/backup/services/backup.service.dart';
|
|
|
|
import 'package:immich_mobile/shared/models/asset.dart';
|
2022-08-03 07:04:34 +02:00
|
|
|
import 'package:immich_mobile/shared/providers/api.provider.dart';
|
2022-07-13 14:23:48 +02:00
|
|
|
import 'package:immich_mobile/shared/services/api.service.dart';
|
|
|
|
import 'package:openapi/api.dart';
|
2022-11-21 14:13:14 +02:00
|
|
|
import 'package:photo_manager/photo_manager.dart';
|
2022-02-03 18:06:44 +02:00
|
|
|
|
2022-07-13 14:23:48 +02:00
|
|
|
final assetServiceProvider = Provider(
|
|
|
|
(ref) => AssetService(
|
|
|
|
ref.watch(apiServiceProvider),
|
2022-11-08 19:00:24 +02:00
|
|
|
ref.watch(backupServiceProvider),
|
|
|
|
ref.watch(backgroundServiceProvider),
|
2022-07-13 14:23:48 +02:00
|
|
|
),
|
|
|
|
);
|
2022-06-25 20:46:51 +02:00
|
|
|
|
2022-02-03 18:06:44 +02:00
|
|
|
class AssetService {
|
2022-07-13 14:23:48 +02:00
|
|
|
final ApiService _apiService;
|
2022-11-08 19:00:24 +02:00
|
|
|
final BackupService _backupService;
|
|
|
|
final BackgroundService _backgroundService;
|
2022-02-03 18:06:44 +02:00
|
|
|
|
2022-11-08 19:00:24 +02:00
|
|
|
AssetService(this._apiService, this._backupService, this._backgroundService);
|
2022-02-07 04:31:32 +02:00
|
|
|
|
2022-11-08 19:00:24 +02:00
|
|
|
/// Returns all local, remote assets in that order
|
|
|
|
Future<List<Asset>> getAllAsset({bool urgent = false}) async {
|
|
|
|
final List<Asset> assets = [];
|
2022-02-07 04:31:32 +02:00
|
|
|
try {
|
2022-11-08 19:00:24 +02:00
|
|
|
// not using `await` here to fetch local & remote assets concurrently
|
|
|
|
final Future<List<AssetResponseDto>?> remoteTask =
|
|
|
|
_apiService.assetApi.getAllAssets();
|
|
|
|
final Iterable<AssetEntity> newLocalAssets;
|
|
|
|
final List<AssetEntity> localAssets = await _getLocalAssets(urgent);
|
|
|
|
final List<AssetResponseDto> remoteAssets = await remoteTask ?? [];
|
|
|
|
if (remoteAssets.isNotEmpty && localAssets.isNotEmpty) {
|
|
|
|
final String deviceId = Hive.box(userInfoBox).get(deviceIdKey);
|
|
|
|
final Set<String> existingIds = remoteAssets
|
|
|
|
.where((e) => e.deviceId == deviceId)
|
|
|
|
.map((e) => e.deviceAssetId)
|
|
|
|
.toSet();
|
|
|
|
newLocalAssets = localAssets.where((e) => !existingIds.contains(e.id));
|
|
|
|
} else {
|
|
|
|
newLocalAssets = localAssets;
|
|
|
|
}
|
|
|
|
|
|
|
|
assets.addAll(newLocalAssets.map((e) => Asset.local(e)));
|
|
|
|
// the order (first all local, then remote assets) is important!
|
|
|
|
assets.addAll(remoteAssets.map((e) => Asset.remote(e)));
|
2022-02-07 04:31:32 +02:00
|
|
|
} catch (e) {
|
2022-07-13 14:23:48 +02:00
|
|
|
debugPrint("Error [getAllAsset] ${e.toString()}");
|
2022-11-08 19:00:24 +02:00
|
|
|
}
|
|
|
|
return assets;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// if [urgent] is `true`, do not block by waiting on the background service
|
|
|
|
/// to finish running. Returns an empty list instead after a timeout.
|
|
|
|
Future<List<AssetEntity>> _getLocalAssets(bool urgent) async {
|
|
|
|
try {
|
|
|
|
final Future<bool> hasAccess = urgent
|
|
|
|
? _backgroundService.hasAccess
|
|
|
|
.timeout(const Duration(milliseconds: 250))
|
|
|
|
: _backgroundService.hasAccess;
|
|
|
|
if (!await hasAccess) {
|
|
|
|
throw Exception("Error [getAllAsset] failed to gain access");
|
|
|
|
}
|
|
|
|
final box = await Hive.openBox<HiveBackupAlbums>(hiveBackupInfoBox);
|
|
|
|
final HiveBackupAlbums? backupAlbumInfo = box.get(backupInfoKey);
|
|
|
|
|
|
|
|
return backupAlbumInfo != null
|
|
|
|
? await _backupService
|
|
|
|
.buildUploadCandidates(backupAlbumInfo.deepCopy())
|
|
|
|
: [];
|
|
|
|
} catch (e) {
|
|
|
|
debugPrint("Error [_getLocalAssets] ${e.toString()}");
|
|
|
|
return [];
|
2022-02-07 04:31:32 +02:00
|
|
|
}
|
2022-02-03 18:06:44 +02:00
|
|
|
}
|
2022-02-11 04:40:11 +02:00
|
|
|
|
2022-11-08 19:00:24 +02:00
|
|
|
Future<Asset?> getAssetById(String assetId) async {
|
2022-02-11 04:40:11 +02:00
|
|
|
try {
|
2022-11-08 19:00:24 +02:00
|
|
|
return Asset.remote(await _apiService.assetApi.getAssetById(assetId));
|
2022-02-13 23:10:42 +02:00
|
|
|
} catch (e) {
|
2022-07-13 14:23:48 +02:00
|
|
|
debugPrint("Error [getAssetById] ${e.toString()}");
|
2022-02-13 23:10:42 +02:00
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-07-13 14:23:48 +02:00
|
|
|
Future<List<DeleteAssetResponseDto>?> deleteAssets(
|
2022-11-08 19:00:24 +02:00
|
|
|
Iterable<AssetResponseDto> deleteAssets,
|
2022-07-13 14:23:48 +02:00
|
|
|
) async {
|
2022-02-13 23:10:42 +02:00
|
|
|
try {
|
2022-11-08 19:00:24 +02:00
|
|
|
final List<String> payload = [];
|
2022-02-13 23:10:42 +02:00
|
|
|
|
2022-11-08 19:00:24 +02:00
|
|
|
for (final asset in deleteAssets) {
|
2022-02-13 23:10:42 +02:00
|
|
|
payload.add(asset.id);
|
|
|
|
}
|
|
|
|
|
2022-07-13 14:23:48 +02:00
|
|
|
return await _apiService.assetApi
|
|
|
|
.deleteAsset(DeleteAssetDto(ids: payload));
|
2022-02-11 04:40:11 +02:00
|
|
|
} catch (e) {
|
|
|
|
debugPrint("Error getAllAsset ${e.toString()}");
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
}
|
2022-02-03 18:06:44 +02:00
|
|
|
}
|