diff --git a/apps/browser-extension/src/i18n/locales/en.json b/apps/browser-extension/src/i18n/locales/en.json
index 2873333f5..4be1ad5c6 100644
--- a/apps/browser-extension/src/i18n/locales/en.json
+++ b/apps/browser-extension/src/i18n/locales/en.json
@@ -211,7 +211,7 @@
"allItemsInFolders": "All your items are organized in folders. Click a folder above to view your credentials, or use the search to find specific items.",
"deleteFolder": "Delete Folder",
"deleteFolderKeepItems": "Delete folder only",
- "deleteFolderKeepItemsDescription": "Items will be moved back to the main list.",
+ "deleteFolderKeepItemsDescription": "Items will be moved to the parent folder.",
"deleteFolderAndItems": "Delete folder and all items",
"deleteFolderAndItemsDescription": "{{count}} item(s) will be moved to Recently Deleted.",
"filters": {
diff --git a/apps/browser-extension/src/utils/db/repositories/FolderRepository.ts b/apps/browser-extension/src/utils/db/repositories/FolderRepository.ts
index e19b252d6..0ed75034f 100644
--- a/apps/browser-extension/src/utils/db/repositories/FolderRepository.ts
+++ b/apps/browser-extension/src/utils/db/repositories/FolderRepository.ts
@@ -109,9 +109,10 @@ export class FolderRepository extends BaseRepository {
/**
* Delete a folder (soft delete).
- * Recursively handles child folders and items:
- * - All items in this folder and child folders are moved to the parent folder (or root if no parent)
- * - All child folders are moved to the parent of the deleted folder
+ * Handles child folders and items:
+ * - Items in this folder only are moved to the parent folder (or root if no parent)
+ * - Items in child folders stay in their respective folders (since child folders are moved to parent)
+ * - All direct child folders are moved to the parent of the deleted folder
* @param folderId - The ID of the folder to delete
* @returns The number of rows updated
*/
@@ -123,10 +124,7 @@ export class FolderRepository extends BaseRepository {
const folder = this.getById(folderId);
const targetParentId = folder?.ParentFolderId || null;
- // Get all child folder IDs recursively
- const allChildFolderIds = this.getAllChildFolderIds(folderId);
-
- // Move all items in this folder and all child folders to the parent folder (or root if no parent)
+ // Move only items in this folder to the parent folder (or root if no parent)
if (targetParentId) {
// Has parent: move items to parent folder
this.client.executeUpdate(FolderQueries.MOVE_ITEMS_TO_FOLDER, [
@@ -134,27 +132,12 @@ export class FolderRepository extends BaseRepository {
currentDateTime,
folderId
]);
-
- for (const childFolderId of allChildFolderIds) {
- this.client.executeUpdate(FolderQueries.MOVE_ITEMS_TO_FOLDER, [
- targetParentId,
- currentDateTime,
- childFolderId
- ]);
- }
} else {
// No parent: move items to root (NULL)
this.client.executeUpdate(FolderQueries.CLEAR_ITEMS_FOLDER, [
currentDateTime,
folderId
]);
-
- for (const childFolderId of allChildFolderIds) {
- this.client.executeUpdate(FolderQueries.CLEAR_ITEMS_FOLDER, [
- currentDateTime,
- childFolderId
- ]);
- }
}
// Move direct child folders to the parent of the deleted folder
diff --git a/apps/server/AliasVault.Client/Main/Pages/Items/Home.razor b/apps/server/AliasVault.Client/Main/Pages/Items/Home.razor
index 4c05b3032..d6fbcc22d 100644
--- a/apps/server/AliasVault.Client/Main/Pages/Items/Home.razor
+++ b/apps/server/AliasVault.Client/Main/Pages/Items/Home.razor
@@ -321,7 +321,7 @@ else
OnDeleteFolderOnly="DeleteFolderOnlyAsync"
OnDeleteFolderAndContents="DeleteFolderAndContentsAsync"
FolderName="@CurrentFolderName"
- ItemCount="@FilteredAndSortedItems.Count()" />
+ ItemCount="@CurrentFolderItemCount" />
@code {
private IStringLocalizer Localizer => LocalizerFactory.Create("Pages.Main.Items.Home", "AliasVault.Client");
@@ -392,6 +392,25 @@ else
///
private string CurrentFolderName { get; set; } = string.Empty;
+ ///
+ /// Gets the total item count in the current folder tree (includes items in all subfolders recursively).
+ /// Used for the delete folder modal to determine if "delete with contents" option should be shown.
+ ///
+ private int CurrentFolderItemCount
+ {
+ get
+ {
+ if (!FolderId.HasValue)
+ {
+ return FilteredAndSortedItems.Count();
+ }
+
+ // Find the current folder in the Folders list and return its recursive count
+ var currentFolder = Folders.FirstOrDefault(f => f.Id == FolderId.Value);
+ return currentFolder?.ItemCount ?? 0;
+ }
+ }
+
///
/// Gets or sets whether the settings dropdown is shown.
///
@@ -889,16 +908,28 @@ else
}
///
- /// Delete the current folder only (move items to root).
+ /// Delete the current folder only (move items to parent folder).
///
private async Task DeleteFolderOnlyAsync()
{
if (FolderId.HasValue)
{
+ // Get the parent folder ID before deletion
+ var folder = await FolderService.GetByIdAsync(FolderId.Value);
+ var parentFolderId = folder?.ParentFolderId;
+
var success = await FolderService.DeleteAsync(FolderId.Value);
if (success)
{
- NavigationManager.NavigateTo("/items");
+ // Navigate to parent folder if it exists, otherwise root
+ if (parentFolderId.HasValue)
+ {
+ NavigationManager.NavigateTo($"/items/folder/{parentFolderId.Value}");
+ }
+ else
+ {
+ NavigationManager.NavigateTo("/items");
+ }
}
else
{
@@ -914,10 +945,22 @@ else
{
if (FolderId.HasValue)
{
+ // Get the parent folder ID before deletion
+ var folder = await FolderService.GetByIdAsync(FolderId.Value);
+ var parentFolderId = folder?.ParentFolderId;
+
var success = await FolderService.DeleteWithContentsAsync(FolderId.Value);
if (success)
{
- NavigationManager.NavigateTo("/items");
+ // Navigate to parent folder if it exists, otherwise root
+ if (parentFolderId.HasValue)
+ {
+ NavigationManager.NavigateTo($"/items/folder/{parentFolderId.Value}");
+ }
+ else
+ {
+ NavigationManager.NavigateTo("/items");
+ }
}
else
{
diff --git a/apps/server/AliasVault.Client/Resources/Components/Folders/DeleteFolderModal.en.resx b/apps/server/AliasVault.Client/Resources/Components/Folders/DeleteFolderModal.en.resx
index 44cace688..71bff6b97 100644
--- a/apps/server/AliasVault.Client/Resources/Components/Folders/DeleteFolderModal.en.resx
+++ b/apps/server/AliasVault.Client/Resources/Components/Folders/DeleteFolderModal.en.resx
@@ -72,7 +72,7 @@
Title for delete folder only option
- Items in this folder will be moved to root
+ Items will be moved to the parent folder
Description for delete folder only option
diff --git a/apps/server/AliasVault.Client/Services/FolderService.cs b/apps/server/AliasVault.Client/Services/FolderService.cs
index 1a193e518..48843cfab 100644
--- a/apps/server/AliasVault.Client/Services/FolderService.cs
+++ b/apps/server/AliasVault.Client/Services/FolderService.cs
@@ -233,6 +233,7 @@ public sealed class FolderService(DbService dbService)
foreach (var item in itemsInFolders)
{
item.DeletedAt = currentDateTime;
+ item.FolderId = null;
item.UpdatedAt = currentDateTime;
}