[client] Delete resource version [#19]

This commit is contained in:
Abhishek Shroff
2025-09-16 11:01:26 +05:30
parent 139dc6305e
commit 014adceddc
4 changed files with 131 additions and 19 deletions

View File

@@ -0,0 +1,80 @@
import 'package:offtheline/offtheline.dart';
import 'package:phylum/libphylum/actions/changes/update_resource_modified_change.dart';
import 'package:phylum/libphylum/actions/changes/update_resource_version_deleted_change.dart';
import 'package:phylum/libphylum/db/db.dart';
import 'package:phylum/libphylum/phylum_api_types.dart';
import 'action_resource.dart';
class ResourceVersionDeleteAction extends ResourceAction with JsonApiAction {
static const kActionName = 'resourceVersionDelete';
@override
String get actionName => kActionName;
@override
String get method => 'POST';
@override
String get endpoint => '/api/v1/fs/delete_version';
@override
Map<String, dynamic>? get requestBody => {
'path': '$resourceId:',
'version_id': versionId,
};
@override
List<LocalChange> get localChanges => [
UpdateResourceVersionDeletedChange(
objectId: resourceId,
),
UpdateResourceModifiedChange(
objectId: resourceId,
timestamp: timestamp,
),
];
@override
String get description => "Deleting version ${versionId.substring(0, 12)} of $resourceName";
@override
Map<String, dynamic> get props => {
'resourceId': resourceId,
'versionId': versionId,
'resourceName': resourceName,
'timestamp': timestamp.millisecondsSinceEpoch,
};
final String versionId;
final String resourceName;
final DateTime timestamp;
ResourceVersionDeleteAction._({
required super.resourceId,
required this.timestamp,
required this.resourceName,
required this.versionId,
});
ResourceVersionDeleteAction({
required Resource r,
required String versionId,
}) : this._(
resourceId: r.id,
versionId: versionId,
resourceName: r.name,
timestamp: DateTime.now(),
);
factory ResourceVersionDeleteAction.fromMap(Map<String, dynamic> map) {
return ResourceVersionDeleteAction._(
resourceId: map['resourceId'],
versionId: map['versionId'],
resourceName: map['resourceName'],
timestamp: DateTime.fromMillisecondsSinceEpoch(map['timestamp']),
);
}
@override
bool dependsOn(PhylumAction action) => action is ResourceAction && action.resourceId == resourceId;
}

View File

@@ -0,0 +1,17 @@
import 'package:offtheline/offtheline.dart';
import 'package:phylum/libphylum/db/db.dart';
class UpdateResourceVersionDeletedChange extends LocalChange<ResourceVersion> {
@override
final String objectId;
@override
String get description => 'Deleting Version';
const UpdateResourceVersionDeletedChange({required this.objectId});
@override
ResourceVersion? apply(ResourceVersion? data) {
return null;
}
}

View File

@@ -8,6 +8,7 @@ import 'package:phylum/libphylum/actions/action_resource_share.dart';
import 'package:phylum/libphylum/actions/action_resource_upload.dart';
import 'package:phylum/libphylum/actions/action_resource_bookmark_add.dart';
import 'package:phylum/libphylum/actions/action_resource_bookmark_remove.dart';
import 'package:phylum/libphylum/actions/action_resource_version_delete.dart';
import 'package:phylum/libphylum/actions/action_user_invite.dart';
const actionDeserializers = {
@@ -21,5 +22,6 @@ const actionDeserializers = {
ResourcePublinkCreateAction.kActionName: ResourcePublinkCreateAction.fromMap,
ResourceShareAction.kActionName: ResourceShareAction.fromMap,
ResourceUploadAction.kActionName: ResourceUploadAction.fromMap,
ResourceVersionDeleteAction.kActionName: ResourceVersionDeleteAction.fromMap,
UserInviteAction.kActionName: UserInviteAction.fromMap,
};

View File

@@ -2,6 +2,7 @@ import 'package:collection/collection.dart';
import 'package:drift/drift.dart' show TableOrViewStatements, OrderingTerm;
import 'package:flutter/material.dart';
import 'package:phylum/integrations/download_manager.dart';
import 'package:phylum/libphylum/actions/action_resource_version_delete.dart';
import 'package:phylum/libphylum/db/db.dart';
import 'package:phylum/libphylum/db/resource_helpers.dart';
import 'package:phylum/libphylum/phylum_account.dart';
@@ -39,25 +40,37 @@ class ResourceVersionsView extends StatelessWidget {
...versions.mapIndexed((i, v) => ListTile(
title: Text(v.sha256.isEmpty ? 'Unknown' : v.sha256.substring(0, 12)),
subtitle: Text('${v.created.formatShort()} \u2022 ${v.size.formatForDisplay()}'),
trailing: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.remove_red_eye),
onPressed: () async {
final resource = await account.db.getResource(resourceId);
if (resource == null || !context.mounted) return;
FilePreviewDialog.showVersions(context, resource, versions, i);
}),
IconButton(
icon: Icon(Icons.download),
onPressed: () async {
final r = await account.db.getResource(resourceId);
if (r == null || !context.mounted) return;
downloadResource(context, r, version: v);
}),
],
),
trailing: v.deleted
? Text(
'Deleted',
style: TextStyle(fontStyle: FontStyle.italic),
)
: Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
icon: Icon(Icons.remove_red_eye),
onPressed: () async {
final resource = await account.db.getResource(resourceId);
if (resource == null || !context.mounted) return;
FilePreviewDialog.showVersions(context, resource, versions, i);
}),
IconButton(
icon: Icon(Icons.download),
onPressed: () async {
final r = await account.db.getResource(resourceId);
if (r == null || !context.mounted) return;
downloadResource(context, r, version: v);
}),
IconButton(
icon: Icon(Icons.delete_forever),
onPressed: () async {
final r = await account.db.getResource(resourceId);
if (r == null || !context.mounted) return;
account.addAction(ResourceVersionDeleteAction(r: r, versionId: v.id));
}),
],
),
)),
],
);