Skip to content

Commit f211adc

Browse files
authored
Navigate to a directory when dragging items and hovering over a folder for a few seconds (#2166)
1 parent d460e8f commit f211adc

File tree

4 files changed

+112
-9
lines changed

4 files changed

+112
-9
lines changed

Files/BaseLayout.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using Files.View_Models;
88
using Files.Views;
99
using Files.Views.Pages;
10+
using Microsoft.Toolkit.Uwp.UI.Extensions;
1011
using Newtonsoft.Json;
1112
using System;
1213
using System.Collections.Generic;
@@ -636,13 +637,41 @@ protected async void Item_DragStarting(object sender, DragStartingEventArgs e)
636637
e.DragUI.SetContentFromDataPackage();
637638
}
638639

640+
private ListedItem dragOverItem = null;
641+
private DispatcherTimer dragOverTimer = new DispatcherTimer();
642+
643+
private void Item_DragLeave(object sender, DragEventArgs e)
644+
{
645+
ListedItem item = GetItemFromElement(sender);
646+
if (item == dragOverItem)
647+
{
648+
// Reset dragged over item
649+
dragOverItem = null;
650+
}
651+
}
652+
639653
protected async void Item_DragOver(object sender, DragEventArgs e)
640654
{
641655
var deferral = e.GetDeferral();
642656

643657
ListedItem item = GetItemFromElement(sender);
644658
SetSelectedItemOnUi(item);
645659

660+
if (dragOverItem != item)
661+
{
662+
dragOverItem = item;
663+
dragOverTimer.Stop();
664+
dragOverTimer.Debounce(() =>
665+
{
666+
if (dragOverItem != null)
667+
{
668+
dragOverItem = null;
669+
dragOverTimer.Stop();
670+
AssociatedInteractions.OpenItem_Click(null, null);
671+
}
672+
}, TimeSpan.FromMilliseconds(1000), false);
673+
}
674+
646675
if (e.DataView.Contains(StandardDataFormats.StorageItems))
647676
{
648677
e.Handled = true;
@@ -687,11 +716,13 @@ protected void InitializeDrag(UIElement element)
687716
element.DragStarting -= Item_DragStarting;
688717
element.DragStarting += Item_DragStarting;
689718
element.DragOver -= Item_DragOver;
719+
element.DragLeave -= Item_DragLeave;
690720
element.Drop -= Item_Drop;
691721
if (item.PrimaryItemAttribute == StorageItemTypes.Folder)
692722
{
693723
element.AllowDrop = true;
694724
element.DragOver += Item_DragOver;
725+
element.DragLeave += Item_DragLeave;
695726
element.Drop += Item_Drop;
696727
}
697728
}

Files/UserControls/ModernNavigationToolbar.xaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,7 @@
508508
AutomationProperties.Name="{Binding Title}"
509509
Background="Transparent"
510510
DragOver="PathBoxItem_DragOver"
511+
DragLeave="PathBoxItem_DragLeave"
511512
Drop="PathBoxItem_Drop"
512513
Tag="{Binding Path}">
513514

@@ -588,6 +589,7 @@
588589
AutomationProperties.Name="{Binding Title}"
589590
Background="Transparent"
590591
DragOver="PathBoxItem_DragOver"
592+
DragLeave="PathBoxItem_DragLeave"
591593
Drop="PathBoxItem_Drop"
592594
Tag="{Binding Path}">
593595
<Interactivity:Interaction.Behaviors>

Files/UserControls/ModernNavigationToolbar.xaml.cs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Files.Interacts;
66
using Files.View_Models;
77
using Files.Views.Pages;
8+
using Microsoft.Toolkit.Uwp.UI.Extensions;
89
using System;
910
using System.Collections.Generic;
1011
using System.Collections.ObjectModel;
@@ -405,6 +406,24 @@ private void VerticalTabs_PointerEntered(object sender, PointerRoutedEventArgs e
405406
}
406407
}
407408

409+
private string dragOverPath = null;
410+
private DispatcherTimer dragOverTimer = new DispatcherTimer();
411+
412+
private void PathBoxItem_DragLeave(object sender, DragEventArgs e)
413+
{
414+
if (!((sender as Grid).DataContext is PathBoxItem pathBoxItem) ||
415+
pathBoxItem.Path == "Home" || pathBoxItem.Path == ResourceController.GetTranslation("NewTab"))
416+
{
417+
return;
418+
}
419+
420+
if (pathBoxItem.Path == dragOverPath)
421+
{
422+
// Reset dragged over pathbox item
423+
dragOverPath = null;
424+
}
425+
}
426+
408427
private async void PathBoxItem_DragOver(object sender, DragEventArgs e)
409428
{
410429
if (!((sender as Grid).DataContext is PathBoxItem pathBoxItem) ||
@@ -413,6 +432,24 @@ private async void PathBoxItem_DragOver(object sender, DragEventArgs e)
413432
return;
414433
}
415434

435+
if (dragOverPath != pathBoxItem.Path)
436+
{
437+
dragOverPath = pathBoxItem.Path;
438+
dragOverTimer.Stop();
439+
if (dragOverPath != App.CurrentInstance.NavigationToolbar.PathComponents.LastOrDefault()?.Path)
440+
{
441+
dragOverTimer.Debounce(() =>
442+
{
443+
if (dragOverPath != null)
444+
{
445+
dragOverTimer.Stop();
446+
App.CurrentInstance.ContentFrame.Navigate(AppSettings.GetLayoutType(), dragOverPath); // navigate to folder
447+
dragOverPath = null;
448+
}
449+
}, TimeSpan.FromMilliseconds(1000), false);
450+
}
451+
}
452+
416453
if (!e.DataView.Contains(StandardDataFormats.StorageItems))
417454
{
418455
e.AcceptedOperation = DataPackageOperation.None;
@@ -428,13 +465,13 @@ private async void PathBoxItem_DragOver(object sender, DragEventArgs e)
428465
Trim(Path.DirectorySeparatorChar).
429466
Contains(Path.DirectorySeparatorChar)))
430467
{
431-
e.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.None;
468+
e.AcceptedOperation = DataPackageOperation.None;
432469
}
433470
else
434471
{
435472
e.DragUIOverride.IsCaptionVisible = true;
436473
e.DragUIOverride.Caption = string.Format(ResourceController.GetTranslation("MoveToFolderCaptionText"), pathBoxItem.Title);
437-
e.AcceptedOperation = Windows.ApplicationModel.DataTransfer.DataPackageOperation.Move;
474+
e.AcceptedOperation = DataPackageOperation.Move;
438475
}
439476

440477
deferral.Complete();

Files/UserControls/SidebarControl.xaml.cs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Files.Filesystem;
33
using Files.Interacts;
44
using Files.View_Models;
5+
using Microsoft.Toolkit.Uwp.UI.Extensions;
56
using System;
67
using System.ComponentModel;
78
using System.IO;
@@ -123,19 +124,24 @@ private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
123124

124125
private void Sidebar_ItemInvoked(Microsoft.UI.Xaml.Controls.NavigationView sender, Microsoft.UI.Xaml.Controls.NavigationViewItemInvokedEventArgs args)
125126
{
126-
string navigationPath; // path to navigate
127-
Type sourcePageType = null; // type of page to navigate
128-
129127
if (args.InvokedItem == null)
130128
{
131129
return;
132130
}
133131

134-
switch ((args.InvokedItemContainer.DataContext as INavigationControlItem).ItemType)
132+
OpenSidebarItem(args.InvokedItemContainer);
133+
}
134+
135+
private void OpenSidebarItem(Microsoft.UI.Xaml.Controls.NavigationViewItemBase invokedItemContainer)
136+
{
137+
string navigationPath; // path to navigate
138+
Type sourcePageType = null; // type of page to navigate
139+
140+
switch ((invokedItemContainer.DataContext as INavigationControlItem).ItemType)
135141
{
136142
case NavigationControlItemType.Location:
137143
{
138-
var ItemPath = (args.InvokedItemContainer.DataContext as INavigationControlItem).Path; // Get the path of the invoked item
144+
var ItemPath = (invokedItemContainer.DataContext as INavigationControlItem).Path; // Get the path of the invoked item
139145

140146
if (ItemPath.Equals("Home", StringComparison.OrdinalIgnoreCase)) // Home item
141147
{
@@ -146,7 +152,7 @@ private void Sidebar_ItemInvoked(Microsoft.UI.Xaml.Controls.NavigationView sende
146152
}
147153
else // Any other item
148154
{
149-
navigationPath = args.InvokedItemContainer.Tag.ToString();
155+
navigationPath = invokedItemContainer.Tag.ToString();
150156
}
151157

152158
break;
@@ -158,7 +164,7 @@ private void Sidebar_ItemInvoked(Microsoft.UI.Xaml.Controls.NavigationView sende
158164
}
159165
default:
160166
{
161-
navigationPath = args.InvokedItemContainer.Tag.ToString();
167+
navigationPath = invokedItemContainer.Tag.ToString();
162168
break;
163169
}
164170
}
@@ -255,14 +261,41 @@ private async void OpenInNewWindow_Click(object sender, RoutedEventArgs e)
255261
await Interaction.OpenPathInNewWindow(App.rightClickedItem.Path.ToString());
256262
}
257263

264+
private object dragOverItem = null;
265+
private DispatcherTimer dragOverTimer = new DispatcherTimer();
266+
258267
private void NavigationViewItem_DragEnter(object sender, DragEventArgs e)
259268
{
260269
VisualStateManager.GoToState(sender as Microsoft.UI.Xaml.Controls.NavigationViewItem, "DragEnter", false);
270+
271+
if ((sender as Microsoft.UI.Xaml.Controls.NavigationViewItem).DataContext is INavigationControlItem)
272+
{
273+
dragOverItem = sender;
274+
dragOverTimer.Stop();
275+
dragOverTimer.Debounce(() =>
276+
{
277+
if (dragOverItem != null)
278+
{
279+
dragOverTimer.Stop();
280+
OpenSidebarItem(dragOverItem as Microsoft.UI.Xaml.Controls.NavigationViewItem);
281+
dragOverItem = null;
282+
}
283+
}, TimeSpan.FromMilliseconds(1000), false);
284+
}
261285
}
262286

263287
private void NavigationViewItem_DragLeave(object sender, DragEventArgs e)
264288
{
265289
VisualStateManager.GoToState(sender as Microsoft.UI.Xaml.Controls.NavigationViewItem, "DragLeave", false);
290+
291+
if ((sender as Microsoft.UI.Xaml.Controls.NavigationViewItem).DataContext is INavigationControlItem)
292+
{
293+
if (sender == dragOverItem)
294+
{
295+
// Reset dragged over item
296+
dragOverItem = null;
297+
}
298+
}
266299
}
267300

268301
private async void NavigationViewLocationItem_DragOver(object sender, DragEventArgs e)

0 commit comments

Comments
 (0)