From c19c1b8bc9aed203d8ff619566cba8316af6e4b4 Mon Sep 17 00:00:00 2001 From: Leendert de Borst Date: Fri, 23 Jan 2026 21:11:18 +0100 Subject: [PATCH] Use LayoutUtils for dynamically calculating element width for better use of UI space (#1473) --- .../Main/Pages/Items/View.razor | 13 +-- .../Main/Utilities/LayoutUtils.cs | 95 +++++++++++++++++++ 2 files changed, 98 insertions(+), 10 deletions(-) create mode 100644 apps/server/AliasVault.Client/Main/Utilities/LayoutUtils.cs diff --git a/apps/server/AliasVault.Client/Main/Pages/Items/View.razor b/apps/server/AliasVault.Client/Main/Pages/Items/View.razor index 62d8366e4..8ed636b6f 100644 --- a/apps/server/AliasVault.Client/Main/Pages/Items/View.razor +++ b/apps/server/AliasVault.Client/Main/Pages/Items/View.razor @@ -171,14 +171,9 @@ else
- @{ - var hasEmail = loginFields.Any(f => f.FieldKey == FieldKey.LoginEmail); - } @foreach (var field in loginFields) { - @* Make username full width if there's no email field *@ - var isUsernameWithoutEmail = field.FieldKey == FieldKey.LoginUsername && !hasEmail; - + }
@@ -206,7 +201,7 @@ else } @foreach (var field in aliasFields) { - + } @@ -223,9 +218,7 @@ else
@foreach (var field in cardFields) { - @* Cardholder name should be full width *@ - var isFullWidthCardField = field.FieldKey == FieldKey.CardCardholderName; - + }
diff --git a/apps/server/AliasVault.Client/Main/Utilities/LayoutUtils.cs b/apps/server/AliasVault.Client/Main/Utilities/LayoutUtils.cs new file mode 100644 index 000000000..9f7feeba1 --- /dev/null +++ b/apps/server/AliasVault.Client/Main/Utilities/LayoutUtils.cs @@ -0,0 +1,95 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) aliasvault. All rights reserved. +// Licensed under the AGPLv3 license. See LICENSE.md file in the project root for full license information. +// +// ----------------------------------------------------------------------- + +namespace AliasVault.Client.Main.Utilities; + +using AliasClientDb.Models; +using AliasVault.Client.Main.Models; + +/// +/// Utility for calculating field layout widths dynamically. +/// +public static class LayoutUtils +{ + /// + /// Determines which fields should be displayed at full width based on the field list. + /// Rules: + /// - Fields that are inherently full width (Password, TextArea, URL) always stay full width. + /// - If there's only one half-width-capable field, it should be full width. + /// - If there's an odd number of half-width-capable fields, the last one should be full width. + /// - Password fields are placed at the end and always full width. + /// + /// The list of fields to analyze. + /// A set of field keys that should be displayed at full width. + public static HashSet GetFullWidthFields(IReadOnlyList fields) + { + var fullWidthFields = new HashSet(); + + if (fields == null || fields.Count == 0) + { + return fullWidthFields; + } + + // First, identify fields that are always full width by their type + var alwaysFullWidthTypes = new HashSet(StringComparer.OrdinalIgnoreCase) + { + FieldType.Password, + FieldType.Hidden, + FieldType.TextArea, + FieldType.URL, + }; + + // Separate fields into always-full-width and half-width-capable + var halfWidthCapableFields = new List(); + + foreach (var field in fields) + { + if (alwaysFullWidthTypes.Contains(field.FieldType)) + { + fullWidthFields.Add(GetFieldIdentifier(field)); + } + else + { + halfWidthCapableFields.Add(field); + } + } + + // If there's only one half-width-capable field, make it full width + if (halfWidthCapableFields.Count == 1) + { + fullWidthFields.Add(GetFieldIdentifier(halfWidthCapableFields[0])); + } + else if (halfWidthCapableFields.Count > 1 && halfWidthCapableFields.Count % 2 == 1) + { + fullWidthFields.Add(GetFieldIdentifier(halfWidthCapableFields[^1])); + } + + return fullWidthFields; + } + + /// + /// Determines if a specific field should be displayed at full width based on the field list. + /// + /// The field to check. + /// The list of all fields in the section. + /// True if the field should be full width, false otherwise. + public static bool ShouldBeFullWidth(DisplayField field, IReadOnlyList fields) + { + var fullWidthFields = GetFullWidthFields(fields); + return fullWidthFields.Contains(GetFieldIdentifier(field)); + } + + /// + /// Gets a unique identifier for a field (uses FieldKey for system fields, FieldDefinitionId for custom). + /// + private static string GetFieldIdentifier(DisplayField field) + { + return !string.IsNullOrEmpty(field.FieldKey) + ? field.FieldKey + : field.FieldDefinitionId ?? string.Empty; + } +}