Implemented operation to delete asset in database

This commit is contained in:
Alex Tran 2022-02-13 13:46:54 -06:00
parent f7f4e9c710
commit 78dbe4061b
12 changed files with 135 additions and 48 deletions

View file

@ -0,0 +1,52 @@
import 'dart:convert';
class DeleteAssetResponse {
final String id;
final String status;
DeleteAssetResponse({
required this.id,
required this.status,
});
DeleteAssetResponse copyWith({
String? id,
String? status,
}) {
return DeleteAssetResponse(
id: id ?? this.id,
status: status ?? this.status,
);
}
Map<String, dynamic> toMap() {
return {
'id': id,
'status': status,
};
}
factory DeleteAssetResponse.fromMap(Map<String, dynamic> map) {
return DeleteAssetResponse(
id: map['id'] ?? '',
status: map['status'] ?? '',
);
}
String toJson() => json.encode(toMap());
factory DeleteAssetResponse.fromJson(String source) => DeleteAssetResponse.fromMap(json.decode(source));
@override
String toString() => 'DeleteAssetResponse(id: $id, status: $status)';
@override
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is DeleteAssetResponse && other.id == id && other.status == status;
}
@override
int get hashCode => id.hashCode ^ status.hashCode;
}

View file

@ -1,4 +1,5 @@
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:immich_mobile/modules/home/models/delete_asset_response.model.dart';
import 'package:immich_mobile/modules/home/services/asset.service.dart';
import 'package:immich_mobile/shared/models/immich_asset.model.dart';
import 'package:immich_mobile/shared/services/device_info.service.dart';
@ -29,6 +30,16 @@ class AssetNotifier extends StateNotifier<List<ImmichAsset>> {
var deviceId = deviceInfo["deviceId"];
// Delete asset on server
List<DeleteAssetResponse>? deleteAssetResult = await _assetService.deleteAssets(deleteAssets);
if (deleteAssetResult == null) {
return;
}
for (var asset in deleteAssetResult) {
if (asset.status == 'success') {
state = state.where((immichAsset) => immichAsset.id != asset.id).toList();
}
}
// Delete asset from device
}

View file

@ -1,7 +1,8 @@
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:immich_mobile/modules/home/models/get_all_asset_respose.model.dart';
import 'package:immich_mobile/modules/home/models/delete_asset_response.model.dart';
import 'package:immich_mobile/modules/home/models/get_all_asset_response.model.dart';
import 'package:immich_mobile/shared/models/immich_asset.model.dart';
import 'package:immich_mobile/shared/models/immich_asset_with_exif.model.dart';
import 'package:immich_mobile/shared/services/network.service.dart';
@ -89,7 +90,24 @@ class AssetService {
}
}
deleteAssets(Set<ImmichAsset> deleteAssets) async {
return null;
Future<List<DeleteAssetResponse>?> deleteAssets(Set<ImmichAsset> deleteAssets) async {
try {
var payload = [];
for (var asset in deleteAssets) {
payload.add(asset.id);
}
var res = await _networkService.deleteRequest(url: "asset/", data: {"ids": payload});
List<dynamic> decodedData = jsonDecode(res.toString());
List<DeleteAssetResponse> result = List.from(decodedData.map((a) => DeleteAssetResponse.fromMap(a)));
return result;
} catch (e) {
debugPrint("Error getAllAsset ${e.toString()}");
return null;
}
}
}

View file

@ -27,8 +27,10 @@ class DeleteDialog extends ConsumerWidget {
),
TextButton(
onPressed: () {
// onConfirmed();
ref.watch(assetProvider.notifier).deleteAssets(homePageState.selectedItems);
ref.watch(homePageStateProvider.notifier).disableMultiSelect();
Navigator.of(context).pop();
},
child: Text(
"Delete",

View file

@ -102,8 +102,6 @@ class ThumbnailImage extends HookConsumerWidget {
child: CircularProgressIndicator(value: downloadProgress.progress),
),
errorWidget: (context, url, error) {
debugPrint("Error Loading Thumbnail Widget $error");
cacheKey.value += 1;
return Icon(
Icons.image_not_supported_outlined,
color: Theme.of(context).primaryColor,

View file

@ -19,29 +19,14 @@ class HomePage extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
ScrollController _scrollController = useScrollController();
// List<ImmichAssetGroupByDate> _assetGroup = ref.watch(assetProvider);
var assetGroupByDateTime = ref.watch(assetGroupByDateTimeProvider);
List<Widget> _imageGridGroup = [];
var isMultiSelectEnable = ref.watch(homePageStateProvider).isMultiSelectEnable;
var homePageState = ref.watch(homePageStateProvider);
_scrollControllerCallback() {
var endOfPage = _scrollController.position.maxScrollExtent;
if (_scrollController.offset >= endOfPage - (endOfPage * 0.1) && !_scrollController.position.outOfRange) {
// ref.read(assetProvider.notifier).getOlderAsset();
}
}
useEffect(() {
ref.read(assetProvider.notifier).getAllAsset();
// ref.read(assetProvider.notifier).getAllAssetsWithPagination();
_scrollController.addListener(_scrollControllerCallback);
return () {
_scrollController.removeListener(_scrollControllerCallback);
};
return null;
}, []);
onPopBackFromBackupPage() {

View file

@ -15,7 +15,7 @@ class LoginForm extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final usernameController = useTextEditingController(text: 'testuser@email.com');
final passwordController = useTextEditingController(text: 'password');
final serverEndpointController = useTextEditingController(text: 'http://192.168.1.216:2283');
final serverEndpointController = useTextEditingController(text: 'http://192.168.1.103:2283');
return Center(
child: ConstrainedBox(

View file

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:hive_flutter/hive_flutter.dart';
@ -11,7 +13,7 @@ import 'package:immich_mobile/shared/services/backup.service.dart';
import 'package:photo_manager/photo_manager.dart';
class BackupNotifier extends StateNotifier<BackUpState> {
BackupNotifier(this.ref)
BackupNotifier({this.ref})
: super(
BackUpState(
backupProgress: BackUpProgressEnum.idle,
@ -32,9 +34,10 @@ class BackupNotifier extends StateNotifier<BackUpState> {
),
);
final Ref ref;
Ref? ref;
final BackupService _backupService = BackupService();
final ServerInfoService _serverInfoService = ServerInfoService();
final StreamController _onAssetBackupStreamCtrl = StreamController.broadcast();
void getBackupInfo() async {
_updateServerInfo();
@ -103,7 +106,7 @@ class BackupNotifier extends StateNotifier<BackUpState> {
state = state.copyWith(backupProgress: BackUpProgressEnum.idle, progressInPercentage: 0.0);
}
void _onAssetUploaded() {
void _onAssetUploaded(String deviceAssetId, String deviceId) {
state =
state.copyWith(backingUpAssetCount: state.backingUpAssetCount - 1, assetOnDatabase: state.assetOnDatabase + 1);
@ -136,36 +139,37 @@ class BackupNotifier extends StateNotifier<BackUpState> {
}
void resumeBackup() {
debugPrint("[resumeBackup]");
var authState = ref.read(authenticationProvider);
var authState = ref?.read(authenticationProvider);
// Check if user is login
var accessKey = Hive.box(userInfoBox).get(accessTokenKey);
// User has been logged out return
if (accessKey == null || !authState.isAuthenticated) {
debugPrint("[resumeBackup] not authenticated - abort");
return;
}
// Check if this device is enable backup by the user
if ((authState.deviceInfo.deviceId == authState.deviceId) && authState.deviceInfo.isAutoBackup) {
// check if backup is alreayd in process - then return
if (state.backupProgress == BackUpProgressEnum.inProgress) {
debugPrint("[resumeBackup] Backup is already in progress - abort");
if (authState != null) {
if (accessKey == null || !authState.isAuthenticated) {
debugPrint("[resumeBackup] not authenticated - abort");
return;
}
// Run backup
debugPrint("[resumeBackup] Start back up");
startBackupProcess();
}
// Check if this device is enable backup by the user
if ((authState.deviceInfo.deviceId == authState.deviceId) && authState.deviceInfo.isAutoBackup) {
// check if backup is alreayd in process - then return
if (state.backupProgress == BackUpProgressEnum.inProgress) {
debugPrint("[resumeBackup] Backup is already in progress - abort");
return;
}
debugPrint("[resumeBackup] User disables auto backup");
return;
// Run backup
debugPrint("[resumeBackup] Start back up");
startBackupProcess();
}
debugPrint("[resumeBackup] User disables auto backup");
return;
}
}
}
final backupProvider = StateNotifierProvider<BackupNotifier, BackUpState>((ref) {
return BackupNotifier(ref);
return BackupNotifier(ref: ref);
});

View file

@ -26,7 +26,7 @@ class BackupService {
return result.cast<String>();
}
backupAsset(List<AssetEntity> assetList, CancelToken cancelToken, Function singleAssetDoneCb,
backupAsset(List<AssetEntity> assetList, CancelToken cancelToken, Function(String, String) singleAssetDoneCb,
Function(int, int) uploadProgress) async {
var dio = Dio();
dio.interceptors.add(AuthenticatedRequestInterceptor());
@ -77,7 +77,7 @@ class BackupService {
);
if (res.statusCode == 201) {
singleAssetDoneCb();
singleAssetDoneCb(entity.id, deviceId);
}
}
} on DioError catch (e) {

View file

@ -7,6 +7,24 @@ import 'package:immich_mobile/constants/hive_box.dart';
import 'package:immich_mobile/utils/dio_http_interceptor.dart';
class NetworkService {
Future<dynamic> deleteRequest({required String url, dynamic data}) async {
try {
var dio = Dio();
dio.interceptors.add(AuthenticatedRequestInterceptor());
var savedEndpoint = Hive.box(userInfoBox).get(serverEndpointKey);
Response res = await dio.delete('$savedEndpoint/$url', data: data);
if (res.statusCode == 200) {
return res;
}
} on DioError catch (e) {
debugPrint("DioError: ${e.response}");
} catch (e) {
debugPrint("ERROR getRequest: ${e.toString()}");
}
}
Future<dynamic> getRequest({required String url}) async {
try {
var dio = Dio();

View file

@ -81,7 +81,6 @@ export class AssetController {
return await this.assetService.getAllAssets(authUser, query);
}
@Get('/')
async getAllAssetsNoPagination(@GetAuthUser() authUser: AuthUserDto) {
return await this.assetService.getAllAssetsNoPagination(authUser);