refactor(mobile): reworked Asset, store all required fields from local & remote (#1539)

replace usage of AssetResponseDto with Asset

Add new class ExifInfo to store data from ExifResponseDto
This commit is contained in:
Fynn Petersen-Frey 2023-02-04 21:42:42 +01:00 committed by GitHub
parent 7bd2455175
commit 0048662182
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
28 changed files with 626 additions and 504 deletions

View file

@ -4,8 +4,8 @@ import 'package:flutter/foundation.dart';
import 'package:hive/hive.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/constants/hive_box.dart';
import 'package:immich_mobile/modules/home/services/asset.service.dart';
import 'package:immich_mobile/modules/home/services/asset_cache.service.dart';
import 'package:immich_mobile/shared/services/asset.service.dart';
import 'package:immich_mobile/shared/services/asset_cache.service.dart';
import 'package:immich_mobile/modules/home/ui/asset_grid/asset_grid_data_structure.dart';
import 'package:immich_mobile/modules/settings/providers/app_settings.provider.dart';
import 'package:immich_mobile/modules/settings/services/app_settings.service.dart';
@ -36,7 +36,7 @@ class AssetsState {
return AssetsState([...allAssets, ...toAdd]);
}
_groupByDate() async {
Future<Map<String, List<Asset>>> _groupByDate() async {
sortCompare(List<Asset> assets) {
assets.sortByCompare<DateTime>(
(e) => e.createdAt,
@ -50,11 +50,11 @@ class AssetsState {
return await compute(sortCompare, allAssets.toList());
}
static fromAssetList(List<Asset> assets) {
static AssetsState fromAssetList(List<Asset> assets) {
return AssetsState(assets);
}
static empty() {
static AssetsState empty() {
return AssetsState([]);
}
}
@ -82,7 +82,10 @@ class AssetNotifier extends StateNotifier<AssetsState> {
this._settingsService,
) : super(AssetsState.fromAssetList([]));
_updateAssetsState(List<Asset> newAssetList, {bool cache = true}) async {
Future<void> _updateAssetsState(
List<Asset> newAssetList, {
bool cache = true,
}) async {
if (cache) {
_assetCacheService.put(newAssetList);
}
@ -101,20 +104,26 @@ class AssetNotifier extends StateNotifier<AssetsState> {
final stopwatch = Stopwatch();
try {
_getAllAssetInProgress = true;
final bool isCacheValid = await _assetCacheService.isValid();
bool isCacheValid = await _assetCacheService.isValid();
stopwatch.start();
final Box box = Hive.box(userInfoBox);
if (isCacheValid && state.allAssets.isEmpty) {
final List<Asset>? cachedData = await _assetCacheService.get();
if (cachedData == null) {
isCacheValid = false;
log.warning("Cached asset data is invalid, fetching new data");
} else {
await _updateAssetsState(cachedData, cache: false);
log.info(
"Reading assets ${state.allAssets.length} from cache: ${stopwatch.elapsedMilliseconds}ms",
);
}
stopwatch.reset();
}
final localTask = _assetService.getLocalAssets(urgent: !isCacheValid);
final remoteTask = _assetService.getRemoteAssets(
etag: isCacheValid ? box.get(assetEtagKey) : null,
);
if (isCacheValid && state.allAssets.isEmpty) {
await _updateAssetsState(await _assetCacheService.get(), cache: false);
log.info(
"Reading assets ${state.allAssets.length} from cache: ${stopwatch.elapsedMilliseconds}ms",
);
stopwatch.reset();
}
int remoteBegin = state.allAssets.indexWhere((a) => a.isRemote);
remoteBegin = remoteBegin == -1 ? state.allAssets.length : remoteBegin;
@ -184,7 +193,7 @@ class AssetNotifier extends StateNotifier<AssetsState> {
_updateAssetsState([]);
}
onNewAssetUploaded(AssetResponseDto newAsset) {
void onNewAssetUploaded(Asset newAsset) {
final int i = state.allAssets.indexWhere(
(a) =>
a.isRemote ||
@ -192,13 +201,13 @@ class AssetNotifier extends StateNotifier<AssetsState> {
);
if (i == -1 || state.allAssets[i].deviceAssetId != newAsset.deviceAssetId) {
_updateAssetsState([...state.allAssets, Asset.remote(newAsset)]);
_updateAssetsState([...state.allAssets, newAsset]);
} else {
// order is important to keep all local-only assets at the beginning!
_updateAssetsState([
...state.allAssets.slice(0, i),
...state.allAssets.slice(i + 1),
Asset.remote(newAsset),
newAsset,
]);
// TODO here is a place to unify local/remote assets by replacing the
// local-only asset in the state with a local&remote asset
@ -230,7 +239,7 @@ class AssetNotifier extends StateNotifier<AssetsState> {
// Delete asset from device
for (final Asset asset in assetsToDelete) {
if (asset.isLocal) {
local.add(asset.id);
local.add(asset.localId!);
} else if (asset.deviceId == deviceId) {
// Delete asset on device if it is still present
var localAsset = await AssetEntity.fromId(asset.deviceAssetId);
@ -252,8 +261,7 @@ class AssetNotifier extends StateNotifier<AssetsState> {
Future<Iterable<String>> _deleteRemoteAssets(
Set<Asset> assetsToDelete,
) async {
final Iterable<AssetResponseDto> remote =
assetsToDelete.where((e) => e.isRemote).map((e) => e.remote!);
final Iterable<Asset> remote = assetsToDelete.where((e) => e.isRemote);
final List<DeleteAssetResponseDto> deleteAssetResult =
await _assetService.deleteAssets(remote) ?? [];
return deleteAssetResult