Created search bar
This commit is contained in:
@@ -1,38 +1,78 @@
|
|||||||
using Adw;
|
using Adw;
|
||||||
using Keychain.UI.ViewModels;
|
using Keychain.UI.ViewModels;
|
||||||
|
|
||||||
namespace Keychain.UI;
|
namespace Keychain.UI;
|
||||||
|
|
||||||
public class MainWindow
|
public class MainWindow
|
||||||
{
|
{
|
||||||
public Window Window { get; }
|
public Window Window { get; }
|
||||||
private PreferencesGroup shortcutsGroup;
|
private PreferencesGroup shortcutsGroup;
|
||||||
private PasswordStoreShortcutCollection shortcuts;
|
private PasswordStoreShortcutCollection shortcuts;
|
||||||
|
private Gtk.ToggleButton searchToggleButton;
|
||||||
|
private Gtk.Stack titleStack;
|
||||||
|
private Gtk.SearchEntry searchEntry;
|
||||||
|
|
||||||
|
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";
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
var builder = new Gtk.Builder("Keychain.UI.MainWindow.MainWindow.xml");
|
var builder = new Gtk.Builder("Keychain.UI.MainWindow.MainWindow.xml");
|
||||||
|
|
||||||
var window = builder.GetObject("main_window") as Window;
|
|
||||||
if (window == null)
|
Window = builder.GetObject(windowId) as Window;
|
||||||
|
if (Window == null)
|
||||||
{
|
{
|
||||||
throw new Exception("Failed to load embedded resource MainWindow.xml");
|
throw new Exception("Failed to load embedded resource MainWindow.xml");
|
||||||
}
|
}
|
||||||
Window = window;
|
|
||||||
|
|
||||||
var group = builder.GetObject("shortcuts_group") as PreferencesGroup;
|
try
|
||||||
if (group == null)
|
|
||||||
{
|
{
|
||||||
throw new Exception("Failed to load UI element with ID: shortcuts_group");
|
shortcutsGroup = builder.GetObject(shortcutsGroupId) as PreferencesGroup;
|
||||||
}
|
if (shortcutsGroup == null)
|
||||||
shortcutsGroup = group;
|
throw new Exception(shortcutsGroupId);
|
||||||
|
|
||||||
var addButton = builder.GetObject("add_shortcut_button") as Gtk.Button;
|
var addButton = builder.GetObject(addShortcutButtonId) as Gtk.Button;
|
||||||
if (addButton == null)
|
if (addButton == null)
|
||||||
{
|
{
|
||||||
throw new Exception("Failed to load UI element with ID: add_shortcut_button");
|
throw new Exception(addShortcutButtonId);
|
||||||
|
}
|
||||||
|
addButton.OnClicked += OnAddShortcutClicked;
|
||||||
|
|
||||||
|
searchToggleButton = builder.GetObject(searchToggleButtonId) as Gtk.ToggleButton;
|
||||||
|
if (searchToggleButton == null)
|
||||||
|
{
|
||||||
|
throw new Exception(searchToggleButtonId);
|
||||||
|
}
|
||||||
|
searchToggleButton.OnToggled += SetSearchBarVisible;
|
||||||
|
|
||||||
|
|
||||||
|
titleStack = builder.GetObject(titleStackId) as Gtk.Stack;
|
||||||
|
if (titleStack == null)
|
||||||
|
{
|
||||||
|
throw new Exception(titleStackId);
|
||||||
|
}
|
||||||
|
|
||||||
|
searchEntry = builder.GetObject(searchEntryId) as Gtk.SearchEntry;
|
||||||
|
if (searchEntry == null)
|
||||||
|
{
|
||||||
|
throw new Exception(searchEntryId);
|
||||||
|
}
|
||||||
|
var focusController = new Gtk.EventControllerFocus();
|
||||||
|
focusController.OnLeave += (s, e) =>
|
||||||
|
{
|
||||||
|
searchToggleButton.Active = false;
|
||||||
|
};
|
||||||
|
searchEntry.AddController(focusController);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new Exception("Failed to load UI element with ID: " + e.Message);
|
||||||
}
|
}
|
||||||
addButton.OnClicked += OnAddShortcutClicked;
|
|
||||||
|
|
||||||
// Initialize the observable collection with property binding
|
// Initialize the observable collection with property binding
|
||||||
shortcuts = new PasswordStoreShortcutCollection(shortcutsGroup);
|
shortcuts = new PasswordStoreShortcutCollection(shortcutsGroup);
|
||||||
@@ -44,26 +84,39 @@ public class MainWindow
|
|||||||
{
|
{
|
||||||
var dialog = new AddShortcutWindow().Dialog;
|
var dialog = new AddShortcutWindow().Dialog;
|
||||||
dialog.Present(Window);
|
dialog.Present(Window);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void AddShortcut(string path)
|
private void AddShortcut(string path)
|
||||||
{
|
{
|
||||||
var newShortcut = new PasswordStoreShortcut(path:path);
|
var newShortcut = new PasswordStoreShortcut(path: path);
|
||||||
shortcuts.Add(newShortcut); // This will automatically update the UI
|
shortcuts.Add(newShortcut); // This will automatically update the UI
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveShortcut(PasswordStoreShortcut shortcut)
|
private void RemoveShortcut(PasswordStoreShortcut shortcut)
|
||||||
{
|
{
|
||||||
shortcuts.Remove(shortcut); // This will automatically update the UI
|
shortcuts.Remove(shortcut); // This will automatically update the UI
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LoadDefaultShortcuts()
|
private void LoadDefaultShortcuts()
|
||||||
{
|
{
|
||||||
shortcuts.Add(new PasswordStoreShortcut(displayName:"Default", path:Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)+"/.password_store"));
|
shortcuts.Add(new PasswordStoreShortcut(displayName: "Default", path: Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) + "/.password_store"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateShortcutName(PasswordStoreShortcut shortcut, string newName)
|
private void UpdateShortcutName(PasswordStoreShortcut shortcut, string newName)
|
||||||
{
|
{
|
||||||
shortcut.DisplayName = newName; // This will automatically update the UI row
|
shortcut.DisplayName = newName; // This will automatically update the UI row
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void SetSearchBarVisible(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
if (searchToggleButton.Active)
|
||||||
|
{
|
||||||
|
titleStack.SetVisibleChildName("Search");
|
||||||
|
searchEntry.GrabFocus();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
titleStack.SetVisibleChildName("Passwords");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,126 +1,160 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<interface>
|
<interface>
|
||||||
<object class="AdwWindow" id="main_window">
|
<object class="AdwWindow" id="main_window">
|
||||||
<property name="width-request">350</property>
|
<property name="width-request">350</property>
|
||||||
<property name="height-request">300</property>
|
<property name="height-request">300</property>
|
||||||
<property name="default-width">800</property>
|
<property name="default-width">800</property>
|
||||||
<property name="default-height">500</property>
|
<property name="default-height">500</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="AdwBreakpoint">
|
<object class="AdwBreakpoint">
|
||||||
<condition>max-width: 500sp</condition>
|
<condition>max-width: 500sp</condition>
|
||||||
<setter object="split_view" property="collapsed">True</setter>
|
<setter object="split_view" property="collapsed">True</setter>
|
||||||
<setter object="show_sidebar_button" property="visible">True</setter>
|
<setter object="show_sidebar_button" property="visible">True</setter>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<property name="content">
|
<property name="content">
|
||||||
<object class="AdwOverlaySplitView" id="split_view">
|
<object class="AdwOverlaySplitView" id="split_view">
|
||||||
<property name="min-sidebar-width">300</property>
|
<property name="min-sidebar-width">300</property>
|
||||||
<property name="max-sidebar-width">300</property>
|
<property name="max-sidebar-width">300</property>
|
||||||
<property name="show-sidebar"
|
<property name="show-sidebar"
|
||||||
bind-source="show_sidebar_button"
|
bind-source="show_sidebar_button"
|
||||||
bind-property="active"
|
bind-property="active"
|
||||||
bind-flags="sync-create|bidirectional"/>
|
bind-flags="sync-create|bidirectional"/>
|
||||||
<property name="sidebar">
|
<property name="sidebar">
|
||||||
<object class="AdwNavigationPage">
|
<object class="AdwNavigationPage">
|
||||||
<property name="title" translatable="yes" context="label" comments="Noun. Marks a list of password collections.">Stores</property>
|
<property name="title" translatable="yes" context="label" comments="Noun. Marks a list of password collections.">Stores</property>
|
||||||
<property name="child">
|
|
||||||
<object class="AdwToolbarView">
|
|
||||||
<child type="top">
|
|
||||||
<object class="AdwHeaderBar">
|
|
||||||
<child type="start">
|
|
||||||
<object class="GtkButton" id="add_shortcut_button">
|
|
||||||
<property name="valign">center</property>
|
|
||||||
<style>
|
|
||||||
<class name="flat" />
|
|
||||||
</style>
|
|
||||||
<child>
|
|
||||||
<object class="AdwButtonContent">
|
|
||||||
<property name="icon-name">list-add-symbolic</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<property name="content">
|
|
||||||
<object class="AdwPreferencesPage">
|
|
||||||
<child>
|
|
||||||
<object class="AdwPreferencesGroup" id="shortcuts_group">
|
|
||||||
<!-- Dynamic rows will be added here via model binding -->
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</property>
|
|
||||||
</object>
|
|
||||||
</property>
|
|
||||||
</object>
|
|
||||||
</property>
|
|
||||||
<property name="content">
|
|
||||||
<object class="AdwNavigationPage">
|
|
||||||
<property name="title" translatable="yes" context="label" comments="Noun, plural. Indicates the location of the actual decryptable passwords">Passwords</property>
|
|
||||||
<property name="child">
|
<property name="child">
|
||||||
<object class="AdwToolbarView">
|
<object class="AdwToolbarView">
|
||||||
<child type="top">
|
<child type="top">
|
||||||
<object class="AdwHeaderBar">
|
<object class="AdwHeaderBar">
|
||||||
<child type="start">
|
<child type="start">
|
||||||
<object class="GtkBox">
|
<object class="GtkButton" id="add_shortcut_button">
|
||||||
<property name="orientation">horizontal</property>
|
<property name="valign">center</property>
|
||||||
<property name="spacing">6</property>
|
<style>
|
||||||
|
<class name="flat" />
|
||||||
|
</style>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkToggleButton" id="search_button">
|
<object class="AdwButtonContent">
|
||||||
<property name="icon-name">system-search-symbolic</property>
|
<property name="icon-name">list-add-symbolic</property>
|
||||||
<!--<signal name="notify::active" handler="search_button_toggled_cb"/> -->
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
<child>
|
|
||||||
<object class="GtkToggleButton" id="show_sidebar_button">
|
|
||||||
<property name="icon-name">sidebar-show-symbolic</property>
|
|
||||||
<property name="active">True</property>
|
|
||||||
<property name="visible">False</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<property name="content">
|
|
||||||
<object class="AdwPreferencesPage">
|
|
||||||
<child>
|
|
||||||
<object class="AdwPreferencesGroup">
|
|
||||||
<property name="title">Default</property>
|
|
||||||
<property name="description">/home/typo/.password-store</property>
|
|
||||||
<property name="header-suffix">
|
|
||||||
<object class="GtkButton">
|
|
||||||
<property name="valign">center</property>
|
|
||||||
<style>
|
|
||||||
<class name="flat" />
|
|
||||||
</style>
|
|
||||||
<child>
|
|
||||||
<object class="AdwButtonContent">
|
|
||||||
<property name="icon-name">list-add-symbolic</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
|
||||||
</property>
|
|
||||||
<child>
|
|
||||||
<object class="AdwActionRow">
|
|
||||||
<property name="title">Sample password</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
<child>
|
|
||||||
<object class="AdwActionRow">
|
|
||||||
<property name="title">Sample password 2</property>
|
|
||||||
</object>
|
|
||||||
</child>
|
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
</property>
|
</child>
|
||||||
</object>
|
<property name="content">
|
||||||
|
<object class="AdwPreferencesPage">
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup" id="shortcuts_group">
|
||||||
|
<!-- Dynamic rows will be added here via model binding -->
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
</property>
|
</property>
|
||||||
</object>
|
</object>
|
||||||
</property>
|
</property>
|
||||||
</object>
|
<property name="content">
|
||||||
</property>
|
<object class="AdwNavigationPage">
|
||||||
</object>
|
<property name="title" translatable="yes" context="label" comments="Noun, plural. Indicates the location of the actual decryptable passwords">Passwords</property>
|
||||||
</interface>
|
<property name="child">
|
||||||
|
<object class="AdwToolbarView">
|
||||||
|
<child type="top">
|
||||||
|
<object class="AdwHeaderBar">
|
||||||
|
<child type="start">
|
||||||
|
<object class="GtkBox">
|
||||||
|
<property name="orientation">horizontal</property>
|
||||||
|
<property name="spacing">6</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkToggleButton" id="search_button">
|
||||||
|
<property name="icon-name">system-search-symbolic</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkToggleButton" id="show_sidebar_button">
|
||||||
|
<property name="icon-name">sidebar-show-symbolic</property>
|
||||||
|
<property name="active">True</property>
|
||||||
|
<property name="visible">False</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<property name="title-widget">
|
||||||
|
<object class="GtkStack" id="title_stack">
|
||||||
|
<property name="transition-type">slide-up-down</property>
|
||||||
|
<child>
|
||||||
|
<object class="GtkStackPage">
|
||||||
|
<property name="name">Passwords</property>
|
||||||
|
<property name="child">
|
||||||
|
<object class="AdwWindowTitle">
|
||||||
|
<property name="title">Passwords</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkStackPage">
|
||||||
|
<property name="name">Search</property>
|
||||||
|
<property name="child">
|
||||||
|
<object class="AdwClamp">
|
||||||
|
<property name="tightening-threshold">300</property>
|
||||||
|
<property name="maximum-size">400</property>
|
||||||
|
<property name="child">
|
||||||
|
<object class="GtkSearchEntry" id="search_entry">
|
||||||
|
<property name="hexpand">True</property>
|
||||||
|
<property name="placeholder-text" translatable="yes">Search passwords</property>
|
||||||
|
<!-- <signal name="search-started" handler="search_started_cb" swapped="yes"/> -->
|
||||||
|
<!-- <signal name="search-changed" handler="search_changed_cb" swapped="yes"/> -->
|
||||||
|
<!-- <signal name="stop-search" handler="stop_search_cb" swapped="yes"/> -->
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<property name="content">
|
||||||
|
<object class="AdwPreferencesPage">
|
||||||
|
<child>
|
||||||
|
<object class="AdwPreferencesGroup">
|
||||||
|
<property name="title">Default</property>
|
||||||
|
<property name="description">/home/typo/.password-store</property>
|
||||||
|
<property name="header-suffix">
|
||||||
|
<object class="GtkButton">
|
||||||
|
<property name="valign">center</property>
|
||||||
|
<style>
|
||||||
|
<class name="flat" />
|
||||||
|
</style>
|
||||||
|
<child>
|
||||||
|
<object class="AdwButtonContent">
|
||||||
|
<property name="icon-name">list-add-symbolic</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="title">Sample password</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="AdwActionRow">
|
||||||
|
<property name="title">Sample password 2</property>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</property>
|
||||||
|
</object>
|
||||||
|
</interface>
|
||||||
Reference in New Issue
Block a user