diff --git a/apps/server/AliasVault.Client/Main/Components/Widgets/SearchWidget.razor b/apps/server/AliasVault.Client/Main/Components/Widgets/SearchWidget.razor index c394b5bc4..382f41f7a 100644 --- a/apps/server/AliasVault.Client/Main/Components/Widgets/SearchWidget.razor +++ b/apps/server/AliasVault.Client/Main/Components/Widgets/SearchWidget.razor @@ -10,6 +10,7 @@ @using System.Timers @using AliasClientDb @using AliasClientDb.Models +@using AliasVault.Client.Main.Utilities
-
@result.Name
+
+ @if (result.FolderId.HasValue && FolderPathCache.TryGetValue(result.FolderId.Value, out var folderPath)) + { + + @GetTruncatedFolderPath(folderPath) > + + } + @result.Name +
@{ var email = ItemService.GetFieldValue(result, FieldKey.LoginEmail); var username = ItemService.GetFieldValue(result, FieldKey.LoginUsername); @@ -107,6 +116,7 @@ private string SearchTerm { get; set; } = string.Empty; private List SearchResults { get; set; } = new(); + private Dictionary> FolderPathCache { get; set; } = new(); private bool ShowResults { get; set; } private bool ShowHelpText { get; set; } private int SelectedIndex { get; set; } = -1; @@ -209,6 +219,7 @@ var query = context.Items .Include(x => x.Logo) .Include(x => x.FieldValues.Where(fv => !fv.IsDeleted)) + .Include(x => x.Folder) .Where(x => !x.IsDeleted) .Where(x => x.DeletedAt == null) .AsQueryable(); @@ -236,12 +247,28 @@ SearchResults = await query.Take(10).ToListAsync(); + // Build folder path cache for all results + var allFolders = await context.Folders.Where(f => !f.IsDeleted).ToListAsync(); + FolderPathCache.Clear(); + foreach (var item in SearchResults) + { + if (item.FolderId.HasValue) + { + var folderPath = FolderTreeUtilities.GetFolderPath(item.FolderId, allFolders); + if (folderPath.Count > 0) + { + FolderPathCache[item.FolderId.Value] = folderPath; + } + } + } + // Select first entry by default so when pressing enter, the first result is immediately selected. SelectedIndex = SearchResults.Count > 0 ? 0 : -1; } else { SearchResults.Clear(); + FolderPathCache.Clear(); SelectedIndex = -1; } @@ -297,4 +324,24 @@ { await JsInteropService.FocusElementById("searchWidget"); } + + private string GetTruncatedFolderPath(List pathSegments) + { + const int maxSegments = 3; + + if (pathSegments.Count <= maxSegments) + { + return FolderTreeUtilities.FormatFolderPath(pathSegments); + } + + // Truncate middle segments: "First > ... > Last" + var truncated = new List + { + pathSegments[0], + "...", + pathSegments[pathSegments.Count - 1] + }; + + return FolderTreeUtilities.FormatFolderPath(truncated); + } }