diff --git a/Wino.Core.Domain/Translations/en_US/resources.json b/Wino.Core.Domain/Translations/en_US/resources.json index 4d5fc623..d7c71364 100644 --- a/Wino.Core.Domain/Translations/en_US/resources.json +++ b/Wino.Core.Domain/Translations/en_US/resources.json @@ -298,9 +298,9 @@ "NewAccountDialog_AccountNameDefaultValue": "Personal", "NewAccountDialog_AccountNamePlaceholder": "eg. Personal Mail", "NewAccountDialog_Title": "Add New Account", - "NoMailSelected": "no message selected", - "NoMessageCrieteria": "no messages match your search criteria.", - "NoMessageEmptyFolder": "this folder is empty.", + "NoMailSelected": "No message selected", + "NoMessageCrieteria": "No messages match your search criteria", + "NoMessageEmptyFolder": "This folder is empty", "Notifications_MultipleNotificationsMessage": "You have {0} new mails", "Notifications_MultipleNotificationsTitle": "New Mails", "Notifications_WinoUpdatedMessage": "Checkout new version {0}", @@ -321,8 +321,9 @@ "Right": "Right", "SynchronizationFolderReport_Success": "up to date", "SynchronizationFolderReport_Failed": "synchronization is failed", - "SearchBarPlaceholder": "search", - "SearchingIn": "searching in", + "SearchBarPlaceholder": "Search", + "SearchingIn": "Searching in", + "SearchPivotName": "Results", "SettingsAboutGithub_Description": "Go to issue tracker GitHub repository.", "SettingsAboutGithub_Title": "GitHub", "SettingsAccountManagementAppendMessage_Title": "Append messages to Sent folder", diff --git a/Wino.Core.Domain/Translator.Designer.cs b/Wino.Core.Domain/Translator.Designer.cs index 6f905ef8..a07f3c76 100644 --- a/Wino.Core.Domain/Translator.Designer.cs +++ b/Wino.Core.Domain/Translator.Designer.cs @@ -424,7 +424,7 @@ namespace Wino.Core.Domain public static string DialogMessage_UnsubscribeConfirmationGoToWebsiteConfirmButton => Resources.GetTranslatedString(@"DialogMessage_UnsubscribeConfirmationGoToWebsiteConfirmButton"); /// - /// Do you want to stop getting messages from {0}? WinoMail will unsubscribe for you by sending an email from your email account to {1}. + /// Do you want to stop getting messages from {0}? Wino will unsubscribe for you by sending an email from your email account to {1}. /// public static string DialogMessage_UnsubscribeConfirmationMailtoMessage => Resources.GetTranslatedString(@"DialogMessage_UnsubscribeConfirmationMailtoMessage"); @@ -1514,17 +1514,17 @@ namespace Wino.Core.Domain public static string NewAccountDialog_Title => Resources.GetTranslatedString(@"NewAccountDialog_Title"); /// - /// no message selected + /// No message selected /// public static string NoMailSelected => Resources.GetTranslatedString(@"NoMailSelected"); /// - /// no messages match your search criteria. + /// No messages match your search criteria /// public static string NoMessageCrieteria => Resources.GetTranslatedString(@"NoMessageCrieteria"); /// - /// this folder is empty. + /// This folder is empty /// public static string NoMessageEmptyFolder => Resources.GetTranslatedString(@"NoMessageEmptyFolder"); @@ -1629,15 +1629,20 @@ namespace Wino.Core.Domain public static string SynchronizationFolderReport_Failed => Resources.GetTranslatedString(@"SynchronizationFolderReport_Failed"); /// - /// search + /// Search /// public static string SearchBarPlaceholder => Resources.GetTranslatedString(@"SearchBarPlaceholder"); /// - /// searching in + /// Searching in /// public static string SearchingIn => Resources.GetTranslatedString(@"SearchingIn"); + /// + /// Results + /// + public static string SearchPivotName => Resources.GetTranslatedString(@"SearchPivotName"); + /// /// Go to issue tracker GitHub repository. /// diff --git a/Wino.Mail.ViewModels/MailListPageViewModel.cs b/Wino.Mail.ViewModels/MailListPageViewModel.cs index 6e9d4ae0..bc49de02 100644 --- a/Wino.Mail.ViewModels/MailListPageViewModel.cs +++ b/Wino.Mail.ViewModels/MailListPageViewModel.cs @@ -51,14 +51,14 @@ namespace Wino.Mail.ViewModels * to prevent them from being removed from the list when they are marked as read. */ - private HashSet gmailUnreadFolderMarkedAsReadUniqueIds = new HashSet(); + private readonly HashSet gmailUnreadFolderMarkedAsReadUniqueIds = []; private IObservable> selectionChangedObservable = null; public WinoMailCollection MailCollection { get; } = new WinoMailCollection(); - public ObservableCollection SelectedItems { get; set; } = new ObservableCollection(); - public ObservableCollection PivotFolders { get; set; } = new ObservableCollection(); + public ObservableCollection SelectedItems { get; set; } = []; + public ObservableCollection PivotFolders { get; set; } = []; private readonly SemaphoreSlim listManipulationSemepahore = new SemaphoreSlim(1); private CancellationTokenSource listManipulationCancellationTokenSource = new CancellationTokenSource(); @@ -68,7 +68,6 @@ namespace Wino.Mail.ViewModels public IPreferencesService PreferencesService { get; } private readonly IMailService _mailService; - private readonly INotificationBuilder _notificationBuilder; private readonly IFolderService _folderService; private readonly IWinoSynchronizerFactory _winoSynchronizerFactory; private readonly IThreadingStrategyProvider _threadingStrategyProvider; @@ -100,10 +99,12 @@ namespace Wino.Mail.ViewModels private FilterOption _selectedFilterOption; private SortingOption _selectedSortingOption; + // Indicates state when folder is initializing. It can happen after folder navigation, search or filter change applied or loading more items. [ObservableProperty] [NotifyPropertyChangedFor(nameof(IsEmpty))] [NotifyPropertyChangedFor(nameof(IsCriteriaFailed))] [NotifyPropertyChangedFor(nameof(IsFolderEmpty))] + [NotifyPropertyChangedFor(nameof(IsProgressRing))] private bool isInitializingFolder; [ObservableProperty] @@ -118,10 +119,21 @@ namespace Wino.Mail.ViewModels [ObservableProperty] private bool isBarOpen; + /// + /// Current folder that is being represented from the menu. + /// + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(CanSynchronize))] + [NotifyPropertyChangedFor(nameof(IsFolderSynchronizationEnabled))] + private IBaseFolderMenuItem activeFolder; + + [ObservableProperty] + [NotifyPropertyChangedFor(nameof(CanSynchronize))] + private bool isAccountSynchronizerInSynchronization; + public MailListPageViewModel(IDialogService dialogService, IWinoNavigationService navigationService, IMailService mailService, - INotificationBuilder notificationBuilder, IStatePersistanceService statePersistanceService, IFolderService folderService, IWinoSynchronizerFactory winoSynchronizerFactory, @@ -136,7 +148,6 @@ namespace Wino.Mail.ViewModels NavigationService = navigationService; _mailService = mailService; - _notificationBuilder = notificationBuilder; _folderService = folderService; _winoSynchronizerFactory = winoSynchronizerFactory; _threadingStrategyProvider = threadingStrategyProvider; @@ -156,53 +167,65 @@ namespace Wino.Mail.ViewModels }); } - /// - /// Executes the requested mail operation for currently selected items. - /// - /// Action to execute for selected items. - [RelayCommand] - private async Task MailOperationAsync(int mailOperationIndex) - { - if (!SelectedItems.Any()) return; - - // Commands don't like enums. So it has to be int. - var operation = (MailOperation)mailOperationIndex; - - var package = new MailOperationPreperationRequest(operation, SelectedItems.Select(a => a.MailCopy)); - - await ExecuteMailOperationAsync(package); - } + #region Properties /// - /// Sens a new message to synchronize current folder. + /// Selected internal folder. This can be either folder's own name or Focused-Other. /// - [RelayCommand] - private void SyncFolder() + public FolderPivotViewModel SelectedFolderPivot { - if (!CanSynchronize) return; - - // Only synchronize listed folders. - - // When doing linked inbox sync, we need to save the sync id to report progress back only once. - // Otherwise, we will report progress for each folder and that's what we don't want. - - trackingSynchronizationId = Guid.NewGuid(); - completedTrackingSynchronizationCount = 0; - - foreach (var folder in ActiveFolder.HandlingFolders) + get => _selectedFolderPivot; + set { - var options = new SynchronizationOptions() - { - AccountId = folder.MailAccountId, - Type = SynchronizationType.Custom, - SynchronizationFolderIds = [folder.Id], - GroupedSynchronizationTrackingId = trackingSynchronizationId - }; + if (_selectedFolderPivot != null) + _selectedFolderPivot.SelectedItemCount = 0; - Messenger.Send(new NewSynchronizationRequested(options)); + SetProperty(ref _selectedFolderPivot, value); } } + /// + /// Selected sorting option. + /// + public SortingOption SelectedSortingOption + { + get => _selectedSortingOption; + set + { + if (SetProperty(ref _selectedSortingOption, value)) + { + if (value != null && MailCollection != null) + { + MailCollection.SortingType = value.Type; + } + } + } + } + + public bool CanSynchronize => !IsAccountSynchronizerInSynchronization && IsFolderSynchronizationEnabled; + public bool IsFolderSynchronizationEnabled => ActiveFolder?.IsSynchronizationEnabled ?? false; + public int SelectedItemCount => SelectedItems.Count; + public bool HasMultipleItemSelections => SelectedItemCount > 1; + public bool HasSelectedItems => SelectedItems.Any(); + public bool IsArchiveSpecialFolder => ActiveFolder?.SpecialFolderType == SpecialFolderType.Archive; + + /// + /// Indicates current state of the mail list. Doesn't matter it's loading or no. + /// + public bool IsEmpty => MailCollection.Count == 0; + + /// + /// Progress ring only should be visible when the folder is initializing and there are no items. We don't need to show it when there are items. + /// + public bool IsProgressRing => IsInitializingFolder && IsEmpty; + private bool isFilters => IsInSearchMode || SelectedFilterOption.Type != FilterOptionType.All; + public bool IsCriteriaFailed => !IsInitializingFolder && IsEmpty && isFilters; + public bool IsFolderEmpty => !IsInitializingFolder && IsEmpty && !isFilters; + + public bool IsInSearchMode { get; set; } + + #endregion + private async void ActiveMailItemChanged(MailItemViewModel selectedMailItemViewModel) { if (_activeMailItem == selectedMailItemViewModel) return; @@ -245,83 +268,6 @@ namespace Wino.Mail.ViewModels } } - /// - /// Selected internal folder. This can be either folder's own name or Focused-Other. - /// - public FolderPivotViewModel SelectedFolderPivot - { - get => _selectedFolderPivot; - set - { - if (_selectedFolderPivot != null) - _selectedFolderPivot.SelectedItemCount = 0; - - SetProperty(ref _selectedFolderPivot, value); - } - } - - /// - /// Selected sorting option. - /// - public SortingOption SelectedSortingOption - { - get => _selectedSortingOption; - set - { - if (SetProperty(ref _selectedSortingOption, value)) - { - if (value != null && MailCollection != null) - { - MailCollection.SortingType = value.Type; - } - } - } - } - - /// - /// Current folder that is being represented from the menu. - /// - [ObservableProperty] - [NotifyPropertyChangedFor(nameof(CanSynchronize))] - [NotifyPropertyChangedFor(nameof(IsFolderSynchronizationEnabled))] - private IBaseFolderMenuItem activeFolder; - - [ObservableProperty] - [NotifyPropertyChangedFor(nameof(CanSynchronize))] - private bool isAccountSynchronizerInSynchronization; - - public bool CanSynchronize => !IsAccountSynchronizerInSynchronization && IsFolderSynchronizationEnabled; - - public bool IsFolderSynchronizationEnabled => ActiveFolder?.IsSynchronizationEnabled ?? false; - - #region Properties - - public int SelectedItemCount => SelectedItems.Count; - public bool HasMultipleItemSelections => SelectedItemCount > 1; - public bool HasSelectedItems => SelectedItems.Any(); - public bool IsArchiveSpecialFolder => ActiveFolder?.SpecialFolderType == SpecialFolderType.Archive; - public bool IsEmpty => !IsPerformingSearch && MailCollection.Count == 0; - public bool IsCriteriaFailed => IsEmpty && IsInSearchMode; - public bool IsFolderEmpty => !IsInitializingFolder && IsEmpty && !IsInSearchMode; - - private bool _isPerformingSearch; - - public bool IsPerformingSearch - { - get => _isPerformingSearch; - set - { - if (SetProperty(ref _isPerformingSearch, value)) - { - NotifyItemFoundState(); - } - } - } - - public bool IsInSearchMode => !string.IsNullOrEmpty(SearchQuery); - - #endregion - public void NotifyItemSelected() { OnPropertyChanged(nameof(HasSelectedItems)); @@ -339,11 +285,6 @@ namespace Wino.Mail.ViewModels OnPropertyChanged(nameof(IsFolderEmpty)); } - [RelayCommand] - public Task ExecuteHoverAction(MailOperationPreperationRequest request) => ExecuteMailOperationAsync(request); - - public Task ExecuteMailOperationAsync(MailOperationPreperationRequest package) => _winoRequestDelegator.ExecuteAsync(package); - protected override void OnDispatcherAssigned() { base.OnDispatcherAssigned(); @@ -444,6 +385,58 @@ namespace Wino.Mail.ViewModels SelectedFolderPivot = PivotFolders.FirstOrDefault(); } + #region Commands + + [RelayCommand] + public Task ExecuteHoverAction(MailOperationPreperationRequest request) => ExecuteMailOperationAsync(request); + + /// + /// Executes the requested mail operation for currently selected items. + /// + /// Action to execute for selected items. + [RelayCommand] + private async Task MailOperationAsync(int mailOperationIndex) + { + if (!SelectedItems.Any()) return; + + // Commands don't like enums. So it has to be int. + var operation = (MailOperation)mailOperationIndex; + + var package = new MailOperationPreperationRequest(operation, SelectedItems.Select(a => a.MailCopy)); + + await ExecuteMailOperationAsync(package); + } + + /// + /// Sens a new message to synchronize current folder. + /// + [RelayCommand] + private void SyncFolder() + { + if (!CanSynchronize) return; + + // Only synchronize listed folders. + + // When doing linked inbox sync, we need to save the sync id to report progress back only once. + // Otherwise, we will report progress for each folder and that's what we don't want. + + trackingSynchronizationId = Guid.NewGuid(); + completedTrackingSynchronizationCount = 0; + + foreach (var folder in ActiveFolder.HandlingFolders) + { + var options = new SynchronizationOptions() + { + AccountId = folder.MailAccountId, + Type = SynchronizationType.Custom, + SynchronizationFolderIds = [folder.Id], + GroupedSynchronizationTrackingId = trackingSynchronizationId + }; + + Messenger.Send(new NewSynchronizationRequested(options)); + } + } + [RelayCommand] private async Task SelectedPivotChanged() { @@ -472,6 +465,84 @@ namespace Wino.Mail.ViewModels await InitializeFolderAsync(); } + [RelayCommand] + public async Task PerformSearchAsync() + { + if (string.IsNullOrEmpty(SearchQuery) && IsInSearchMode) + { + UpdateFolderPivots(); + IsInSearchMode = false; + await InitializeFolderAsync(); + } + + if (!string.IsNullOrEmpty(SearchQuery)) + { + + IsInSearchMode = true; + CreateSearchPivot(); + } + + void CreateSearchPivot() + { + PivotFolders.Clear(); + var isFocused = SelectedFolderPivot?.IsFocused; + SelectedFolderPivot = null; + + if (ActiveFolder == null) return; + + PivotFolders.Add(new FolderPivotViewModel(Translator.SearchPivotName, isFocused)); + + // This will trigger refresh. + SelectedFolderPivot = PivotFolders.FirstOrDefault(); + } + } + + [RelayCommand] + private async Task EnableFolderSynchronizationAsync() + { + if (ActiveFolder == null) return; + + foreach (var folder in ActiveFolder.HandlingFolders) + { + await _folderService.ChangeFolderSynchronizationStateAsync(folder.Id, true); + } + + // TODO + //ActiveFolder.IsSynchronizationEnabled = true; + + //OnPropertyChanged(nameof(IsFolderSynchronizationEnabled)); + //OnPropertyChanged(nameof(CanSynchronize)); + + //SyncFolderCommand?.Execute(null); + } + + [RelayCommand] + private async Task LoadMoreItemsAsync() + { + if (IsInitializingFolder) return; + + await ExecuteUIThread(() => { IsInitializingFolder = true; }); + + var initializationOptions = new MailListInitializationOptions(ActiveFolder.HandlingFolders, + SelectedFilterOption.Type, + SelectedSortingOption.Type, + PreferencesService.IsThreadingEnabled, + SelectedFolderPivot.IsFocused, + IsInSearchMode ? SearchQuery : string.Empty, + MailCollection.MailCopyIdHashSet); + + var items = await _mailService.FetchMailsAsync(initializationOptions).ConfigureAwait(false); + + var viewModels = PrepareMailViewModels(items); + + await ExecuteUIThread(() => { MailCollection.AddRange(viewModels, clearIdCache: false); }); + await ExecuteUIThread(() => { IsInitializingFolder = false; }); + } + + #endregion + + public Task ExecuteMailOperationAsync(MailOperationPreperationRequest package) => _winoRequestDelegator.ExecuteAsync(package); + public IEnumerable GetTargetMailItemViewModels(IMailItem clickedItem) { // Threat threads as a whole and include everything in the group. Except single selections outside of the thread. @@ -496,7 +567,7 @@ namespace Wino.Mail.ViewModels if (includedInSelectedItems) contextMailItems = SelectedItems; else - contextMailItems = new List() { clickedMailItemViewModel }; + contextMailItems = [clickedMailItemViewModel]; } return contextMailItems; @@ -506,7 +577,7 @@ namespace Wino.Mail.ViewModels => _contextMenuItemService.GetMailItemContextMenuActions(contextMailItems); public void ChangeCustomFocusedState(IEnumerable mailItems, bool isFocused) - => mailItems.Where(a => a is MailItemViewModel).Cast().ForEach(a => a.IsCustomFocused = isFocused); + => mailItems.OfType().ForEach(a => a.IsCustomFocused = isFocused); private bool ShouldPreventItemAdd(IMailItem mailItem) { @@ -650,29 +721,6 @@ namespace Wino.Mail.ViewModels } } - [RelayCommand] - private async Task LoadMoreItemsAsync() - { - if (IsInitializingFolder) return; - - await ExecuteUIThread(() => { IsInitializingFolder = true; }); - - var initializationOptions = new MailListInitializationOptions(ActiveFolder.HandlingFolders, - SelectedFilterOption.Type, - SelectedSortingOption.Type, - PreferencesService.IsThreadingEnabled, - SelectedFolderPivot.IsFocused, - SearchQuery, - MailCollection.MailCopyIdHashSet); - - var items = await _mailService.FetchMailsAsync(initializationOptions).ConfigureAwait(false); - - var viewModels = PrepareMailViewModels(items); - - await ExecuteUIThread(() => { MailCollection.AddRange(viewModels, clearIdCache: false); }); - await ExecuteUIThread(() => { IsInitializingFolder = false; }); - } - private async Task InitializeFolderAsync() { if (SelectedFilterOption == null || SelectedFolderPivot == null || SelectedSortingOption == null) @@ -680,10 +728,6 @@ namespace Wino.Mail.ViewModels try { - // Clear search query if not performing search. - if (!IsPerformingSearch) - SearchQuery = string.Empty; - MailCollection.Clear(); MailCollection.MailCopyIdHashSet.Clear(); @@ -768,53 +812,12 @@ namespace Wino.Mail.ViewModels } } - [RelayCommand] - private async Task EnableFolderSynchronizationAsync() - { - if (ActiveFolder == null) return; + #region Receivers + void IRecipient.Receive(MailItemSelectedEvent message) + => SelectedItems.Add(message.SelectedMailItem); - foreach (var folder in ActiveFolder.HandlingFolders) - { - await _folderService.ChangeFolderSynchronizationStateAsync(folder.Id, true); - } - - // TODO - //ActiveFolder.IsSynchronizationEnabled = true; - - //OnPropertyChanged(nameof(IsFolderSynchronizationEnabled)); - //OnPropertyChanged(nameof(CanSynchronize)); - - //SyncFolderCommand?.Execute(null); - } - - void IRecipient.Receive(MailItemNavigationRequested message) - { - // Find mail item and add to selected items. - - MailItemViewModel navigatingMailItem = null; - ThreadMailItemViewModel threadMailItemViewModel = null; - - for (int i = 0; i < 3; i++) - { - var mailContainer = MailCollection.GetMailItemContainer(message.UniqueMailId); - - if (mailContainer != null) - { - navigatingMailItem = mailContainer.ItemViewModel; - threadMailItemViewModel = mailContainer.ThreadViewModel; - - break; - } - } - - if (threadMailItemViewModel != null) - threadMailItemViewModel.IsThreadExpanded = true; - - if (navigatingMailItem != null) - WeakReferenceMessenger.Default.Send(new SelectMailItemContainerEvent(navigatingMailItem, message.ScrollToItem)); - else - Debugger.Break(); - } + void IRecipient.Receive(MailItemSelectionRemovedEvent message) + => SelectedItems.Remove(message.RemovedMailItem); async void IRecipient.Receive(ActiveMailFolderChangedEvent message) { @@ -835,6 +838,9 @@ namespace Wino.Mail.ViewModels // Prepare Focused - Other or folder name tabs. UpdateFolderPivots(); + // Reset filters and sorting options. + ResetFilters(); + await InitializeFolderAsync(); // TODO: This should be done in a better way. @@ -847,14 +853,17 @@ namespace Wino.Mail.ViewModels message.FolderInitLoadAwaitTask?.TrySetResult(true); isChangingFolder = false; + + void ResetFilters() + { + // Expected that FilterOptions and SortingOptions have default value in 0 index. + SelectedFilterOption = FilterOptions[0]; + SelectedSortingOption = SortingOptions[0]; + SearchQuery = string.Empty; + IsInSearchMode = false; + } } - void IRecipient.Receive(MailItemSelectedEvent message) - => SelectedItems.Add(message.SelectedMailItem); - - void IRecipient.Receive(MailItemSelectionRemovedEvent message) - => SelectedItems.Remove(message.RemovedMailItem); - public void Receive(AccountSynchronizationCompleted message) { if (ActiveFolder == null) return; @@ -889,24 +898,40 @@ namespace Wino.Mail.ViewModels } } + void IRecipient.Receive(MailItemNavigationRequested message) + { + // Find mail item and add to selected items. + + MailItemViewModel navigatingMailItem = null; + ThreadMailItemViewModel threadMailItemViewModel = null; + + for (int i = 0; i < 3; i++) + { + var mailContainer = MailCollection.GetMailItemContainer(message.UniqueMailId); + + if (mailContainer != null) + { + navigatingMailItem = mailContainer.ItemViewModel; + threadMailItemViewModel = mailContainer.ThreadViewModel; + + break; + } + } + + if (threadMailItemViewModel != null) + threadMailItemViewModel.IsThreadExpanded = true; + + if (navigatingMailItem != null) + WeakReferenceMessenger.Default.Send(new SelectMailItemContainerEvent(navigatingMailItem, message.ScrollToItem)); + else + Debugger.Break(); + } + + #endregion + public async void Receive(NewSynchronizationRequested message) => await ExecuteUIThread(() => { OnPropertyChanged(nameof(CanSynchronize)); }); - [RelayCommand] - public async Task PerformSearchAsync() - { - try - { - IsPerformingSearch = !string.IsNullOrEmpty(SearchQuery); - - await InitializeFolderAsync(); - } - finally - { - IsPerformingSearch = false; - } - } - public async void Receive(AccountSynchronizerStateChanged message) => await CheckIfAccountIsSynchronizingAsync(); diff --git a/Wino.Mail/Controls/Advanced/WinoListView.cs b/Wino.Mail/Controls/Advanced/WinoListView.cs index a6382321..a1f7ece3 100644 --- a/Wino.Mail/Controls/Advanced/WinoListView.cs +++ b/Wino.Mail/Controls/Advanced/WinoListView.cs @@ -205,7 +205,7 @@ namespace Wino.Controls.Advanced { bool found = false; - Items.Where(a => a is ThreadMailItemViewModel).Cast().ForEach(c => + Items.OfType().ForEach(c => { if (!found) { diff --git a/Wino.Mail/Views/MailListPage.xaml b/Wino.Mail/Views/MailListPage.xaml index bab8c1bb..1cad33f7 100644 --- a/Wino.Mail/Views/MailListPage.xaml +++ b/Wino.Mail/Views/MailListPage.xaml @@ -391,6 +391,7 @@ PlaceholderText="{x:Bind domain:Translator.SearchBarPlaceholder}" QueryIcon="Find" TabIndex="1000" + TextChanged="SearchBar_TextChanged" Text="{x:Bind ViewModel.SearchQuery, Mode=TwoWay}"> @@ -402,17 +403,16 @@ - + @@ -590,36 +590,6 @@ x:Load="{x:Bind ViewModel.IsInitializingFolder, Mode=OneWay}" /> - - - - - - - - - - - - - + + + + Visibility="{x:Bind ViewModel.IsEmpty, Converter={StaticResource ReverseBooleanToVisibilityConverter}, Mode=OneWay}"> - - - - - - - - - - - - -