Skip to content

Commit cda8b99

Browse files
authored
Feature: Show the "send to" option in the main menu (#11329)
1 parent e7d00f3 commit cda8b99

File tree

8 files changed

+110
-15
lines changed

8 files changed

+110
-15
lines changed

src/Files.App/BaseLayout.cs

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -713,11 +713,12 @@ private void AddNewFileTagsToMenu(CommandBarFlyout contextMenu)
713713
private void AddShellItemsToMenu(List<ContextMenuFlyoutItemViewModel> shellMenuItems, CommandBarFlyout contextMenuFlyout, bool shiftPressed)
714714
{
715715
var openWithSubItems = ItemModelListToContextFlyoutHelper.GetMenuFlyoutItemsFromModel(ShellContextmenuHelper.GetOpenWithItems(shellMenuItems));
716+
var sendToSubItems = ItemModelListToContextFlyoutHelper.GetMenuFlyoutItemsFromModel(ShellContextmenuHelper.GetSendToItems(shellMenuItems));
716717
var mainShellMenuItems = shellMenuItems.RemoveFrom(!UserSettingsService.PreferencesSettingsService.MoveShellExtensionsToSubMenu ? int.MaxValue : shiftPressed ? 6 : 0);
717718
var overflowShellMenuItemsUnfiltered = shellMenuItems.Except(mainShellMenuItems).ToList();
718719
var overflowShellMenuItems = overflowShellMenuItemsUnfiltered.Where(
719-
(x, i) => (x.ItemType == ItemType.Separator &&
720-
overflowShellMenuItemsUnfiltered[i + 1 < overflowShellMenuItemsUnfiltered.Count ? i + 1 : i].ItemType == ItemType.Separator)
720+
(x, i) => (x.ItemType == ItemType.Separator &&
721+
overflowShellMenuItemsUnfiltered[i + 1 < overflowShellMenuItemsUnfiltered.Count ? i + 1 : i].ItemType != ItemType.Separator)
721722
|| x.ItemType != ItemType.Separator).ToList();
722723

723724
var overflowItems = ItemModelListToContextFlyoutHelper.GetMenuFlyoutItemsFromModel(overflowShellMenuItems);
@@ -800,6 +801,24 @@ private void AddShellItemsToMenu(List<ContextMenuFlyoutItemViewModel> shellMenuI
800801
openWithOverflow.Visibility = Visibility.Visible;
801802
}
802803

804+
// Add items to sendto dropdown
805+
var sendToOverflow = contextMenuFlyout.SecondaryCommands.FirstOrDefault(x => x is AppBarButton abb && (abb.Tag as string) == "SendToOverflow") as AppBarButton;
806+
807+
var sendTo = contextMenuFlyout.SecondaryCommands.FirstOrDefault(x => x is AppBarButton abb && (abb.Tag as string) == "SendTo") as AppBarButton;
808+
if (sendToSubItems is not null && sendToOverflow is not null)
809+
{
810+
var flyout = (MenuFlyout)sendToOverflow.Flyout;
811+
812+
flyout.Items.Clear();
813+
814+
foreach (var item in sendToSubItems)
815+
flyout.Items.Add(item);
816+
817+
sendToOverflow.Flyout = flyout;
818+
sendTo.Visibility = Visibility.Collapsed;
819+
sendToOverflow.Visibility = Visibility.Visible;
820+
}
821+
803822
if (itemsControl is not null)
804823
{
805824
itemsControl.Items.OfType<FrameworkElement>().ForEach(item =>

src/Files.App/Helpers/ContextFlyoutItemHelper.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,6 +1119,30 @@ public static List<ContextMenuFlyoutItemViewModel> GetBaseItemMenuItems(BaseLayo
11191119
},
11201120
},
11211121
new ContextMenuFlyoutItemViewModel()
1122+
{
1123+
Text = "SendTo".GetLocalizedResource(),
1124+
Tag = "SendTo",
1125+
CollapseLabel = true,
1126+
ShowInSearchPage = true,
1127+
ShowItem = true
1128+
},
1129+
new ContextMenuFlyoutItemViewModel()
1130+
{
1131+
Text = "SendTo".GetLocalizedResource(),
1132+
Tag = "SendToOverflow",
1133+
IsHidden = true,
1134+
CollapseLabel = true,
1135+
Items = new List<ContextMenuFlyoutItemViewModel>() {
1136+
new()
1137+
{
1138+
Text = "Placeholder",
1139+
ShowInSearchPage = true,
1140+
}
1141+
},
1142+
ShowInSearchPage = true,
1143+
ShowItem = true
1144+
},
1145+
new ContextMenuFlyoutItemViewModel()
11221146
{
11231147
ItemType = ItemType.Separator,
11241148
Tag = "OverflowSeparator",

src/Files.App/Helpers/ShellContextMenuHelper.cs

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
using Microsoft.UI.Xaml.Media.Imaging;
1717
using System;
1818
using System.Collections.Generic;
19+
using System.Diagnostics;
1920
using System.IO;
2021
using System.Linq;
2122
using System.Threading;
@@ -138,6 +139,9 @@ public static void LoadMenuFlyoutItem(IList<ContextMenuFlyoutItemViewModel> menu
138139
}
139140
else if (!string.IsNullOrEmpty(menuFlyoutItem.Label) && menuFlyoutItem.SubItems.Where(x => x.Type != MenuItemType.MFT_SEPARATOR).Any())
140141
{
142+
if (string.Equals(menuFlyoutItem.Label, Win32API.ExtractStringFromDLL("shell32.dll", 30312)))
143+
menuFlyoutItem.CommandString = "sendto";
144+
141145
var menuLayoutSubItem = new ContextMenuFlyoutItemViewModel()
142146
{
143147
Text = menuFlyoutItem.Label.Replace("&", "", StringComparison.Ordinal),
@@ -149,14 +153,14 @@ public static void LoadMenuFlyoutItem(IList<ContextMenuFlyoutItemViewModel> menu
149153
}
150154
else if (!string.IsNullOrEmpty(menuFlyoutItem.Label))
151155
{
152-
var menuLayoutItem = new ContextMenuFlyoutItemViewModel()
156+
var menuLayoutItem = new ContextMenuFlyoutItemViewModel
153157
{
154158
Text = menuFlyoutItem.Label.Replace("&", "", StringComparison.Ordinal),
155159
Tag = menuFlyoutItem,
156-
BitmapIcon = image
160+
BitmapIcon = image,
161+
Command = new RelayCommand<object>(x => InvokeShellMenuItem(contextMenu, x)),
162+
CommandParameter = menuFlyoutItem
157163
};
158-
menuLayoutItem.Command = new RelayCommand<object>(x => InvokeShellMenuItem(contextMenu, x));
159-
menuLayoutItem.CommandParameter = menuFlyoutItem;
160164
menuItemsListLocal.Insert(0, menuLayoutItem);
161165
}
162166
}
@@ -222,7 +226,20 @@ void InstallFont(string path, bool asAdmin)
222226
return item?.Items;
223227
}
224228

225-
public static async Task LoadShellMenuItems(string path, CommandBarFlyout itemContextMenuFlyout, ContextMenuOptions options = null, bool showOpenWithMenu = false)
229+
public static List<ContextMenuFlyoutItemViewModel>? GetSendToItems(List<ContextMenuFlyoutItemViewModel> flyout)
230+
{
231+
var item = flyout.FirstOrDefault(x => x.Tag is Win32ContextMenuItem { CommandString: "sendto" });
232+
if (item is not null)
233+
flyout.Remove(item);
234+
return item?.Items;
235+
}
236+
237+
public static async Task LoadShellMenuItems(
238+
string path,
239+
CommandBarFlyout itemContextMenuFlyout,
240+
ContextMenuOptions options = null,
241+
bool showOpenWithMenu = false,
242+
bool showSendToMenu = false)
226243
{
227244
try
228245
{
@@ -269,6 +286,20 @@ public static async Task LoadShellMenuItems(string path, CommandBarFlyout itemCo
269286
}
270287
}
271288

289+
if (showSendToMenu)
290+
{
291+
var sendToItem = shellMenuItems.Where(x => (x.Tag as Win32ContextMenuItem)?.CommandString == "sendto").ToList().FirstOrDefault();
292+
if (sendToItem is not null)
293+
{
294+
var (_, sendToItems) = ItemModelListToContextFlyoutHelper.GetAppBarItemsFromModel(new List<ContextMenuFlyoutItemViewModel>() { sendToItem });
295+
var placeholder = itemContextMenuFlyout.SecondaryCommands.Where(x => Equals((x as AppBarButton)?.Tag, "SendToPlaceholder")).FirstOrDefault() as AppBarButton;
296+
if (placeholder is not null)
297+
placeholder.Visibility = Visibility.Collapsed;
298+
itemContextMenuFlyout.SecondaryCommands.Insert(1, sendToItems.FirstOrDefault());
299+
shellMenuItems.Remove(sendToItem);
300+
}
301+
}
302+
272303
if (!UserSettingsService.PreferencesSettingsService.MoveShellExtensionsToSubMenu)
273304
{
274305
var (_, secondaryElements) = ItemModelListToContextFlyoutHelper.GetAppBarItemsFromModel(shellMenuItems);

src/Files.App/Strings/en-US/Resources.resw

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,9 @@
513513
<data name="BaseLayoutItemContextFlyoutOpenItemWith.Text" xml:space="preserve">
514514
<value>Open With</value>
515515
</data>
516+
<data name="SendTo" xml:space="preserve">
517+
<value>Send to</value>
518+
</data>
516519
<data name="FileNameTeachingTip.Subtitle" xml:space="preserve">
517520
<value>The item name must not contain the following characters: \ / : * ? " &lt; &gt; |</value>
518521
</data>

src/Files.App/UserControls/SidebarControl.xaml.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,8 +232,12 @@ private List<ContextMenuFlyoutItemViewModel> GetLocationItemMenuItems(INavigatio
232232
new ContextMenuFlyoutItemViewModel()
233233
{
234234
Text = "OpenInNewPane".GetLocalizedResource(),
235-
Glyph = "\uF117",
236-
GlyphFontFamilyName = "CustomGlyph",
235+
ColoredIcon = new ColoredIconModel()
236+
{
237+
BaseBackdropGlyph = "\uF056",
238+
BaseLayerGlyph = "\uF03B",
239+
OverlayLayerGlyph = "\uF03C",
240+
},
237241
Command = OpenInNewPaneCommand,
238242
ShowItem = options.IsLocationItem && userSettingsService.PreferencesSettingsService.ShowOpenInNewPane
239243
},

src/Files.App/UserControls/Widgets/DrivesWidget.xaml.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ public DrivesWidget()
136136
MapNetworkDriveCommand = new AsyncRelayCommand(DoNetworkMapDrive);
137137
DisconnectNetworkDriveCommand = new RelayCommand<DriveCardItem>(DisconnectNetworkDrive);
138138
}
139-
139+
140140
public override List<ContextMenuFlyoutItemViewModel> GetItemMenuItems(WidgetCardItem item, bool isPinned)
141141
{
142142
var options = (item.Item as DriveItem)?.MenuOptions;
@@ -163,8 +163,12 @@ public override List<ContextMenuFlyoutItemViewModel> GetItemMenuItems(WidgetCard
163163
new ContextMenuFlyoutItemViewModel()
164164
{
165165
Text = "OpenInNewPane".GetLocalizedResource(),
166-
Glyph = "\uF117",
167-
GlyphFontFamilyName = "CustomGlyph",
166+
ColoredIcon = new ColoredIconModel()
167+
{
168+
BaseBackdropGlyph = "\uF056",
169+
BaseLayerGlyph = "\uF03B",
170+
OverlayLayerGlyph = "\uF03C",
171+
},
168172
Command = OpenInNewPaneCommand,
169173
CommandParameter = item,
170174
ShowItem = userSettingsService.PreferencesSettingsService.ShowOpenInNewPane

src/Files.App/UserControls/Widgets/QuickAccessWidget.xaml.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,12 @@ public override List<ContextMenuFlyoutItemViewModel> GetItemMenuItems(WidgetCard
176176
new ContextMenuFlyoutItemViewModel()
177177
{
178178
Text = "OpenInNewPane".GetLocalizedResource(),
179-
Glyph = "\uF117",
180-
GlyphFontFamilyName = "CustomGlyph",
179+
ColoredIcon = new ColoredIconModel()
180+
{
181+
BaseBackdropGlyph = "\uF056",
182+
BaseLayerGlyph = "\uF03B",
183+
OverlayLayerGlyph = "\uF03C",
184+
},
181185
Command = OpenInNewPaneCommand,
182186
CommandParameter = item,
183187
ShowItem = userSettingsService.PreferencesSettingsService.ShowOpenInNewPane

src/Files.App/UserControls/Widgets/RecentFilesWidget.xaml.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ private void Grid_RightTapped(object sender, RightTappedRoutedEventArgs e)
117117
secondaryElements.ForEach(i => itemContextMenuFlyout.SecondaryCommands.Add(i));
118118
itemContextMenuFlyout.ShowAt(recentItemsGrid, new FlyoutShowOptions { Position = e.GetPosition(recentItemsGrid) });
119119

120-
_ = ShellContextmenuHelper.LoadShellMenuItems(item.Path, itemContextMenuFlyout, showOpenWithMenu: true);
120+
_ = ShellContextmenuHelper.LoadShellMenuItems(item.Path, itemContextMenuFlyout, showOpenWithMenu: true, showSendToMenu: true);
121121

122122
e.Handled = true;
123123
}
@@ -134,6 +134,12 @@ public override List<ContextMenuFlyoutItemViewModel> GetItemMenuItems(WidgetCard
134134
IsEnabled = false
135135
},
136136
new ContextMenuFlyoutItemViewModel()
137+
{
138+
Text = "SendTo".GetLocalizedResource(),
139+
Tag = "SendToPlaceholder",
140+
IsEnabled = false
141+
},
142+
new ContextMenuFlyoutItemViewModel()
137143
{
138144
Text = "RecentItemRemove/Text".GetLocalizedResource(),
139145
Glyph = "\uE738",

0 commit comments

Comments
 (0)