diff --git a/src/App/UI/MainWindow/MainWindow.cs b/src/App/UI/MainWindow/MainWindow.cs index 491dc4b..a71b361 100644 --- a/src/App/UI/MainWindow/MainWindow.cs +++ b/src/App/UI/MainWindow/MainWindow.cs @@ -8,19 +8,22 @@ public class MainWindow { public Window Window { get; } private PreferencesGroup shortcutsGroup; + private PasswordList passwordCollection; private PasswordStoreShortcutCollection shortcuts; private Gtk.ToggleButton searchToggleButton; private Gtk.Stack titleStack; private Gtk.SearchEntry searchEntry; + private PreferencesGroup passwordList; private readonly IPasswordStoreService passwordStoreService; - private readonly string windowId = "main_window"; - private readonly string shortcutsGroupId = "shortcuts_group"; - private readonly string addShortcutButtonId = "add_shortcut_button"; - private readonly string searchToggleButtonId = "search_button"; - private readonly string titleStackId = "title_stack"; - private readonly string searchEntryId = "search_entry"; + private const string windowId = "main_window"; + private const string shortcutsGroupId = "shortcuts_group"; + private const string addShortcutButtonId = "add_shortcut_button"; + private const string searchToggleButtonId = "search_button"; + private const string titleStackId = "title_stack"; + private const string searchEntryId = "search_entry"; + private const string passwordListId = "password_list"; public MainWindow(IPasswordStoreService passwordStoreService) { @@ -38,7 +41,9 @@ public class MainWindow { shortcutsGroup = builder.GetObject(shortcutsGroupId) as PreferencesGroup; if (shortcutsGroup == null) + { throw new Exception(shortcutsGroupId); + } var addButton = builder.GetObject(addShortcutButtonId) as Gtk.Button; if (addButton == null) @@ -72,16 +77,26 @@ public class MainWindow searchToggleButton.Active = false; }; searchEntry.AddController(focusController); + + passwordList = builder.GetObject(passwordListId) as PreferencesGroup; + if (passwordList == null) + { + throw new Exception(passwordListId); + } } catch (Exception e) { throw new Exception("Failed to load UI element with ID: " + e.Message); } - // Initialize the observable collection with property binding - shortcuts = new PasswordStoreShortcutCollection(shortcutsGroup, passwordStoreService); + // Initialize the observable collection with property binding + shortcuts = new PasswordStoreShortcutCollection(shortcutsGroup, passwordStoreService); + if (shortcuts.Count == 0) + { + LoadDefaultShortcuts(); + } - LoadDefaultShortcuts(); + passwordCollection = new PasswordList(passwordList); } private void OnAddShortcutClicked(object sender, EventArgs e) diff --git a/src/App/ViewModels/PasswordList.cs b/src/App/ViewModels/PasswordList.cs new file mode 100644 index 0000000..7d43b6d --- /dev/null +++ b/src/App/ViewModels/PasswordList.cs @@ -0,0 +1,83 @@ +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using Adw; +using Gtk; +using Logic; + +namespace Keychain.ViewModels; + +public class PasswordList : ObservableCollection +{ + private readonly IPasswordService _passwordService; + private readonly PreferencesGroup list; + private Dictionary itemToRowMap = new(); + + public PasswordList(PreferencesGroup list, IPasswordService passwordService) + : base() + { + this.list = list; + CollectionChanged += OnCollectionChanged; + _passwordService = passwordService; + + //test + Add(new PasswordViewModel("Sample Password")); + } + + + private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) + { + switch (e.Action) + { + case NotifyCollectionChangedAction.Add: + foreach (PasswordViewModel item in e.NewItems) + { + var row = CreateActionRow(item); + itemToRowMap[item] = row; + list.Add(row); + + // Subscribe to property changes for reactive updates + item.PropertyChanged += (sender, args) => UpdateRowFromItem(item, ref row); + } + break; + + case NotifyCollectionChangedAction.Remove: + foreach (PasswordViewModel item in e.OldItems) + { + if (itemToRowMap.TryGetValue(item, out var row)) + { + list.Remove(row); + itemToRowMap.Remove(item); + } + } + break; + + case NotifyCollectionChangedAction.Reset: + foreach (var row in itemToRowMap.Values) + { + list.Remove(row); + } + itemToRowMap.Clear(); + break; + } + } + + private ActionRow CreateActionRow(PasswordViewModel item) + { + var row = new ActionRow(); + UpdateRowFromItem(item, ref row); + return row; + } + + private void UpdateRowFromItem(PasswordViewModel item, ref ActionRow row) + { + row.SetTitle(item.Name); + + // Inactive button for intuitive UI + var go = new Button(); + go.Sensitive = false; + go.AddCssClass("flat"); + go.SetValign(Align.Center); + go.IconName = "go-next-symbolic"; + row.AddSuffix(go); + } +} \ No newline at end of file diff --git a/src/App/ViewModels/PasswordStoreShortcutCollection.cs b/src/App/ViewModels/PasswordStoreShortcutCollection.cs index 3c68ed0..9a52b17 100644 --- a/src/App/ViewModels/PasswordStoreShortcutCollection.cs +++ b/src/App/ViewModels/PasswordStoreShortcutCollection.cs @@ -8,10 +8,10 @@ using System.Collections.Specialized; public class PasswordStoreShortcutCollection : ObservableCollection { - private IPasswordStoreService _passwordStoreService; + private readonly IPasswordStoreService _passwordStoreService; private readonly PreferencesGroup shortcutsGroup; - private readonly Dictionary itemToRowMap = new(); + private Dictionary itemToRowMap = new(); public PasswordStoreShortcutCollection(PreferencesGroup shortcutsGroup, IPasswordStoreService passwordStoreService) : base() @@ -19,6 +19,12 @@ public class PasswordStoreShortcutCollection : ObservableCollection _model; } + + public string Name + { + get => _model.Name; + } + + public PasswordViewModel(Password item) + { + _model = item; + } + + public PasswordViewModel(string name) + { + _model = new Password + { + Name = name, + }; + } +} diff --git a/src/Models/Password.cs b/src/Models/Password.cs new file mode 100644 index 0000000..0698b9c --- /dev/null +++ b/src/Models/Password.cs @@ -0,0 +1,6 @@ +namespace Models; + +public class Password +{ + public string Name { get; set; } +} diff --git a/src/Repository/JsonRepository.cs b/src/Repository/JsonRepository.cs index 8d2c58f..418fa39 100644 --- a/src/Repository/JsonRepository.cs +++ b/src/Repository/JsonRepository.cs @@ -13,7 +13,7 @@ public class JsonRepository : IRepository, IDisposable private List _cache; private bool _cacheAhead; - public JsonRepository(string fileName) + public JsonRepository() { string? xdgDataHome = Environment.GetEnvironmentVariable("XDG_DATA_HOME"); string dataHome;