-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature: Option to open all items in a tag #11598
Changes from all commits
6024171
34ba7f9
47d8e5f
60dfa34
37843bc
618f2c6
ed1c241
8d4a84a
df2ec0f
ddb4d1c
5bb2683
029ecfb
15a3df1
a43899e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using CommunityToolkit.Mvvm.DependencyInjection; | ||
using Files.App.Commands; | ||
using Files.App.Contexts; | ||
using Files.App.Extensions; | ||
using Files.App.Helpers; | ||
using Files.Shared.Extensions; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
|
||
namespace Files.App.Actions.Content.Tags | ||
{ | ||
internal class OpenAllTaggedAction : IAction | ||
{ | ||
private readonly ITagsContext tagsContext = Ioc.Default.GetRequiredService<ITagsContext>(); | ||
|
||
private readonly IContentPageContext pageContext = Ioc.Default.GetRequiredService<IContentPageContext>(); | ||
|
||
public string Label => "OpenAllItems".GetLocalizedResource(); | ||
|
||
public RichGlyph Glyph { get; } = new("\uE8E5"); | ||
|
||
public async Task ExecuteAsync() | ||
{ | ||
if (pageContext.ShellPage is null) | ||
return; | ||
|
||
var files = tagsContext.TaggedItems.Where(taggedItem => !taggedItem.IsFolder); | ||
var folders = tagsContext.TaggedItems.Where(taggedItem => taggedItem.IsFolder); | ||
|
||
await Task.WhenAll(files.Select(file => NavigationHelpers.OpenPath(file.Path, pageContext.ShellPage))); | ||
folders.ForEach(async folder => await NavigationHelpers.OpenPathInNewTab(folder.Path)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -48,6 +48,8 @@ public interface ICommandManager : IEnumerable<IRichCommand> | |
|
||
IRichCommand RotateLeft { get; } | ||
IRichCommand RotateRight { get; } | ||
|
||
IRichCommand OpenAllTaggedItems { get; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Spacing looks off |
||
|
||
IRichCommand NewTab { get; } | ||
IRichCommand DuplicateTab { get; } | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using Files.App.ViewModels.Widgets; | ||
using System.Collections.Generic; | ||
|
||
namespace Files.App.Contexts | ||
{ | ||
public interface ITagsContext | ||
{ | ||
IEnumerable<FileTagsItemViewModel> TaggedItems { get; set; } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
using Files.App.ViewModels.Widgets; | ||
using System.Collections.Generic; | ||
using System.Collections.Immutable; | ||
using System.Linq; | ||
|
||
namespace Files.App.Contexts | ||
{ | ||
internal class TagsContext : ITagsContext | ||
{ | ||
private static readonly IReadOnlyList<FileTagsItemViewModel> emptyTaggedItemsList = Enumerable.Empty<FileTagsItemViewModel>().ToImmutableList(); | ||
|
||
private IEnumerable<FileTagsItemViewModel> taggedItems = emptyTaggedItemsList; | ||
public IEnumerable<FileTagsItemViewModel> TaggedItems | ||
{ | ||
get => taggedItems; | ||
set | ||
{ | ||
if (value is not null) | ||
taggedItems = value; | ||
else | ||
taggedItems = emptyTaggedItemsList; | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,16 @@ | ||
using CommunityToolkit.Mvvm.DependencyInjection; | ||
using CommunityToolkit.Mvvm.Input; | ||
using CommunityToolkit.WinUI.UI; | ||
using CommunityToolkit.WinUI.UI.Controls; | ||
using Files.App.Commands; | ||
using Files.App.Contexts; | ||
using Files.App.Extensions; | ||
using Files.App.Filesystem; | ||
using Files.App.Helpers; | ||
using Files.App.Helpers.ContextFlyouts; | ||
using Files.App.ViewModels; | ||
using Files.App.ViewModels.Widgets; | ||
using Files.App.Views; | ||
using Files.Backend.Services.Settings; | ||
using Files.Shared.Extensions; | ||
using Microsoft.UI.Input; | ||
using Microsoft.UI.Xaml; | ||
using Microsoft.UI.Xaml.Controls; | ||
using Microsoft.UI.Xaml.Controls.Primitives; | ||
|
@@ -22,8 +22,6 @@ | |
using System.Threading.Tasks; | ||
using System.Windows.Input; | ||
using Windows.Storage; | ||
using Windows.System; | ||
using Windows.UI.Core; | ||
|
||
// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 | ||
|
||
|
@@ -39,6 +37,10 @@ public FileTagsWidgetViewModel ViewModel | |
|
||
private readonly IUserSettingsService userSettingsService = Ioc.Default.GetRequiredService<IUserSettingsService>(); | ||
|
||
private readonly ICommandManager commands = Ioc.Default.GetRequiredService<ICommandManager>(); | ||
|
||
private readonly ITagsContext tagsContext = Ioc.Default.GetRequiredService<ITagsContext>(); | ||
|
||
public IShellPage AppInstance; | ||
public Func<string, Task>? OpenAction { get; set; } | ||
|
||
|
@@ -110,16 +112,50 @@ private async void FileTagItem_ItemClick(object sender, ItemClickEventArgs e) | |
await itemViewModel.ClickCommand.ExecuteAsync(null); | ||
} | ||
|
||
private async void Item_RightTapped(object sender, RightTappedRoutedEventArgs e) | ||
private void TagTitle_RightTapped(object sender, RightTappedRoutedEventArgs e) | ||
{ | ||
if (sender is not Grid grid || grid.Parent is not Grid parent) | ||
return; | ||
|
||
LoadContextMenuItem(parent, e, true); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would it be possible to create the menu in xaml? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, anyway I'll mark this as Draft and I'll change this once we have a final context, to avoid working twice |
||
} | ||
|
||
private void Item_RightTapped(object sender, RightTappedRoutedEventArgs e) | ||
{ | ||
App.Logger.Warn("rightTapped"); | ||
if (sender is not Grid tagsItemsGrid) | ||
return; | ||
|
||
LoadContextMenuItem(tagsItemsGrid, e); | ||
} | ||
|
||
private async void LoadContextMenuItem(Grid contextGrid, RightTappedRoutedEventArgs e, bool isWidgetMenu = false) | ||
{ | ||
List<ContextMenuFlyoutItemViewModel> menuItems; | ||
FileTagsItemViewModel? selectedItem = null; | ||
|
||
if (isWidgetMenu) | ||
{ | ||
if (contextGrid.Children[1] is not AdaptiveGridView gridView) | ||
return; | ||
|
||
var items = gridView.Items.Select(item => (FileTagsItemViewModel)item); | ||
|
||
tagsContext.TaggedItems = items; | ||
menuItems = GetWidgetMenuItems(); | ||
} | ||
else | ||
{ | ||
if (contextGrid.DataContext is not FileTagsItemViewModel item) | ||
return; | ||
|
||
selectedItem = item; | ||
menuItems = GetItemMenuItems(item, QuickAccessService.IsItemPinned(item.Path), item.IsFolder); | ||
} | ||
|
||
|
||
var itemContextMenuFlyout = new CommandBarFlyout { Placement = FlyoutPlacementMode.Full }; | ||
itemContextMenuFlyout.Opening += (sender, e) => App.LastOpenedFlyout = sender as CommandBarFlyout; | ||
if (sender is not StackPanel tagsItemsStackPanel || tagsItemsStackPanel.DataContext is not FileTagsItemViewModel item) | ||
return; | ||
|
||
App.Logger.Warn("Item path: " + item.Path + " widgetcarditem.path = " + (item as WidgetCardItem)?.Path); | ||
var menuItems = GetItemMenuItems(item, QuickAccessService.IsItemPinned(item.Path), item.IsFolder); | ||
var (_, secondaryElements) = ItemModelListToContextFlyoutHelper.GetAppBarItemsFromModel(menuItems); | ||
|
||
if (!UserSettingsService.PreferencesSettingsService.MoveShellExtensionsToSubMenu) | ||
|
@@ -128,9 +164,11 @@ private async void Item_RightTapped(object sender, RightTappedRoutedEventArgs e) | |
|
||
secondaryElements.ForEach(i => itemContextMenuFlyout.SecondaryCommands.Add(i)); | ||
ItemContextMenuFlyout = itemContextMenuFlyout; | ||
itemContextMenuFlyout.ShowAt(tagsItemsStackPanel, new FlyoutShowOptions { Position = e.GetPosition(tagsItemsStackPanel) }); | ||
itemContextMenuFlyout.ShowAt(contextGrid, new FlyoutShowOptions { Position = e.GetPosition(contextGrid) }); | ||
|
||
if (selectedItem is not null) | ||
await ShellContextmenuHelper.LoadShellMenuItems(selectedItem.Path, itemContextMenuFlyout, showOpenWithMenu: true, showSendToMenu: true); | ||
|
||
await ShellContextmenuHelper.LoadShellMenuItems(item.Path, itemContextMenuFlyout, showOpenWithMenu: true, showSendToMenu: true); | ||
e.Handled = true; | ||
} | ||
|
||
|
@@ -240,6 +278,14 @@ public override List<ContextMenuFlyoutItemViewModel> GetItemMenuItems(WidgetCard | |
}.Where(x => x.ShowItem).ToList(); | ||
} | ||
|
||
public List<ContextMenuFlyoutItemViewModel> GetWidgetMenuItems() | ||
{ | ||
return new List<ContextMenuFlyoutItemViewModel>() | ||
{ | ||
new ContextMenuFlyoutItemViewModelBuilder(commands.OpenAllTaggedItems).Build() | ||
}; | ||
} | ||
|
||
public void OpenFileLocation(WidgetCardItem? item) | ||
{ | ||
FileTagsOpenLocationInvoked?.Invoke(this, new PathNavigationEventArgs() | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which icon is this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a temp icon since
OpacityIcon
is not workingThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you try

?