From b6176dce485ec28506e928380e2fcf63b61b6f77 Mon Sep 17 00:00:00 2001 From: Filippo Ferrario Date: Tue, 18 Jul 2023 23:09:03 +0200 Subject: [PATCH 1/8] Feature: Open all items in a tag --- .../Content/Tags/OpenAllTaggedActions.cs | 56 ++++++++++++++ src/Files.App/App.xaml.cs | 1 + src/Files.App/Data/Commands/CommandCodes.cs | 3 + .../Data/Commands/Manager/CommandManager.cs | 2 + .../Data/Commands/Manager/ICommandManager.cs | 2 + .../Data/Contexts/Tags/ITagsContext.cs | 12 +++ .../Data/Contexts/Tags/TagsContext.cs | 41 ++++++++++ src/Files.App/Strings/en-US/Resources.resw | 6 ++ .../UserControls/Widgets/FileTagsWidget.xaml | 6 +- .../Widgets/FileTagsWidget.xaml.cs | 76 ++++++++++++++++--- 10 files changed, 193 insertions(+), 12 deletions(-) create mode 100644 src/Files.App/Actions/Content/Tags/OpenAllTaggedActions.cs create mode 100644 src/Files.App/Data/Contexts/Tags/ITagsContext.cs create mode 100644 src/Files.App/Data/Contexts/Tags/TagsContext.cs diff --git a/src/Files.App/Actions/Content/Tags/OpenAllTaggedActions.cs b/src/Files.App/Actions/Content/Tags/OpenAllTaggedActions.cs new file mode 100644 index 000000000000..3ae1f7dc8776 --- /dev/null +++ b/src/Files.App/Actions/Content/Tags/OpenAllTaggedActions.cs @@ -0,0 +1,56 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +namespace Files.App.Actions +{ + sealed class OpenAllTaggedActions: ObservableObject, IAction + { + private readonly IContentPageContext _pageContext; + + private readonly ITagsContext _tagsContext; + + public string Label + => "OpenAllItems".GetLocalizedResource(); + + public string Description + => "OpenAllItemsDescription".GetLocalizedResource(); + + public RichGlyph Glyph + => new("\uE71D"); + + public bool IsExecutable => + _pageContext.ShellPage is not null && + _tagsContext.TaggedItems.Any(); + + public OpenAllTaggedActions() + { + _pageContext = Ioc.Default.GetRequiredService(); + _tagsContext = Ioc.Default.GetRequiredService(); + + _pageContext.PropertyChanged += Context_PropertyChanged; + _tagsContext.PropertyChanged += Context_PropertyChanged; + } + + public async Task ExecuteAsync() + { + var files = _tagsContext.TaggedItems.Where(item => !item.IsFolder); + var folders = _tagsContext.TaggedItems.Where(item => item.IsFolder); + + await Task.WhenAll(files.Select(file + => NavigationHelpers.OpenPath(file.Path, _pageContext.ShellPage!))); + + folders.ForEach(async folder => await NavigationHelpers.OpenPathInNewTab(folder.Path)); + } + + private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e) + { + switch (e.PropertyName) + { + case nameof(IContentPageContext.ShellPage): + case nameof(ITagsContext.TaggedItems): + OnPropertyChanged(nameof(IsExecutable)); + break; + } + } + } +} diff --git a/src/Files.App/App.xaml.cs b/src/Files.App/App.xaml.cs index 71e457778ffd..1a2068d143be 100644 --- a/src/Files.App/App.xaml.cs +++ b/src/Files.App/App.xaml.cs @@ -117,6 +117,7 @@ private IHost ConfigureHost() .AddSingleton() .AddSingleton() .AddSingleton() + .AddSingleton() .AddSingleton() .AddSingleton() .AddSingleton() diff --git a/src/Files.App/Data/Commands/CommandCodes.cs b/src/Files.App/Data/Commands/CommandCodes.cs index d58cec6ebbfb..34dfb695b6a6 100644 --- a/src/Files.App/Data/Commands/CommandCodes.cs +++ b/src/Files.App/Data/Commands/CommandCodes.cs @@ -190,5 +190,8 @@ public enum CommandCodes GitPull, GitPush, GitSync, + + // Tags + OpenAllTaggedItems, } } diff --git a/src/Files.App/Data/Commands/Manager/CommandManager.cs b/src/Files.App/Data/Commands/Manager/CommandManager.cs index e8f991b81738..9c92bb821104 100644 --- a/src/Files.App/Data/Commands/Manager/CommandManager.cs +++ b/src/Files.App/Data/Commands/Manager/CommandManager.cs @@ -166,6 +166,7 @@ public IRichCommand this[HotKey hotKey] public IRichCommand GitPull => commands[CommandCodes.GitPull]; public IRichCommand GitPush => commands[CommandCodes.GitPush]; public IRichCommand GitSync => commands[CommandCodes.GitSync]; + public IRichCommand OpenAllTaggedItems => commands[CommandCodes.OpenAllTaggedItems]; public CommandManager() { @@ -326,6 +327,7 @@ public CommandManager() [CommandCodes.GitPull] = new GitPullAction(), [CommandCodes.GitPush] = new GitPushAction(), [CommandCodes.GitSync] = new GitSyncAction(), + [CommandCodes.OpenAllTaggedItems] = new OpenAllTaggedActions(), }; private void UpdateHotKeys() diff --git a/src/Files.App/Data/Commands/Manager/ICommandManager.cs b/src/Files.App/Data/Commands/Manager/ICommandManager.cs index 55f4ed037525..ea9840303a60 100644 --- a/src/Files.App/Data/Commands/Manager/ICommandManager.cs +++ b/src/Files.App/Data/Commands/Manager/ICommandManager.cs @@ -169,5 +169,7 @@ public interface ICommandManager : IEnumerable IRichCommand GitPull { get; } IRichCommand GitPush { get; } IRichCommand GitSync { get; } + + IRichCommand OpenAllTaggedItems { get; } } } diff --git a/src/Files.App/Data/Contexts/Tags/ITagsContext.cs b/src/Files.App/Data/Contexts/Tags/ITagsContext.cs new file mode 100644 index 000000000000..e755aa424afd --- /dev/null +++ b/src/Files.App/Data/Contexts/Tags/ITagsContext.cs @@ -0,0 +1,12 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +using Files.App.ViewModels.Widgets; + +namespace Files.App.Data.Contexts +{ + interface ITagsContext: INotifyPropertyChanged + { + IEnumerable TaggedItems { get; } + } +} diff --git a/src/Files.App/Data/Contexts/Tags/TagsContext.cs b/src/Files.App/Data/Contexts/Tags/TagsContext.cs new file mode 100644 index 000000000000..15b3548c11bd --- /dev/null +++ b/src/Files.App/Data/Contexts/Tags/TagsContext.cs @@ -0,0 +1,41 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +using Files.App.UserControls.Widgets; +using Files.App.ViewModels.Widgets; +using System.Collections.Immutable; + +namespace Files.App.Data.Contexts +{ + sealed class TagsContext : ITagsContext + { + private static readonly IReadOnlyList _emptyTaggedItemsList + = Enumerable.Empty().ToImmutableList(); + + public event PropertyChangedEventHandler? PropertyChanged; + + private IEnumerable _TaggedItems = _emptyTaggedItemsList; + public IEnumerable TaggedItems + { + get => _TaggedItems; + set + { + _TaggedItems = value is not null + ? value + : _emptyTaggedItemsList; + + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TaggedItems))); + } + } + + public TagsContext() + { + FileTagsWidget.RightClickedTagsChanged += FileTagsWidget_RightClickedTagsChanged; + } + + private void FileTagsWidget_RightClickedTagsChanged(object sender, IEnumerable items) + { + TaggedItems = items; + } + } +} diff --git a/src/Files.App/Strings/en-US/Resources.resw b/src/Files.App/Strings/en-US/Resources.resw index 09ff3f9ec5d4..fffe3db77330 100644 --- a/src/Files.App/Strings/en-US/Resources.resw +++ b/src/Files.App/Strings/en-US/Resources.resw @@ -3398,4 +3398,10 @@ Open directory in new window + + Open all + + + Open all tagged items + \ No newline at end of file diff --git a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml index a06cc033ef22..8901fcad3d77 100644 --- a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml +++ b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml @@ -51,7 +51,11 @@ - + diff --git a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs index df216b42ccad..3281f4cf78fd 100644 --- a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs +++ b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs @@ -1,6 +1,7 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. +using CommunityToolkit.WinUI.UI.Controls; using Files.App.Helpers.ContextFlyouts; using Files.App.ViewModels.Widgets; using Microsoft.UI.Xaml; @@ -17,22 +18,29 @@ namespace Files.App.UserControls.Widgets { public sealed partial class FileTagsWidget : HomePageWidget, IWidgetItemModel { + private readonly ICommandManager _commands; + + private readonly ITagsContext _tagsContext; + + private readonly IUserSettingsService userSettingsService; + public FileTagsWidgetViewModel ViewModel { get => (FileTagsWidgetViewModel)DataContext; set => DataContext = value; } - private readonly IUserSettingsService userSettingsService = Ioc.Default.GetRequiredService(); - public IShellPage AppInstance; + public Func? OpenAction { get; set; } public delegate void FileTagsOpenLocationInvokedEventHandler(object sender, PathNavigationEventArgs e); public delegate void FileTagsNewPaneInvokedEventHandler(object sender, QuickAccessCardInvokedEventArgs e); + public delegate void RightClickedTagsChangedEventHandler(object sender, IEnumerable items); public event FileTagsOpenLocationInvokedEventHandler FileTagsOpenLocationInvoked; public event FileTagsNewPaneInvokedEventHandler FileTagsNewPaneInvoked; + public static event RightClickedTagsChangedEventHandler? RightClickedTagsChanged; public string WidgetName => nameof(FileTagsWidget); @@ -50,6 +58,10 @@ public FileTagsWidgetViewModel ViewModel public FileTagsWidget() { + _commands = Ioc.Default.GetRequiredService(); + _tagsContext = Ioc.Default.GetRequiredService(); + userSettingsService = Ioc.Default.GetRequiredService(); + InitializeComponent(); // Second function is layered on top to ensure that OpenPath function is late initialized and a null reference is not passed-in @@ -67,13 +79,13 @@ public FileTagsWidget() private void OpenProperties(WidgetCardItem? item) { EventHandler flyoutClosed = null!; - flyoutClosed = async (s, e) => + flyoutClosed = (s, e) => { ItemContextMenuFlyout.Closed -= flyoutClosed; ListedItem listedItem = new(null!) { - ItemPath = (item.Item as FileTagsItemViewModel).Path, - ItemNameRaw = (item.Item as FileTagsItemViewModel).Name, + ItemPath = (item.Item as FileTagsItemViewModel)?.Path ?? string.Empty, + ItemNameRaw = (item.Item as FileTagsItemViewModel)?.Name ?? string.Empty, PrimaryItemAttribute = StorageItemTypes.Folder, ItemType = "Folder".GetLocalizedResource(), }; @@ -96,14 +108,47 @@ private async void FileTagItem_ItemClick(object sender, ItemClickEventArgs e) await itemViewModel.ClickCommand.ExecuteAsync(null); } - private async void AdaptiveGridView_RightTapped(object sender, RightTappedRoutedEventArgs e) + private void AdaptiveGridView_RightTapped(object sender, RightTappedRoutedEventArgs e) + { + if (e.OriginalSource is not FrameworkElement element || + element.DataContext is not FileTagsItemViewModel item) + { + return; + } + + LoadContextMenu( + element, + e, + GetItemMenuItems(item, QuickAccessService.IsItemPinned(item.Path), item.IsFolder), + rightClickedItem: item); + } + + public void TagTitle_RightTapped(object sender, RightTappedRoutedEventArgs e) + { + if (sender is not FrameworkElement element || + element.Parent is not Grid parent || + parent.Children[1] is not AdaptiveGridView gridView) + { + return; + } + + RightClickedTagsChanged?.Invoke(this, gridView.Items.Select(item => (FileTagsItemViewModel)item)); + + LoadContextMenu( + element, + e, + GetWidgetMenuItems()); + } + + private async void LoadContextMenu( + FrameworkElement element, + RightTappedRoutedEventArgs e, + List menuItems, + FileTagsItemViewModel? rightClickedItem = null) { var itemContextMenuFlyout = new CommandBarFlyout { Placement = FlyoutPlacementMode.Full }; itemContextMenuFlyout.Opening += (sender, e) => App.LastOpenedFlyout = sender as CommandBarFlyout; - if (e.OriginalSource is not FrameworkElement element || element.DataContext is not FileTagsItemViewModel item) - return; - var menuItems = GetItemMenuItems(item, QuickAccessService.IsItemPinned(item.Path), item.IsFolder); var (_, secondaryElements) = ItemModelListToContextFlyoutHelper.GetAppBarItemsFromModel(menuItems); if (!UserSettingsService.GeneralSettingsService.MoveShellExtensionsToSubMenu) @@ -113,8 +158,9 @@ private async void AdaptiveGridView_RightTapped(object sender, RightTappedRouted secondaryElements.ForEach(i => itemContextMenuFlyout.SecondaryCommands.Add(i)); ItemContextMenuFlyout = itemContextMenuFlyout; itemContextMenuFlyout.ShowAt(element, new FlyoutShowOptions { Position = e.GetPosition(element) }); + if (rightClickedItem is not null) + await ShellContextmenuHelper.LoadShellMenuItems(rightClickedItem.Path, itemContextMenuFlyout, showOpenWithMenu: true, showSendToMenu: true); - await ShellContextmenuHelper.LoadShellMenuItems(item.Path, itemContextMenuFlyout, showOpenWithMenu: true, showSendToMenu: true); e.Handled = true; } @@ -222,6 +268,14 @@ public override List GetItemMenuItems(WidgetCard }.Where(x => x.ShowItem).ToList(); } + public List GetWidgetMenuItems() + { + return new List() + { + new ContextMenuFlyoutItemViewModelBuilder(_commands.OpenAllTaggedItems).Build() + }; + } + public void OpenFileLocation(WidgetCardItem? item) { FileTagsOpenLocationInvoked?.Invoke(this, new PathNavigationEventArgs() @@ -240,4 +294,4 @@ public void Dispose() { } } -} +} \ No newline at end of file From c322fbe76c549b5382e75e1230277f210b9c0650 Mon Sep 17 00:00:00 2001 From: Filippo Ferrario Date: Tue, 18 Jul 2023 23:11:43 +0200 Subject: [PATCH 2/8] New line --- src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs index 3281f4cf78fd..a26f8d5c8921 100644 --- a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs +++ b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs @@ -294,4 +294,4 @@ public void Dispose() { } } -} \ No newline at end of file +} From 384c46ca6cf8a2fadf9a8d956854ce245c1a4785 Mon Sep 17 00:00:00 2001 From: Yair <39923744+yaira2@users.noreply.github.com> Date: Tue, 18 Jul 2023 18:36:47 -0400 Subject: [PATCH 3/8] Update FileTagsWidget.xaml --- .../UserControls/Widgets/FileTagsWidget.xaml | 33 ++++++++++--------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml index 8901fcad3d77..d123e9457f6f 100644 --- a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml +++ b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml @@ -62,32 +62,33 @@ - - - - - - - - + + + + + + + + + + + + Glyph="" /> From 5a8a5fcb257a349e271fe5d0ead0cea12060f88d Mon Sep 17 00:00:00 2001 From: Yair <39923744+yaira2@users.noreply.github.com> Date: Tue, 18 Jul 2023 18:38:46 -0400 Subject: [PATCH 4/8] Update FileTagsWidget.xaml --- src/Files.App/UserControls/Widgets/FileTagsWidget.xaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml index d123e9457f6f..44b220cef641 100644 --- a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml +++ b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml @@ -68,9 +68,7 @@ AutomationProperties.Name="{helpers:ResourceString Name=ViewMore}" Command="{x:Bind ViewMoreCommand}" ToolTipService.ToolTip="{helpers:ResourceString Name=ViewMore}"> - + From 66cbdcb17bccd1c140bee69be9f8531edac6bf2d Mon Sep 17 00:00:00 2001 From: Yair <39923744+yaira2@users.noreply.github.com> Date: Tue, 18 Jul 2023 18:42:25 -0400 Subject: [PATCH 5/8] Update FileTagsWidget.xaml --- src/Files.App/UserControls/Widgets/FileTagsWidget.xaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml index 44b220cef641..f1d05cee818a 100644 --- a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml +++ b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml @@ -76,6 +76,7 @@ @@ -86,6 +87,7 @@ From 7d58a3b91411bb2e3c6529044d7e51a6ef5ac85d Mon Sep 17 00:00:00 2001 From: Filippo Ferrario Date: Wed, 19 Jul 2023 11:02:49 +0200 Subject: [PATCH 6/8] Remove ContextMenu and use HyperLinkButton --- .../Data/Contexts/Tags/TagsContext.cs | 5 ++- .../UserControls/Widgets/FileTagsWidget.xaml | 17 +++++----- .../Widgets/FileTagsWidget.xaml.cs | 34 ------------------- .../Widgets/FileTagsContainerViewModel.cs | 27 ++++++++++++--- 4 files changed, 34 insertions(+), 49 deletions(-) diff --git a/src/Files.App/Data/Contexts/Tags/TagsContext.cs b/src/Files.App/Data/Contexts/Tags/TagsContext.cs index 15b3548c11bd..1f14725160c8 100644 --- a/src/Files.App/Data/Contexts/Tags/TagsContext.cs +++ b/src/Files.App/Data/Contexts/Tags/TagsContext.cs @@ -1,7 +1,6 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. -using Files.App.UserControls.Widgets; using Files.App.ViewModels.Widgets; using System.Collections.Immutable; @@ -30,10 +29,10 @@ public IEnumerable TaggedItems public TagsContext() { - FileTagsWidget.RightClickedTagsChanged += FileTagsWidget_RightClickedTagsChanged; + FileTagsContainerViewModel.SelectedTagsChanged += FileTagsContainerViewModel_SelectedTagsChanged; } - private void FileTagsWidget_RightClickedTagsChanged(object sender, IEnumerable items) + private void FileTagsContainerViewModel_SelectedTagsChanged(object sender, IEnumerable items) { TaggedItems = items; } diff --git a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml index f1d05cee818a..bc1017e9848f 100644 --- a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml +++ b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml @@ -8,6 +8,7 @@ xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:helpers="using:Files.App.Helpers" xmlns:local="using:Files.App.UserControls.Widgets" + xmlns:localcontrols="using:Files.App.UserControls" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:vm="using:Files.App.ViewModels.Widgets" d:DesignHeight="300" @@ -54,8 +55,7 @@ + BorderThickness="0,0,0,1"> @@ -82,13 +82,14 @@ - + - + diff --git a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs index a26f8d5c8921..e2ce75293de7 100644 --- a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs +++ b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs @@ -1,7 +1,6 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. -using CommunityToolkit.WinUI.UI.Controls; using Files.App.Helpers.ContextFlyouts; using Files.App.ViewModels.Widgets; using Microsoft.UI.Xaml; @@ -18,10 +17,6 @@ namespace Files.App.UserControls.Widgets { public sealed partial class FileTagsWidget : HomePageWidget, IWidgetItemModel { - private readonly ICommandManager _commands; - - private readonly ITagsContext _tagsContext; - private readonly IUserSettingsService userSettingsService; public FileTagsWidgetViewModel ViewModel @@ -36,11 +31,9 @@ public FileTagsWidgetViewModel ViewModel public delegate void FileTagsOpenLocationInvokedEventHandler(object sender, PathNavigationEventArgs e); public delegate void FileTagsNewPaneInvokedEventHandler(object sender, QuickAccessCardInvokedEventArgs e); - public delegate void RightClickedTagsChangedEventHandler(object sender, IEnumerable items); public event FileTagsOpenLocationInvokedEventHandler FileTagsOpenLocationInvoked; public event FileTagsNewPaneInvokedEventHandler FileTagsNewPaneInvoked; - public static event RightClickedTagsChangedEventHandler? RightClickedTagsChanged; public string WidgetName => nameof(FileTagsWidget); @@ -58,8 +51,6 @@ public FileTagsWidgetViewModel ViewModel public FileTagsWidget() { - _commands = Ioc.Default.GetRequiredService(); - _tagsContext = Ioc.Default.GetRequiredService(); userSettingsService = Ioc.Default.GetRequiredService(); InitializeComponent(); @@ -123,23 +114,6 @@ private void AdaptiveGridView_RightTapped(object sender, RightTappedRoutedEventA rightClickedItem: item); } - public void TagTitle_RightTapped(object sender, RightTappedRoutedEventArgs e) - { - if (sender is not FrameworkElement element || - element.Parent is not Grid parent || - parent.Children[1] is not AdaptiveGridView gridView) - { - return; - } - - RightClickedTagsChanged?.Invoke(this, gridView.Items.Select(item => (FileTagsItemViewModel)item)); - - LoadContextMenu( - element, - e, - GetWidgetMenuItems()); - } - private async void LoadContextMenu( FrameworkElement element, RightTappedRoutedEventArgs e, @@ -268,14 +242,6 @@ public override List GetItemMenuItems(WidgetCard }.Where(x => x.ShowItem).ToList(); } - public List GetWidgetMenuItems() - { - return new List() - { - new ContextMenuFlyoutItemViewModelBuilder(_commands.OpenAllTaggedItems).Build() - }; - } - public void OpenFileLocation(WidgetCardItem? item) { FileTagsOpenLocationInvoked?.Invoke(this, new PathNavigationEventArgs() diff --git a/src/Files.App/ViewModels/Widgets/FileTagsContainerViewModel.cs b/src/Files.App/ViewModels/Widgets/FileTagsContainerViewModel.cs index c73b3482a1a9..365a8598444d 100644 --- a/src/Files.App/ViewModels/Widgets/FileTagsContainerViewModel.cs +++ b/src/Files.App/ViewModels/Widgets/FileTagsContainerViewModel.cs @@ -9,11 +9,18 @@ namespace Files.App.ViewModels.Widgets public sealed partial class FileTagsContainerViewModel : ObservableObject, IAsyncInitialize { private readonly string _tagUid; + private readonly Func _openAction; - private IFileTagsService FileTagsService { get; } = Ioc.Default.GetRequiredService(); + private readonly IFileTagsService _fileTagsService; + + private readonly IImageService _imageService; + + private readonly ICommandManager _commands; - private IImageService ImageService { get; } = Ioc.Default.GetRequiredService(); + public delegate void SelectedTagsChangedEventHandler(object sender, IEnumerable items); + + public static event SelectedTagsChangedEventHandler? SelectedTagsChanged; public ObservableCollection Tags { get; } @@ -25,6 +32,10 @@ public sealed partial class FileTagsContainerViewModel : ObservableObject, IAsyn public FileTagsContainerViewModel(string tagUid, Func openAction) { + _fileTagsService = Ioc.Default.GetRequiredService(); + _imageService = Ioc.Default.GetRequiredService(); + _commands = Ioc.Default.GetRequiredService(); + _tagUid = tagUid; _openAction = openAction; Tags = new(); @@ -33,9 +44,9 @@ public FileTagsContainerViewModel(string tagUid, Func openAction) /// public async Task InitAsync(CancellationToken cancellationToken = default) { - await foreach (var item in FileTagsService.GetItemsForTagAsync(_tagUid, cancellationToken)) + await foreach (var item in _fileTagsService.GetItemsForTagAsync(_tagUid, cancellationToken)) { - var icon = await ImageService.GetIconAsync(item.Storable, cancellationToken); + var icon = await _imageService.GetIconAsync(item.Storable, cancellationToken); Tags.Add(new(item.Storable, _openAction, icon)); } } @@ -45,5 +56,13 @@ private Task ViewMore(CancellationToken cancellationToken) { return _openAction($"tag:{Name}"); } + + [RelayCommand] + private Task OpenAll(CancellationToken cancellationToken) + { + SelectedTagsChanged?.Invoke(this, Tags); + + return _commands.OpenAllTaggedItems.ExecuteAsync(); + } } } From 64bc94ceb0da44da8c80a42420c016a2bdbcf9ae Mon Sep 17 00:00:00 2001 From: Filippo Ferrario Date: Wed, 19 Jul 2023 16:24:59 +0200 Subject: [PATCH 7/8] Requested changes --- src/Files.App/Actions/Content/Tags/OpenAllTaggedActions.cs | 4 ++-- src/Files.App/Strings/en-US/Resources.resw | 4 ++-- src/Files.App/UserControls/Widgets/FileTagsWidget.xaml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Files.App/Actions/Content/Tags/OpenAllTaggedActions.cs b/src/Files.App/Actions/Content/Tags/OpenAllTaggedActions.cs index 3ae1f7dc8776..c29775b302fc 100644 --- a/src/Files.App/Actions/Content/Tags/OpenAllTaggedActions.cs +++ b/src/Files.App/Actions/Content/Tags/OpenAllTaggedActions.cs @@ -10,10 +10,10 @@ sealed class OpenAllTaggedActions: ObservableObject, IAction private readonly ITagsContext _tagsContext; public string Label - => "OpenAllItems".GetLocalizedResource(); + => "OpenAllTaggedItems".GetLocalizedResource(); public string Description - => "OpenAllItemsDescription".GetLocalizedResource(); + => "OpenAllTaggedItemsDescription".GetLocalizedResource(); public RichGlyph Glyph => new("\uE71D"); diff --git a/src/Files.App/Strings/en-US/Resources.resw b/src/Files.App/Strings/en-US/Resources.resw index fffe3db77330..fdbe0debfa82 100644 --- a/src/Files.App/Strings/en-US/Resources.resw +++ b/src/Files.App/Strings/en-US/Resources.resw @@ -3398,10 +3398,10 @@ Open directory in new window - + Open all - + Open all tagged items \ No newline at end of file diff --git a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml index bc1017e9848f..e70a3f5cbcea 100644 --- a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml +++ b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml @@ -85,9 +85,9 @@ + ToolTipService.ToolTip="{helpers:ResourceString Name=OpenAllTaggedItems}"> From 53c22bbb1a5153880feeb5c4a69f6202cf1198a0 Mon Sep 17 00:00:00 2001 From: Filippo Ferrario Date: Wed, 19 Jul 2023 16:54:51 +0200 Subject: [PATCH 8/8] Add MenuFlyout --- .../UserControls/Widgets/FileTagsWidget.xaml | 35 ++++++++++++++----- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml index e70a3f5cbcea..279c42a49f60 100644 --- a/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml +++ b/src/Files.App/UserControls/Widgets/FileTagsWidget.xaml @@ -81,17 +81,34 @@ - - +