feat: mobile editing (#25397)

* feat: mobile editing

fix: openapi patch

this sucks :pepehands:

chore: migrate some changes from the filtering PR

chore: color tweak

fix: hide edit button on server versions

chore: translation

* chore: code review changes

chore: code review

* sealed class

* const constant

* enum

* concurrent queries

* chore: major cleanup to use riverpod provider

* fix: aspect ratio selection

* chore: typesafe websocket event parsing

* fix: wrong disable state for save button

* chore: remove isCancelled shim

* chore: cleanup postframe callback usage

* chore: clean import

---------

Co-authored-by: mertalev <101130780+mertalev@users.noreply.github.com>
This commit is contained in:
Brandon Wees
2026-04-15 09:26:40 -05:00
committed by GitHub
parent 8454cb2631
commit 6dd6053222
30 changed files with 1317 additions and 646 deletions
@@ -1,6 +1,7 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:http/http.dart';
import 'package:immich_mobile/constants/enums.dart';
import 'package:immich_mobile/domain/models/asset_edit.model.dart' hide AssetEditAction;
import 'package:immich_mobile/domain/models/stack.model.dart';
import 'package:immich_mobile/entities/asset.entity.dart';
import 'package:immich_mobile/providers/api.provider.dart';
@@ -105,6 +106,14 @@ class AssetApiRepository extends ApiRepository {
Future<void> updateRating(String assetId, int rating) {
return _api.updateAsset(assetId, UpdateAssetDto(rating: rating));
}
Future<AssetEditsResponseDto?> editAsset(String assetId, List<AssetEdit> edits) {
return _api.editAsset(assetId, AssetEditsCreateDto(edits: edits.map((e) => e.toApi()).toList()));
}
Future<void> removeEdits(String assetId) async {
return _api.removeAssetEdits(assetId);
}
}
extension on StackResponseDto {
@@ -112,3 +121,22 @@ extension on StackResponseDto {
return StackResponse(id: id, primaryAssetId: primaryAssetId, assetIds: assets.map((asset) => asset.id).toList());
}
}
extension on AssetEdit {
AssetEditActionItemDto toApi() {
return switch (this) {
CropEdit(:final parameters) => AssetEditActionItemDto(
action: AssetEditAction.crop,
parameters: parameters.toJson(),
),
RotateEdit(:final parameters) => AssetEditActionItemDto(
action: AssetEditAction.rotate,
parameters: parameters.toJson(),
),
MirrorEdit(:final parameters) => AssetEditActionItemDto(
action: AssetEditAction.mirror,
parameters: parameters.toJson(),
),
};
}
}