From efc4e64c598b14417eb98f65fd999e781744cc3f Mon Sep 17 00:00:00 2001 From: hal-wang Date: Thu, 16 May 2024 14:45:38 +0800 Subject: [PATCH] =?UTF-8?q?feat(uwp):=20=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Lavcode.Uwp/Lavcode.Uwp.csproj | 7 + .../Modules/PasswordCore/FolderList.xaml | 289 +++++++++++------- .../Modules/PasswordCore/PasswordList.xaml.cs | 1 + .../PasswordCore/PasswordListViewModel.cs | 56 ++-- src/Lavcode.Uwp/Modules/Search/SearchBar.xaml | 60 ++++ .../Modules/Search/SearchBar.xaml.cs | 67 ++++ src/Lavcode.Uwp/Modules/Shell/Commands.xaml | 59 ++-- .../Modules/Shell/Commands.xaml.cs | 26 ++ src/Lavcode.Uwp/Modules/Shell/ShellPage.xaml | 119 ++++---- .../Modules/Shell/ShellPage.xaml.cs | 14 + 10 files changed, 483 insertions(+), 215 deletions(-) create mode 100644 src/Lavcode.Uwp/Modules/Search/SearchBar.xaml create mode 100644 src/Lavcode.Uwp/Modules/Search/SearchBar.xaml.cs diff --git a/src/Lavcode.Uwp/Lavcode.Uwp.csproj b/src/Lavcode.Uwp/Lavcode.Uwp.csproj index 17412be..5d5400c 100644 --- a/src/Lavcode.Uwp/Lavcode.Uwp.csproj +++ b/src/Lavcode.Uwp/Lavcode.Uwp.csproj @@ -188,6 +188,9 @@ ProviderSelectButton.xaml + + SearchBar.xaml + @@ -438,6 +441,10 @@ Designer MSBuild:Compile + + Designer + MSBuild:Compile + Designer MSBuild:Compile diff --git a/src/Lavcode.Uwp/Modules/PasswordCore/FolderList.xaml b/src/Lavcode.Uwp/Modules/PasswordCore/FolderList.xaml index dbc285b..85268d7 100644 --- a/src/Lavcode.Uwp/Modules/PasswordCore/FolderList.xaml +++ b/src/Lavcode.Uwp/Modules/PasswordCore/FolderList.xaml @@ -1,224 +1,273 @@  + d:DesignWidth="600" + mc:Ignorable="d"> - - + + - - - - + + + + - - + - + - + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Lavcode.Uwp/Modules/PasswordCore/PasswordList.xaml.cs b/src/Lavcode.Uwp/Modules/PasswordCore/PasswordList.xaml.cs index fecd70d..8b82c35 100644 --- a/src/Lavcode.Uwp/Modules/PasswordCore/PasswordList.xaml.cs +++ b/src/Lavcode.Uwp/Modules/PasswordCore/PasswordList.xaml.cs @@ -36,6 +36,7 @@ private void PasswordList_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs { StrongReferenceMessenger.Default.Register(this, "FolderSelected", (_, item) => FolderSelected(item)); StrongReferenceMessenger.Default.Register(this, "PasswordAddOrEdited", (_, item) => PasswordAddOrEdited()); + StrongReferenceMessenger.Default.Register(this, "Search", async (_, searchText) => await VM.Search(searchText)); } public PasswordListViewModel VM { get; } = ServiceProvider.Services.GetService(); diff --git a/src/Lavcode.Uwp/Modules/PasswordCore/PasswordListViewModel.cs b/src/Lavcode.Uwp/Modules/PasswordCore/PasswordListViewModel.cs index 7200eb3..f57d89f 100644 --- a/src/Lavcode.Uwp/Modules/PasswordCore/PasswordListViewModel.cs +++ b/src/Lavcode.Uwp/Modules/PasswordCore/PasswordListViewModel.cs @@ -72,17 +72,19 @@ public async Task Init(FolderItem folderItem) { SelectedPasswordItem = null; } - PasswordItems.Clear(); if (folderItem == null) { + PasswordItems.Clear(); return; } try { - await foreach (var password in GetPasswordItems()) + var passwords = await _passwordService.GetPasswords(_curFolder.Folder.Id); + PasswordItems.Clear(); + foreach (var password in passwords) { - PasswordItems.Add(password); + PasswordItems.Add(new PasswordItem(password)); } } catch (Exception ex) @@ -91,38 +93,52 @@ public async Task Init(FolderItem folderItem) } } - private async IAsyncEnumerable GetPasswordItems() + public async Task Search(string searchText) { - var passwords = await _passwordService.GetPasswords(_curFolder.Folder.Id); - foreach (var password in passwords) + if (string.IsNullOrEmpty(searchText)) { - PasswordItem passwordItem = null; - await TaskExtend.Run(() => + await Init(_curFolder); + return; + } + + try + { + var passwords = await _passwordService.GetPasswords(); + passwords = passwords + .Where(p => + p.Title.Contains(searchText) + || p.Remark.Contains(searchText) + || p.Value.Contains(searchText) + || p.KeyValuePairs.Any(kvp => kvp.Key.Contains(searchText) || kvp.Value.Contains(searchText))) + .ToList(); + PasswordItems.Clear(); + foreach (var password in passwords) { - passwordItem = new PasswordItem(password); - }); - yield return passwordItem; + PasswordItems.Add(new PasswordItem(password)); + } + } + catch (Exception ex) + { + MessageHelper.ShowError(ex); } } - #endregion private void PasswordAddOrEdited(PasswordModel password) { - if (_curFolder == null || _curFolder.Folder.Id != password.FolderId) + var existPassword = PasswordItems.Where((item) => item.Password.Id == password.Id).FirstOrDefault(); + if (existPassword == null) { - return; - } + if (_curFolder == null || _curFolder.Folder.Id != password.FolderId) + { + return; + } - var queryResult = PasswordItems.Where((item) => item.Password.Id == password.Id); - if (queryResult.Count() == 0) - { PasswordItems.Add(new PasswordItem(password)); } else { - var existItem = queryResult.First(); - existItem.Set(password); + existPassword.Set(password); } SelectedPasswordItem = PasswordItems.Where((item) => item.Password == password).First(); } diff --git a/src/Lavcode.Uwp/Modules/Search/SearchBar.xaml b/src/Lavcode.Uwp/Modules/Search/SearchBar.xaml new file mode 100644 index 0000000..0f04f01 --- /dev/null +++ b/src/Lavcode.Uwp/Modules/Search/SearchBar.xaml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + diff --git a/src/Lavcode.Uwp/Modules/Search/SearchBar.xaml.cs b/src/Lavcode.Uwp/Modules/Search/SearchBar.xaml.cs new file mode 100644 index 0000000..90e727d --- /dev/null +++ b/src/Lavcode.Uwp/Modules/Search/SearchBar.xaml.cs @@ -0,0 +1,67 @@ +using Microsoft.Toolkit.Mvvm.Messaging; +using System; +using System.Threading.Tasks; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; + +namespace Lavcode.Uwp.Modules.Search +{ + public sealed partial class SearchBar : UserControl + { + public SearchBar() + { + this.InitializeComponent(); + } + + public bool IsSearchOpen + { + get { return (bool)GetValue(IsSearchOpenProperty); } + set { SetValue(IsSearchOpenProperty, value); } + } + + // Using a DependencyProperty as the backing store for IsSearchOpen. This enables animation, styling, binding, etc... + public static readonly DependencyProperty IsSearchOpenProperty = + DependencyProperty.Register("IsSearchOpen", typeof(bool), typeof(SearchBar), new PropertyMetadata(false, OnIsSearchOpenChanged)); + + private static async void OnIsSearchOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + if ((bool)e.NewValue) + { + await Task.Delay(200); + (d as SearchBar)!.SearchTextBox.Focus(FocusState.Pointer); + } + } + + public string SearchText + { + get { return (string)GetValue(SearchTextProperty); } + set { SetValue(SearchTextProperty, value); } + } + + // Using a DependencyProperty as the backing store for SearchText. This enables animation, styling, binding, etc... + public static readonly DependencyProperty SearchTextProperty = + DependencyProperty.Register("SearchText", typeof(string), typeof(SearchBar), new PropertyMetadata(string.Empty)); + + + private void TextBox_PreviewKeyDown(object sender, Windows.UI.Xaml.Input.KeyRoutedEventArgs e) + { + switch (e.Key) + { + case Windows.System.VirtualKey.Enter: + Search(); + break; + } + } + + private void Exit() + { + IsSearchOpen = false; + StrongReferenceMessenger.Default.Send("", "Search"); + } + + private void Search() + { + StrongReferenceMessenger.Default.Send(SearchText, "Search"); + } + } +} diff --git a/src/Lavcode.Uwp/Modules/Shell/Commands.xaml b/src/Lavcode.Uwp/Modules/Shell/Commands.xaml index e36a438..d759285 100644 --- a/src/Lavcode.Uwp/Modules/Shell/Commands.xaml +++ b/src/Lavcode.Uwp/Modules/Shell/Commands.xaml @@ -1,46 +1,53 @@  +--> - - - + d:DesignWidth="400" + mc:Ignorable="d"> - + + + + - + - + - + diff --git a/src/Lavcode.Uwp/Modules/Shell/Commands.xaml.cs b/src/Lavcode.Uwp/Modules/Shell/Commands.xaml.cs index 9d0aaa2..a20aa26 100644 --- a/src/Lavcode.Uwp/Modules/Shell/Commands.xaml.cs +++ b/src/Lavcode.Uwp/Modules/Shell/Commands.xaml.cs @@ -6,11 +6,14 @@ using Lavcode.Uwp.Modules.SqliteSync; using Lavcode.Uwp.Modules.SqliteSync.View; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Toolkit.Mvvm.ComponentModel; +using System; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; namespace Lavcode.Uwp.Modules.Shell { + [INotifyPropertyChanged] public sealed partial class Commands : UserControl { public Commands() @@ -18,8 +21,25 @@ public Commands() this.InitializeComponent(); } + + public bool IsSearchOpen + { + get { return (bool)GetValue(IsSearchOpenProperty); } + set { SetValue(IsSearchOpenProperty, value); } + } + + // Using a DependencyProperty as the backing store for IsSearchOpen. This enables animation, styling, binding, etc... + public static readonly DependencyProperty IsSearchOpenProperty = + DependencyProperty.Register("IsSearchOpen", typeof(bool), typeof(Commands), new PropertyMetadata(false, OnIsSearchOpenChanged)); + + private static void OnIsSearchOpenChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) + { + (d as Commands).OnPropertyChanged(nameof(IsSearchVisible)); + } + public bool IsLaunchFile => ServiceProvider.Services.GetService()?.OpenedFile != null; public bool IsSyncVisible => SettingHelper.Instance.Provider == Provider.Sqlite && !IsLaunchFile && App.Frame.CurrentSourcePageType == typeof(ShellPage); + public bool IsSearchVisible => App.Frame.CurrentSourcePageType == typeof(ShellPage) && !IsSearchOpen; public Provider Provider => SettingHelper.Instance.Provider; @@ -42,5 +62,11 @@ private async void SettingBtn_Click(object sender, RoutedEventArgs e) { await new SettingSplitView().ShowAsync(); } + + private void SearchBtn_Click(object sender, RoutedEventArgs e) + { + IsSearchOpen = true; + OnPropertyChanged(nameof(IsSearchVisible)); + } } } diff --git a/src/Lavcode.Uwp/Modules/Shell/ShellPage.xaml b/src/Lavcode.Uwp/Modules/Shell/ShellPage.xaml index 58046f1..a10596d 100644 --- a/src/Lavcode.Uwp/Modules/Shell/ShellPage.xaml +++ b/src/Lavcode.Uwp/Modules/Shell/ShellPage.xaml @@ -1,33 +1,34 @@  + muxc:BackdropMaterial.ApplyToRootOrPageBackground="True" + mc:Ignorable="d"> - - - + + + - + - - - - + + + + @@ -35,67 +36,81 @@ - - - - + + + + - + - + - - + + - + - + + - - - + + + - + - + - + - + - + \ No newline at end of file diff --git a/src/Lavcode.Uwp/Modules/Shell/ShellPage.xaml.cs b/src/Lavcode.Uwp/Modules/Shell/ShellPage.xaml.cs index d01992d..5f72b75 100644 --- a/src/Lavcode.Uwp/Modules/Shell/ShellPage.xaml.cs +++ b/src/Lavcode.Uwp/Modules/Shell/ShellPage.xaml.cs @@ -1,6 +1,7 @@ using HTools.Uwp.Helpers; using Lavcode.Uwp.Modules.SqliteSync; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Toolkit.Mvvm.Messaging; using Microsoft.Toolkit.Uwp.UI.Helpers; using Windows.Storage; using Windows.UI.Core; @@ -37,6 +38,18 @@ public StorageFile OpenedFile public static readonly DependencyProperty OpenedFileProperty = DependencyProperty.Register("OpenedFile", typeof(StorageFile), typeof(ShellPage), new PropertyMetadata(null)); + + public bool IsSearchOpen + { + get { return (bool)GetValue(IsSearchOpenProperty); } + set { SetValue(IsSearchOpenProperty, value); } + } + + // Using a DependencyProperty as the backing store for IsSearchOpen. This enables animation, styling, binding, etc... + public static readonly DependencyProperty IsSearchOpenProperty = + DependencyProperty.Register("IsSearchOpen", typeof(bool), typeof(ShellPage), new PropertyMetadata(false)); + + private void MainPage_Loaded(object sender, Windows.UI.Xaml.RoutedEventArgs e) { _themeListener.ThemeChanged += ThemeListener_ThemeChanged; @@ -77,6 +90,7 @@ public void LoadUI() FindName(nameof(PasswordDetail)); FindName(nameof(PasswordList)); FindName(nameof(FolderList)); + FindName(nameof(SearchBar)); } } }