Skip to content

Commit 2159b62

Browse files
authored
[Farewell, Interaction]: Step 2 of removing the Interaction class (#4189)
1 parent 924109f commit 2159b62

32 files changed

+1682
-1374
lines changed

Files/BaseLayout.cs

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using Files.Common;
22
using Files.DataModels;
3+
using Files.Dialogs;
4+
using Files.Enums;
35
using Files.EventArguments;
46
using Files.Extensions;
57
using Files.Filesystem;
@@ -8,6 +10,7 @@
810
using Files.UserControls;
911
using Files.ViewModels;
1012
using Files.Views;
13+
using Microsoft.Toolkit.Mvvm.Input;
1114
using Microsoft.Toolkit.Uwp;
1215
using Microsoft.Toolkit.Uwp.UI;
1316
using Newtonsoft.Json;
@@ -39,6 +42,8 @@ namespace Files
3942
/// </summary>
4043
public abstract class BaseLayout : Page, IBaseLayout, INotifyPropertyChanged
4144
{
45+
private readonly DispatcherTimer jumpTimer;
46+
4247
protected NamedPipeAsAppServiceConnection Connection => ParentShellPageInstance?.ServiceConnection;
4348

4449
public SelectedItemsPropertiesViewModel SelectedItemsPropertiesViewModel { get; }
@@ -85,6 +90,57 @@ internal set
8590
}
8691
}
8792

93+
private string jumpString = string.Empty;
94+
95+
public string JumpString
96+
{
97+
get => jumpString;
98+
set
99+
{
100+
// If current string is "a", and the next character typed is "a",
101+
// search for next file that starts with "a" (a.k.a. _jumpString = "a")
102+
if (jumpString.Length == 1 && value == jumpString + jumpString)
103+
{
104+
value = jumpString;
105+
}
106+
if (value != string.Empty)
107+
{
108+
ListedItem jumpedToItem = null;
109+
ListedItem previouslySelectedItem = null;
110+
111+
// Use FilesAndFolders because only displayed entries should be jumped to
112+
IEnumerable<ListedItem> candidateItems = ParentShellPageInstance.FilesystemViewModel.FilesAndFolders.Where(f => f.ItemName.Length >= value.Length && f.ItemName.Substring(0, value.Length).ToLower() == value);
113+
114+
if (IsItemSelected)
115+
{
116+
previouslySelectedItem = SelectedItem;
117+
}
118+
119+
// If the user is trying to cycle through items
120+
// starting with the same letter
121+
if (value.Length == 1 && previouslySelectedItem != null)
122+
{
123+
// Try to select item lexicographically bigger than the previous item
124+
jumpedToItem = candidateItems.FirstOrDefault(f => f.ItemName.CompareTo(previouslySelectedItem.ItemName) > 0);
125+
}
126+
if (jumpedToItem == null)
127+
{
128+
jumpedToItem = candidateItems.FirstOrDefault();
129+
}
130+
131+
if (jumpedToItem != null)
132+
{
133+
SetSelectedItemOnUi(jumpedToItem);
134+
ScrollIntoView(jumpedToItem);
135+
}
136+
137+
// Restart the timer
138+
jumpTimer.Start();
139+
}
140+
jumpString = value;
141+
}
142+
}
143+
88144
private List<ListedItem> selectedItems = new List<ListedItem>();
89145

90146
public List<ListedItem> SelectedItems
@@ -153,6 +209,10 @@ internal set
153209

154210
public BaseLayout()
155211
{
212+
jumpTimer = new DispatcherTimer();
213+
jumpTimer.Interval = TimeSpan.FromSeconds(0.8);
214+
jumpTimer.Tick += JumpTimer_Tick; ;
215+
156216
SelectedItemsPropertiesViewModel = new SelectedItemsPropertiesViewModel(this);
157217
DirectoryPropertiesViewModel = new DirectoryPropertiesViewModel();
158218

@@ -168,6 +228,12 @@ public BaseLayout()
168228
dragOverTimer = DispatcherQueue.GetForCurrentThread().CreateTimer();
169229
}
170230

231+
private void JumpTimer_Tick(object sender, object e)
232+
{
233+
jumpString = string.Empty;
234+
jumpTimer.Stop();
235+
}
236+
171237
protected abstract void InitializeCommandsViewModel();
172238

173239
public abstract void FocusFileList();
@@ -611,7 +677,7 @@ public void RightClickContextMenu_Opening(object sender, object e)
611677
Tag = "CreateNewFile"
612678
};
613679
}
614-
menuLayoutItem.Command = ParentShellPageInstance.InteractionOperations.CreateNewFile;
680+
menuLayoutItem.Command = new RelayCommand(() => UIFilesystemHelpers.CreateFileFromDialogResultType(AddItemType.File, null, ParentShellPageInstance));
615681
menuLayoutItem.CommandParameter = newEntry;
616682
newItemMenu.Items.Insert(separatorIndex + 1, menuLayoutItem);
617683
}
@@ -820,8 +886,8 @@ protected virtual void Page_CharacterReceived(CoreWindow sender, CharacterReceiv
820886
{
821887
if (ParentShellPageInstance.IsCurrentInstance)
822888
{
823-
char letterPressed = Convert.ToChar(args.KeyCode);
824-
ParentShellPageInstance.InteractionOperations.PushJumpChar(letterPressed);
889+
char letter = Convert.ToChar(args.KeyCode);
890+
JumpString += letter.ToString().ToLowerInvariant();
825891
}
826892
}
827893

@@ -888,7 +954,7 @@ protected async void List_Drop(object sender, DragEventArgs e)
888954

889955
if (e.DataView.Contains(StandardDataFormats.StorageItems))
890956
{
891-
await ParentShellPageInstance.InteractionOperations.FilesystemHelpers.PerformOperationTypeAsync(e.AcceptedOperation, e.DataView, ParentShellPageInstance.FilesystemViewModel.WorkingDirectory, true);
957+
await ParentShellPageInstance.FilesystemHelpers.PerformOperationTypeAsync(e.AcceptedOperation, e.DataView, ParentShellPageInstance.FilesystemViewModel.WorkingDirectory, true);
892958
e.Handled = true;
893959
}
894960

@@ -963,7 +1029,7 @@ protected async void Item_DragOver(object sender, DragEventArgs e)
9631029
{
9641030
dragOverItem = null;
9651031
dragOverTimer.Stop();
966-
ParentShellPageInstance.InteractionOperations.OpenSelectedItems(false);
1032+
NavigationHelpers.OpenSelectedItems(ParentShellPageInstance, false);
9671033
}
9681034
}, TimeSpan.FromMilliseconds(1000), false);
9691035
}

Files/Files.csproj

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,12 @@
211211
<Compile Include="Dialogs\ConfirmDeleteDialog.xaml.cs">
212212
<DependentUpon>ConfirmDeleteDialog.xaml</DependentUpon>
213213
</Compile>
214+
<Compile Include="Helpers\FilePropertiesHelpers.cs" />
215+
<Compile Include="Helpers\UIFilesystemHelpers.cs" />
216+
<Compile Include="Helpers\NavigationHelpers.cs" />
217+
<Compile Include="Helpers\UIHelpers.cs" />
218+
<Compile Include="Helpers\WallpaperHelpers.cs" />
219+
<Compile Include="Helpers\Win32Helpers.cs" />
214220
<Compile Include="UserControls\RestartControl.xaml.cs">
215221
<DependentUpon>RestartControl.xaml</DependentUpon>
216222
</Compile>
@@ -448,7 +454,6 @@
448454
<Compile Include="ViewModels\InteractionViewModel.cs" />
449455
<Compile Include="ViewModels\DirectoryPropertiesViewModel.cs" />
450456
<Compile Include="ViewModels\SelectedItemsPropertiesViewModel.cs" />
451-
<Compile Include="Interacts\Interaction.cs" />
452457
<Compile Include="IShellPage.cs" />
453458
<Compile Include="Views\LayoutModes\GridViewBrowser.xaml.cs">
454459
<DependentUpon>GridViewBrowser.xaml</DependentUpon>

Files/Filesystem/FilesystemOperations/FilesystemOperations.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ await DialogDisplayHelper.ShowDialogAsync(
183183
CloseButtonText = "ItemAlreadyExistsDialogCloseButtonText".GetLocalized()
184184
};
185185

186-
if (Interacts.Interaction.IsAnyContentDialogOpen())
186+
if (UIHelpers.IsAnyContentDialogOpen())
187187
{
188188
// Only a single ContentDialog can be open at any time.
189189
return null;
@@ -249,7 +249,7 @@ await DialogDisplayHelper.ShowDialogAsync(
249249
CloseButtonText = "ItemAlreadyExistsDialogCloseButtonText".GetLocalized()
250250
};
251251

252-
if (Interacts.Interaction.IsAnyContentDialogOpen())
252+
if (UIHelpers.IsAnyContentDialogOpen())
253253
{
254254
// Only a single ContentDialog can be open at any time.
255255
return null;
@@ -411,7 +411,7 @@ await DialogDisplayHelper.ShowDialogAsync(
411411
CloseButtonText = "ItemAlreadyExistsDialogCloseButtonText".GetLocalized()
412412
};
413413

414-
if (Interacts.Interaction.IsAnyContentDialogOpen())
414+
if (UIHelpers.IsAnyContentDialogOpen())
415415
{
416416
// Only a single ContentDialog can be open at any time.
417417
return null;
@@ -474,7 +474,7 @@ await DialogDisplayHelper.ShowDialogAsync(
474474
CloseButtonText = "ItemAlreadyExistsDialogCloseButtonText".GetLocalized()
475475
};
476476

477-
if (Interacts.Interaction.IsAnyContentDialogOpen())
477+
if (UIHelpers.IsAnyContentDialogOpen())
478478
{
479479
// Only a single ContentDialog can be open at any time.
480480
return null;
@@ -754,7 +754,7 @@ public async Task<IStorageHistory> RenameAsync(IStorageItemWithPath source,
754754
CloseButtonText = "ItemAlreadyExistsDialogCloseButtonText".GetLocalized()
755755
};
756756

757-
if (Interacts.Interaction.IsAnyContentDialogOpen())
757+
if (UIHelpers.IsAnyContentDialogOpen())
758758
{
759759
// Only a single ContentDialog can be open at any time.
760760
return null;

Files/Filesystem/FilesystemOperations/Helpers/FilesystemHelpers.cs

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
using System.Threading;
1515
using System.Threading.Tasks;
1616
using Windows.ApplicationModel.DataTransfer;
17+
using Windows.Foundation.Collections;
1718
using Windows.Storage;
1819
using static Files.Helpers.NativeFindStorageItemHelper;
1920
using FileAttributes = System.IO.FileAttributes;
@@ -119,7 +120,7 @@ public async Task<ReturnResult> DeleteItemsAsync(IEnumerable<IStorageItemWithPat
119120
!deleteFromRecycleBin ? permanently : deleteFromRecycleBin,
120121
associatedInstance.SlimContentPage.SelectedItems.Count);
121122

122-
if (Interacts.Interaction.IsAnyContentDialogOpen())
123+
if (UIHelpers.IsAnyContentDialogOpen())
123124
{
124125
// Can show only one dialog at a time
125126
banner.Remove();
@@ -223,7 +224,7 @@ public async Task<ReturnResult> DeleteItemAsync(IStorageItemWithPath source, boo
223224
permanently,
224225
associatedInstance.SlimContentPage.SelectedItems.Count);
225226

226-
if (Interacts.Interaction.IsAnyContentDialogOpen())
227+
if (UIHelpers.IsAnyContentDialogOpen())
227228
{
228229
// Can show only one dialog at a time
229230
banner.Remove();
@@ -301,7 +302,7 @@ public async Task<ReturnResult> DeleteItemAsync(IStorageItem source, bool showDi
301302
permanently,
302303
associatedInstance.SlimContentPage.SelectedItems.Count);
303304

304-
if (Interacts.Interaction.IsAnyContentDialogOpen())
305+
if (UIHelpers.IsAnyContentDialogOpen())
305306
{
306307
// Can show only one dialog at a time
307308
banner.Remove();
@@ -925,6 +926,20 @@ public static bool ContainsRestrictedFileName(string input)
925926
return false;
926927
}
927928

929+
public async Task OpenShellCommandInExplorerAsync(string shellCommand, NamedPipeAsAppServiceConnection serviceConnection)
930+
{
931+
Debug.WriteLine("Launching shell command in FullTrustProcess");
932+
if (serviceConnection != null)
933+
{
934+
ValueSet value = new ValueSet()
935+
{
936+
{ "ShellCommand", shellCommand },
937+
{ "Arguments", "ShellCommand" }
938+
};
939+
await serviceConnection.SendMessageAsync(value);
940+
}
941+
}
942+
928943
#endregion Public Helpers
929944

930945
#region IDisposable
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
using Files.Dialogs;
2+
using Files.Views;
3+
using Microsoft.Toolkit.Uwp;
4+
using System;
5+
using System.Linq;
6+
using System.Threading.Tasks;
7+
using Windows.ApplicationModel.Core;
8+
using Windows.Foundation;
9+
using Windows.Foundation.Metadata;
10+
using Windows.UI.Core;
11+
using Windows.UI.ViewManagement;
12+
using Windows.UI.Xaml;
13+
using Windows.UI.Xaml.Controls;
14+
using Windows.UI.Xaml.Media.Animation;
15+
using static Files.Views.Properties;
16+
17+
namespace Files.Helpers
18+
{
19+
public static class FilePropertiesHelpers
20+
{
21+
public static async void ShowProperties(IShellPage associatedInstance)
22+
{
23+
if (associatedInstance.SlimContentPage.IsItemSelected)
24+
{
25+
if (associatedInstance.SlimContentPage.SelectedItems.Count > 1)
26+
{
27+
await OpenPropertiesWindowAsync(associatedInstance.SlimContentPage.SelectedItems, associatedInstance);
28+
}
29+
else
30+
{
31+
await OpenPropertiesWindowAsync(associatedInstance.SlimContentPage.SelectedItem, associatedInstance);
32+
}
33+
}
34+
else
35+
{
36+
if (!System.IO.Path.GetPathRoot(associatedInstance.FilesystemViewModel.CurrentFolder.ItemPath)
37+
.Equals(associatedInstance.FilesystemViewModel.CurrentFolder.ItemPath, StringComparison.OrdinalIgnoreCase))
38+
{
39+
await OpenPropertiesWindowAsync(associatedInstance.FilesystemViewModel.CurrentFolder, associatedInstance);
40+
}
41+
else
42+
{
43+
await OpenPropertiesWindowAsync(App.DrivesManager.Drives
44+
.SingleOrDefault(x => x.Path.Equals(associatedInstance.FilesystemViewModel.CurrentFolder.ItemPath)), associatedInstance);
45+
}
46+
}
47+
}
48+
49+
public static async Task OpenPropertiesWindowAsync(object item, IShellPage associatedInstance)
50+
{
51+
if (item == null)
52+
{
53+
return;
54+
}
55+
56+
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
57+
{
58+
CoreApplicationView newWindow = CoreApplication.CreateNewView();
59+
ApplicationView newView = null;
60+
61+
await newWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
62+
{
63+
Frame frame = new Frame();
64+
frame.Navigate(typeof(Properties), new PropertiesPageNavigationArguments()
65+
{
66+
Item = item,
67+
AppInstanceArgument = associatedInstance
68+
}, new SuppressNavigationTransitionInfo());
69+
Window.Current.Content = frame;
70+
Window.Current.Activate();
71+
72+
newView = ApplicationView.GetForCurrentView();
73+
newWindow.TitleBar.ExtendViewIntoTitleBar = true;
74+
newView.Title = "PropertiesTitle".GetLocalized();
75+
newView.PersistedStateId = "Properties";
76+
newView.SetPreferredMinSize(new Size(400, 550));
77+
newView.Consolidated += delegate
78+
{
79+
Window.Current.Close();
80+
};
81+
});
82+
83+
bool viewShown = await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newView.Id);
84+
// Set window size again here as sometimes it's not resized in the page Loaded event
85+
newView.TryResizeView(new Size(400, 550));
86+
}
87+
else
88+
{
89+
var propertiesDialog = new PropertiesDialog();
90+
propertiesDialog.propertiesFrame.Tag = propertiesDialog;
91+
propertiesDialog.propertiesFrame.Navigate(typeof(Properties), new PropertiesPageNavigationArguments()
92+
{
93+
Item = item,
94+
AppInstanceArgument = associatedInstance
95+
}, new SuppressNavigationTransitionInfo());
96+
await propertiesDialog.ShowAsync(ContentDialogPlacement.Popup);
97+
}
98+
}
99+
}
100+
}

0 commit comments

Comments
 (0)