You've already forked immich
mirror of
https://github.com/immich-app/immich.git
synced 2025-08-08 23:07:06 +02:00
refactor(server): stacks (#11453)
* refactor: stacks * mobile: get it built * chore: feedback * fix: sync and duplicates * mobile: remove old stack reference * chore: add primary asset id * revert change to asset entity * mobile: refactor mobile api * mobile: sync stack info after creating stack * mobile: update timeline after deleting stack * server: update asset updatedAt when stack is deleted * mobile: simplify action * mobile: rename to match dto property * fix: web test --------- Co-authored-by: Alex <alex.tran1502@gmail.com>
This commit is contained in:
@ -29,6 +29,7 @@ class ApiService implements Authentication {
|
||||
late ActivitiesApi activitiesApi;
|
||||
late DownloadApi downloadApi;
|
||||
late TrashApi trashApi;
|
||||
late StacksApi stacksApi;
|
||||
|
||||
ApiService() {
|
||||
final endpoint = Store.tryGet(StoreKey.serverEndpoint);
|
||||
@ -61,6 +62,7 @@ class ApiService implements Authentication {
|
||||
activitiesApi = ActivitiesApi(_apiClient);
|
||||
downloadApi = DownloadApi(_apiClient);
|
||||
trashApi = TrashApi(_apiClient);
|
||||
stacksApi = StacksApi(_apiClient);
|
||||
}
|
||||
|
||||
Future<String> resolveAndSetEndpoint(String serverUrl) async {
|
||||
|
@ -1,72 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/providers/api.provider.dart';
|
||||
import 'package:immich_mobile/services/api.service.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
class AssetStackService {
|
||||
AssetStackService(this._api);
|
||||
|
||||
final ApiService _api;
|
||||
|
||||
Future<void> updateStack(
|
||||
Asset parentAsset, {
|
||||
List<Asset>? childrenToAdd,
|
||||
List<Asset>? childrenToRemove,
|
||||
}) async {
|
||||
// Guard [local asset]
|
||||
if (parentAsset.remoteId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (childrenToAdd != null) {
|
||||
final toAdd = childrenToAdd
|
||||
.where((e) => e.isRemote)
|
||||
.map((e) => e.remoteId!)
|
||||
.toList();
|
||||
|
||||
await _api.assetsApi.updateAssets(
|
||||
AssetBulkUpdateDto(ids: toAdd, stackParentId: parentAsset.remoteId),
|
||||
);
|
||||
}
|
||||
|
||||
if (childrenToRemove != null) {
|
||||
final toRemove = childrenToRemove
|
||||
.where((e) => e.isRemote)
|
||||
.map((e) => e.remoteId!)
|
||||
.toList();
|
||||
await _api.assetsApi.updateAssets(
|
||||
AssetBulkUpdateDto(ids: toRemove, removeParent: true),
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
debugPrint("Error while updating stack children: ${error.toString()}");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateStackParent(Asset oldParent, Asset newParent) async {
|
||||
// Guard [local asset]
|
||||
if (oldParent.remoteId == null || newParent.remoteId == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await _api.assetsApi.updateStackParent(
|
||||
UpdateStackParentDto(
|
||||
oldParentId: oldParent.remoteId!,
|
||||
newParentId: newParent.remoteId!,
|
||||
),
|
||||
);
|
||||
} catch (error) {
|
||||
debugPrint("Error while updating stack parent: ${error.toString()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final assetStackServiceProvider = Provider(
|
||||
(ref) => AssetStackService(
|
||||
ref.watch(apiServiceProvider),
|
||||
),
|
||||
);
|
79
mobile/lib/services/stack.service.dart
Normal file
79
mobile/lib/services/stack.service.dart
Normal file
@ -0,0 +1,79 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:immich_mobile/entities/asset.entity.dart';
|
||||
import 'package:immich_mobile/providers/api.provider.dart';
|
||||
import 'package:immich_mobile/providers/db.provider.dart';
|
||||
import 'package:immich_mobile/services/api.service.dart';
|
||||
import 'package:isar/isar.dart';
|
||||
import 'package:openapi/api.dart';
|
||||
|
||||
class StackService {
|
||||
StackService(this._api, this._db);
|
||||
|
||||
final ApiService _api;
|
||||
final Isar _db;
|
||||
|
||||
Future<StackResponseDto?> getStack(String stackId) async {
|
||||
try {
|
||||
return _api.stacksApi.getStack(stackId);
|
||||
} catch (error) {
|
||||
debugPrint("Error while fetching stack: $error");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<StackResponseDto?> createStack(List<String> assetIds) async {
|
||||
try {
|
||||
return _api.stacksApi.createStack(
|
||||
StackCreateDto(assetIds: assetIds),
|
||||
);
|
||||
} catch (error) {
|
||||
debugPrint("Error while creating stack: $error");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<StackResponseDto?> updateStack(
|
||||
String stackId,
|
||||
String primaryAssetId,
|
||||
) async {
|
||||
try {
|
||||
return await _api.stacksApi.updateStack(
|
||||
stackId,
|
||||
StackUpdateDto(primaryAssetId: primaryAssetId),
|
||||
);
|
||||
} catch (error) {
|
||||
debugPrint("Error while updating stack children: $error");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
Future<void> deleteStack(String stackId, List<Asset> assets) async {
|
||||
try {
|
||||
await _api.stacksApi.deleteStack(stackId);
|
||||
|
||||
// Update local database to trigger rerendering
|
||||
final List<Asset> removeAssets = [];
|
||||
for (final asset in assets) {
|
||||
asset.stackId = null;
|
||||
asset.stackPrimaryAssetId = null;
|
||||
asset.stackCount = 0;
|
||||
|
||||
removeAssets.add(asset);
|
||||
}
|
||||
|
||||
_db.writeTxn(() async {
|
||||
await _db.assets.putAll(removeAssets);
|
||||
});
|
||||
} catch (error) {
|
||||
debugPrint("Error while deleting stack: $error");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final stackServiceProvider = Provider(
|
||||
(ref) => StackService(
|
||||
ref.watch(apiServiceProvider),
|
||||
ref.watch(dbProvider),
|
||||
),
|
||||
);
|
Reference in New Issue
Block a user