feat(explorer): add empty recycle bin button & move restore action to top quick actions (close #3473)

master
Aaron Liu 3 days ago
parent 1d091c4100
commit b2e808e6ca

@ -1 +1 @@
Subproject commit 3235069f05124a39c57a7347dc1cb53ebbd2dad9
Subproject commit 2e995f1d4676d15b714dd82cb3aefe2e7697fcea

@ -43,6 +43,8 @@ type (
Rename(ctx context.Context, path *fs.URI, newName string) (fs.File, error)
// Delete deletes a group of file or directory. UnlinkOnly indicates whether to delete file record in DB only.
Delete(ctx context.Context, path []*fs.URI, opts ...fs.Option) error
// EmptyTrash hard-deletes every top-level item in the current user's trash bin.
EmptyTrash(ctx context.Context) error
// Restore restores a group of files
Restore(ctx context.Context, path ...*fs.URI) error
// MoveOrCopy moves or copies a group of files

@ -157,6 +157,46 @@ func (m *manager) SoftDelete(ctx context.Context, path ...*fs.URI) error {
return m.fs.SoftDelete(ctx, path...)
}
// EmptyTrash hard-deletes every top-level item in the current user's trash bin.
// It iterates through all pages of the trash listing and performs the deletion in
// batches. Returns nil if the trash is already empty.
func (m *manager) EmptyTrash(ctx context.Context) error {
trashUri, err := fs.NewUriFromString(fmt.Sprintf("%s://%s", constants.CloudreveScheme, constants.FileSystemTrash))
if err != nil {
return fmt.Errorf("failed to build trash uri: %w", err)
}
dbfsSetting := m.settings.DBFS(ctx)
pageSize := dbfsSetting.MaxPageSize
for {
_, listRes, err := m.fs.List(ctx, trashUri, fs.WithPageSize(pageSize))
if err != nil {
return fmt.Errorf("failed to list trash: %w", err)
}
if len(listRes.Files) == 0 {
return nil
}
uris := make([]*fs.URI, 0, len(listRes.Files))
for _, f := range listRes.Files {
uris = append(uris, f.Uri(false))
}
if err := m.Delete(ctx, uris, fs.WithSysSkipSoftDelete(true)); err != nil {
return fmt.Errorf("failed to delete trash files: %w", err)
}
// Stop when there are no more pages.
if listRes.Pagination == nil ||
(listRes.Pagination.IsCursor && listRes.Pagination.NextPageToken == "") ||
(!listRes.Pagination.IsCursor && len(listRes.Files) < pageSize) {
return nil
}
}
}
func (m *manager) Delete(ctx context.Context, path []*fs.URI, opts ...fs.Option) error {
o := newOption()
for _, opt := range opts {

@ -325,6 +325,18 @@ func Restore(c *gin.Context) {
c.JSON(200, serializer.Response{})
}
// EmptyTrash hard-deletes every top-level item in the current user's trash bin.
func EmptyTrash(c *gin.Context) {
err := explorer.EmptyTrash(c)
if err != nil {
c.JSON(200, serializer.Err(c, err))
c.Abort()
return
}
c.JSON(200, serializer.Response{})
}
// Unlock unlocks files by given tokens
func Unlock(c *gin.Context) {
service := ParametersFromContext[*explorer.UnlockFileService](c, explorer.UnlockFileParameterCtx{})

@ -671,6 +671,11 @@ func initMasterRouter(dep dependency.Dep) *gin.Engine {
middleware.ValidateBatchFileCount(dep, explorer.DeleteFileParameterCtx{}),
controllers.Delete,
)
// Empty trash bin
file.DELETE("trash",
middleware.RequiredScopes(types.ScopeFilesWrite),
controllers.EmptyTrash,
)
// Force unlock
file.DELETE("lock",
middleware.RequiredScopes(types.ScopeFilesWrite),

@ -579,6 +579,20 @@ func (s *DeleteFileService) Restore(c *gin.Context) error {
return nil
}
// EmptyTrash hard-deletes every top-level item in the current user's trash bin.
func EmptyTrash(c *gin.Context) error {
dep := dependency.FromContext(c)
user := inventory.UserFromContext(c)
m := manager.NewFileManager(dep, user)
defer m.Recycle()
if err := m.EmptyTrash(c); err != nil {
return fmt.Errorf("failed to empty trash: %w", err)
}
return nil
}
type (
UnlockFileParameterCtx struct{}
UnlockFileService struct {

Loading…
Cancel
Save