diff --git a/Files/BaseLayout.cs b/Files/BaseLayout.cs index ea05f26cc2df..003b187f7e58 100644 --- a/Files/BaseLayout.cs +++ b/Files/BaseLayout.cs @@ -5,6 +5,7 @@ using Files.Extensions; using Files.Filesystem; using Files.Helpers; +using Files.Interacts; using Files.UserControls; using Files.ViewModels; using Files.Views; @@ -37,9 +38,9 @@ namespace Files /// /// The base class which every layout page must derive from /// - public abstract class BaseLayout : Page, INotifyPropertyChanged + public abstract class BaseLayout : Page, IBaseLayout, INotifyPropertyChanged { - private NamedPipeAsAppServiceConnection Connection => ParentShellPageInstance?.ServiceConnection; + protected NamedPipeAsAppServiceConnection Connection => ParentShellPageInstance?.ServiceConnection; public SelectedItemsPropertiesViewModel SelectedItemsPropertiesViewModel { get; } @@ -59,6 +60,8 @@ public abstract class BaseLayout : Page, INotifyPropertyChanged public MenuFlyout BaseLayoutItemContextFlyout { get; set; } + public BaseLayoutCommandsViewModel CommandsViewModel { get; protected set; } + public IShellPage ParentShellPageInstance { get; private set; } = null; public bool IsRenamingItem { get; set; } = false; @@ -172,6 +175,8 @@ public BaseLayout() dragOverTimer = timerQueue.CreateTimer(); } + protected abstract void InitializeCommandsViewModel(); + public abstract void FocusFileList(); public abstract void SelectAllItems(); @@ -297,7 +302,7 @@ public virtual void SetItemOpacity(ListedItem item) private void FolderSettings_LayoutModeChangeRequested(object sender, LayoutModeEventArgs e) { - if (ParentShellPageInstance.ContentPage != null) + if (ParentShellPageInstance.SlimContentPage != null) { var layoutType = FolderSettings.GetLayoutType(ParentShellPageInstance.FilesystemViewModel.WorkingDirectory); @@ -334,6 +339,7 @@ protected override async void OnNavigatedTo(NavigationEventArgs eventArgs) Window.Current.CoreWindow.CharacterReceived += Page_CharacterReceived; navigationArguments = (NavigationArguments)eventArgs.Parameter; ParentShellPageInstance = navigationArguments.AssociatedTabInstance; + InitializeCommandsViewModel(); IsItemSelected = false; FolderSettings.LayoutModeChangeRequested += FolderSettings_LayoutModeChangeRequested; ParentShellPageInstance.FilesystemViewModel.IsFolderEmptyTextDisplayed = false; @@ -793,7 +799,7 @@ public void RightClickItemContextMenu_Opening(object sender, object e) } //check the file extension of the selected item - ParentShellPageInstance.ContentPage.SelectedItemsPropertiesViewModel.CheckFileExtension(); + SelectedItemsPropertiesViewModel.CheckFileExtension(); } protected virtual void Page_CharacterReceived(CoreWindow sender, CharacterReceivedEventArgs args) @@ -879,7 +885,7 @@ protected async void Item_DragStarting(object sender, DragStartingEventArgs e) { List selectedStorageItems = new List(); - foreach (ListedItem item in ParentShellPageInstance.ContentPage.SelectedItems) + foreach (ListedItem item in ParentShellPageInstance.SlimContentPage.SelectedItems) { if (item is ShortcutItem) { @@ -943,7 +949,7 @@ protected async void Item_DragOver(object sender, DragEventArgs e) { dragOverItem = null; dragOverTimer.Stop(); - ParentShellPageInstance.InteractionOperations.OpenItem_Click(null, null); + ParentShellPageInstance.InteractionOperations.OpenSelectedItems(false); } }, TimeSpan.FromMilliseconds(1000), false); } @@ -1002,7 +1008,7 @@ protected async void Item_Drop(object sender, DragEventArgs e) ListedItem rowItem = GetItemFromElement(sender); if (rowItem != null) { - await ParentShellPageInstance.InteractionOperations.FilesystemHelpers.PerformOperationTypeAsync(e.AcceptedOperation, e.DataView, (rowItem as ShortcutItem)?.TargetPath ?? rowItem.ItemPath, true); + await ParentShellPageInstance.FilesystemHelpers.PerformOperationTypeAsync(e.AcceptedOperation, e.DataView, (rowItem as ShortcutItem)?.TargetPath ?? rowItem.ItemPath, true); } deferral.Complete(); } @@ -1076,5 +1082,7 @@ public void BaseLayout_PointerWheelChanged(object sender, PointerRoutedEventArgs e.Handled = true; } } + + public abstract void Dispose(); } } diff --git a/Files/Dialogs/ConfirmDeleteDialog.xaml.cs b/Files/Dialogs/ConfirmDeleteDialog.xaml.cs index 6a19229182b0..6034493f390f 100644 --- a/Files/Dialogs/ConfirmDeleteDialog.xaml.cs +++ b/Files/Dialogs/ConfirmDeleteDialog.xaml.cs @@ -14,32 +14,29 @@ public enum DialogResult public sealed partial class ConfirmDeleteDialog : ContentDialog { - private SelectedItemsPropertiesViewModel SelectedItemsPropertiesViewModel { get; set; } = null; - public bool PermanentlyDelete { get; set; } public string Description { get; set; } public DialogResult Result { get; set; } - public ConfirmDeleteDialog(bool deleteFromRecycleBin, bool permanently, SelectedItemsPropertiesViewModel propertiesViewModel) + public ConfirmDeleteDialog(bool deleteFromRecycleBin, bool permanently, int itemsSelected) { this.InitializeComponent(); Result = DialogResult.Nothing; //clear the result in case the value is set from last time PermanentlyDelete = permanently; - SelectedItemsPropertiesViewModel = propertiesViewModel; // If deleting from recycle bin disable "permanently delete" option chkPermanentlyDelete.IsEnabled = !deleteFromRecycleBin; - if (SelectedItemsPropertiesViewModel.SelectedItemsCount == 1) + if (itemsSelected == 1) { Description = "ConfirmDeleteDialogDeleteOneItem/Text".GetLocalized(); } else { - Description = string.Format("ConfirmDeleteDialogDeleteMultipleItems/Text".GetLocalized(), SelectedItemsPropertiesViewModel.SelectedItemsCount); + Description = string.Format("ConfirmDeleteDialogDeleteMultipleItems/Text".GetLocalized(), itemsSelected); } } diff --git a/Files/Extensions/EnumExtensions.cs b/Files/Extensions/EnumExtensions.cs new file mode 100644 index 000000000000..cc5f9d2f5766 --- /dev/null +++ b/Files/Extensions/EnumExtensions.cs @@ -0,0 +1,17 @@ +using System; +using System.Reflection; + +namespace Files.Extensions +{ + public static class EnumExtensions + { + public static TEnum GetEnum(string text) where TEnum : struct + { + if (!typeof(TEnum).GetTypeInfo().IsEnum) + { + throw new InvalidOperationException("Generic parameter 'TEnum' must be an enum."); + } + return (TEnum)Enum.Parse(typeof(TEnum), text); + } + } +} diff --git a/Files/Files.csproj b/Files/Files.csproj index b3fc7c54c030..6f606bdf1833 100644 --- a/Files/Files.csproj +++ b/Files/Files.csproj @@ -184,6 +184,7 @@ + @@ -228,9 +229,15 @@ + + + + + + BasicPreview.xaml diff --git a/Files/Filesystem/FilesystemOperations/FilesystemOperations.cs b/Files/Filesystem/FilesystemOperations/FilesystemOperations.cs index 85bf1cd86234..05d5298d758b 100644 --- a/Files/Filesystem/FilesystemOperations/FilesystemOperations.cs +++ b/Files/Filesystem/FilesystemOperations/FilesystemOperations.cs @@ -294,8 +294,8 @@ await DialogDisplayHelper.ShowDialogAsync( if (copiedListedItems.Count > 0) { - associatedInstance.ContentPage.AddSelectedItemsOnUi(copiedListedItems); - associatedInstance.ContentPage.FocusSelectedItems(); + associatedInstance.SlimContentPage.AddSelectedItemsOnUi(copiedListedItems); + associatedInstance.SlimContentPage.FocusSelectedItems(); } }, Windows.UI.Core.CoreDispatcherPriority.Low); } @@ -515,8 +515,8 @@ await DialogDisplayHelper.ShowDialogAsync( if (movedListedItems.Count > 0) { - associatedInstance.ContentPage.AddSelectedItemsOnUi(movedListedItems); - associatedInstance.ContentPage.FocusSelectedItems(); + associatedInstance.SlimContentPage.AddSelectedItemsOnUi(movedListedItems); + associatedInstance.SlimContentPage.FocusSelectedItems(); } }, Windows.UI.Core.CoreDispatcherPriority.Low); } diff --git a/Files/Filesystem/FilesystemOperations/Helpers/FilesystemHelpers.cs b/Files/Filesystem/FilesystemOperations/Helpers/FilesystemHelpers.cs index 48062e4e2cce..f55f80a768fe 100644 --- a/Files/Filesystem/FilesystemOperations/Helpers/FilesystemHelpers.cs +++ b/Files/Filesystem/FilesystemOperations/Helpers/FilesystemHelpers.cs @@ -117,7 +117,7 @@ public async Task DeleteItemsAsync(IEnumerable DeleteItemAsync(IStorageItemWithPath source, boo ConfirmDeleteDialog dialog = new ConfirmDeleteDialog( deleteFromRecycleBin, permanently, - associatedInstance.ContentPage.SelectedItemsPropertiesViewModel); + associatedInstance.SlimContentPage.SelectedItems.Count); if (Interacts.Interaction.IsAnyContentDialogOpen()) { @@ -299,7 +299,7 @@ public async Task DeleteItemAsync(IStorageItem source, bool showDi ConfirmDeleteDialog dialog = new ConfirmDeleteDialog( deleteFromRecycleBin, permanently, - associatedInstance.ContentPage.SelectedItemsPropertiesViewModel); + associatedInstance.SlimContentPage.SelectedItems.Count); if (Interacts.Interaction.IsAnyContentDialogOpen()) { @@ -424,7 +424,7 @@ public async Task CopyItemsAsync(IEnumerable IStorageHistory history; List rawStorageHistory = new List(); - associatedInstance.ContentPage.ClearSelection(); + associatedInstance.SlimContentPage.ClearSelection(); float progress; for (int i = 0; i < source.Count(); i++) { @@ -483,7 +483,7 @@ public async Task CopyItemAsync(IStorageItemWithPath source, strin var sw = new Stopwatch(); sw.Start(); - associatedInstance.ContentPage.ClearSelection(); + associatedInstance.SlimContentPage.ClearSelection(); IStorageHistory history = await filesystemOperations.CopyAsync(source, destination, banner.Progress, banner.ErrorCode, cancellationToken); ((IProgress)banner.Progress).Report(100.0f); @@ -596,7 +596,7 @@ public async Task MoveItemsAsync(IEnumerable IStorageHistory history; var rawStorageHistory = new List(); - associatedInstance.ContentPage.ClearSelection(); + associatedInstance.SlimContentPage.ClearSelection(); float progress; for (int i = 0; i < source.Count(); i++) { @@ -655,7 +655,7 @@ public async Task MoveItemAsync(IStorageItemWithPath source, strin var sw = new Stopwatch(); sw.Start(); - associatedInstance.ContentPage.ClearSelection(); + associatedInstance.SlimContentPage.ClearSelection(); IStorageHistory history = await filesystemOperations.MoveAsync(source, destination, banner.Progress, banner.ErrorCode, cancellationToken); ((IProgress)banner.Progress).Report(100.0f); diff --git a/Files/Helpers/QuickLookHelpers.cs b/Files/Helpers/QuickLookHelpers.cs new file mode 100644 index 000000000000..b131bec93705 --- /dev/null +++ b/Files/Helpers/QuickLookHelpers.cs @@ -0,0 +1,43 @@ +using System; +using Microsoft.Toolkit.Uwp; +using System.Diagnostics; +using System.IO; +using System.Threading.Tasks; +using Windows.ApplicationModel.Core; +using Windows.Foundation.Collections; +using Windows.UI.Core; + +namespace Files.Helpers +{ + public static class QuickLookHelpers + { + public static async void ToggleQuickLook(IShellPage associatedInstance) + { + try + { + if (associatedInstance.SlimContentPage.IsItemSelected && !associatedInstance.SlimContentPage.IsRenamingItem) + { + Debug.WriteLine("Toggle QuickLook"); + if (associatedInstance.ServiceConnection != null) + { + await associatedInstance.ServiceConnection.SendMessageAsync(new ValueSet() + { + { "path", associatedInstance.SlimContentPage.SelectedItem.ItemPath }, + { "Arguments", "ToggleQuickLook" } + }); + } + } + } + catch (FileNotFoundException) + { + await DialogDisplayHelper.ShowDialogAsync("FileNotFoundDialog/Title".GetLocalized(), "FileNotFoundPreviewDialog/Text".GetLocalized()); + associatedInstance.NavigationToolbar.CanRefresh = false; + await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => + { + var ContentOwnedViewModelInstance = associatedInstance.FilesystemViewModel; + ContentOwnedViewModelInstance?.RefreshItems(null); + }); + } + } + } +} diff --git a/Files/Helpers/RecycleBinHelpers.cs b/Files/Helpers/RecycleBinHelpers.cs index 6209d40eddce..d0ba69803c38 100644 --- a/Files/Helpers/RecycleBinHelpers.cs +++ b/Files/Helpers/RecycleBinHelpers.cs @@ -1,4 +1,5 @@ using Files.Common; +using Microsoft.Toolkit.Uwp; using Newtonsoft.Json; using System; using System.Collections.Generic; @@ -8,6 +9,7 @@ using Windows.ApplicationModel.AppService; using Windows.Foundation.Collections; using Windows.Storage; +using Windows.UI.Xaml.Controls; namespace Files.Helpers { @@ -80,6 +82,36 @@ public bool IsPathUnderRecycleBin(string path) return recycleBinPathRegex.IsMatch(path); } + public static void EmptyRecycleBin(IShellPage associatedInstance) + { + new RecycleBinHelpers(associatedInstance).EmptyRecycleBin(); + } + + public async void EmptyRecycleBin() + { + var ConfirmEmptyBinDialog = new ContentDialog() + { + Title = "ConfirmEmptyBinDialogTitle".GetLocalized(), + Content = "ConfirmEmptyBinDialogContent".GetLocalized(), + PrimaryButtonText = "ConfirmEmptyBinDialog/PrimaryButtonText".GetLocalized(), + SecondaryButtonText = "ConfirmEmptyBinDialog/SecondaryButtonText".GetLocalized() + }; + + ContentDialogResult result = await ConfirmEmptyBinDialog.ShowAsync(); + + if (result == ContentDialogResult.Primary) + { + if (Connection != null) + { + var value = new ValueSet(); + value.Add("Arguments", "RecycleBin"); + value.Add("action", "Empty"); + // Send request to fulltrust process to empty recyclebin + await Connection.SendMessageAsync(value); + } + } + } + #region IDisposable public void Dispose() diff --git a/Files/Helpers/SidebarHelpers.cs b/Files/Helpers/SidebarHelpers.cs new file mode 100644 index 000000000000..1e2a547b3d5c --- /dev/null +++ b/Files/Helpers/SidebarHelpers.cs @@ -0,0 +1,24 @@ +using Files.Filesystem; +using System.Collections.Generic; + +namespace Files.Helpers +{ + public static class SidebarHelpers + { + public static void UnpinItems(List itemsToUnpin) + { + foreach (var item in itemsToUnpin) + { + App.SidebarPinnedController.Model.RemoveItem(item.ItemPath); + } + } + + public static void PinItems(List itemsToPin) + { + foreach (ListedItem listedItem in itemsToPin) + { + App.SidebarPinnedController.Model.AddItem(listedItem.ItemPath); + } + } + } +} diff --git a/Files/Helpers/ThemeHelper.cs b/Files/Helpers/ThemeHelper.cs index b80b865e2b32..3a309938a09b 100644 --- a/Files/Helpers/ThemeHelper.cs +++ b/Files/Helpers/ThemeHelper.cs @@ -1,4 +1,5 @@ -using System; +using Files.Extensions; +using System; using Windows.Storage; using Windows.UI; using Windows.UI.ViewManagement; @@ -29,7 +30,7 @@ public static ElementTheme RootTheme if (!string.IsNullOrEmpty(savedTheme)) { - return Interacts.Interaction.GetEnum(savedTheme); + return EnumExtensions.GetEnum(savedTheme); } else { diff --git a/Files/IBaseLayout.cs b/Files/IBaseLayout.cs new file mode 100644 index 000000000000..5f29a3ba42d0 --- /dev/null +++ b/Files/IBaseLayout.cs @@ -0,0 +1,44 @@ +using Files.Filesystem; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Files +{ + public interface IBaseLayout : IDisposable + { + bool IsRenamingItem { get; } + + bool IsItemSelected { get; } + + public List SelectedItems { get; } + + public ListedItem SelectedItem { get; } + + void SetItemOpacity(ListedItem item); // TODO: Add opactiy value here + + void ResetItemOpacity(); + + void ClearSelection(); + + void SelectAllItems(); + + void InvertSelection(); + + void SetDragModeForItems(); + + void ScrollIntoView(ListedItem item); + + void SetSelectedItemOnUi(ListedItem item); + + void SetSelectedItemsOnUi(List selectedItems); + + void AddSelectedItemsOnUi(List selectedItems); + + void FocusSelectedItems(); + + void StartRenameItem(); + } +} diff --git a/Files/IShellPage.cs b/Files/IShellPage.cs index 019370938395..dce497359eea 100644 --- a/Files/IShellPage.cs +++ b/Files/IShellPage.cs @@ -13,26 +13,36 @@ namespace Files public interface IShellPage : ITabItemContent, IMultiPaneInfo, IDisposable { IStatusCenterActions StatusCenterActions { get; } - public Interaction InteractionOperations { get; } - public ItemViewModel FilesystemViewModel { get; } - public CurrentInstanceViewModel InstanceViewModel { get; } - public NamedPipeAsAppServiceConnection ServiceConnection { get; } - public BaseLayout ContentPage { get; } - public Type CurrentPageType { get; } - public IFilesystemHelpers FilesystemHelpers { get; } - public INavigationToolbar NavigationToolbar { get; } - public bool CanNavigateBackward { get; } - public bool CanNavigateForward { get; } - public abstract void Refresh_Click(); + Interaction InteractionOperations { get; } - public void UpdatePathUIToWorkingDirectory(string newWorkingDir, string singleItemOverride = null); + ItemViewModel FilesystemViewModel { get; } - public void NavigateToPath(string navigationPath, Type sourcePageType, NavigationArguments navArgs = null); + CurrentInstanceViewModel InstanceViewModel { get; } - public void NavigateWithArguments(Type sourcePageType, NavigationArguments navArgs); + NamedPipeAsAppServiceConnection ServiceConnection { get; } - public void RemoveLastPageFromBackStack(); + IBaseLayout SlimContentPage { get; } + + Type CurrentPageType { get; } + + IFilesystemHelpers FilesystemHelpers { get; } + + INavigationToolbar NavigationToolbar { get; } + + bool CanNavigateBackward { get; } + + bool CanNavigateForward { get; } + + void Refresh_Click(); + + void UpdatePathUIToWorkingDirectory(string newWorkingDir, string singleItemOverride = null); + + void NavigateToPath(string navigationPath, Type sourcePageType, NavigationArguments navArgs = null); + + void NavigateWithArguments(Type sourcePageType, NavigationArguments navArgs); + + void RemoveLastPageFromBackStack(); } public interface IPaneHolder : IDisposable diff --git a/Files/Interacts/BaseLayoutCommandImplementationModel.cs b/Files/Interacts/BaseLayoutCommandImplementationModel.cs new file mode 100644 index 000000000000..6e3f487446dc --- /dev/null +++ b/Files/Interacts/BaseLayoutCommandImplementationModel.cs @@ -0,0 +1,149 @@ +using Files.Enums; +using Files.Filesystem; +using Files.Helpers; +using Microsoft.Toolkit.Uwp; +using Windows.Foundation.Collections; +using Windows.UI.Xaml; +using System; + +namespace Files.Interacts +{ + /// + /// This class provides default implementation for BaseLayout commands. + /// This class can be also inherited from and functions overridden to provide custom functionality + /// + public class BaseLayoutCommandImplementationModel : IBaseLayoutCommandImplementationModel + { + #region Singleton + + private NamedPipeAsAppServiceConnection ServiceConnection => associatedInstance?.ServiceConnection; + + private IBaseLayout SlimContentPage => associatedInstance?.SlimContentPage; + + #endregion + + #region Private Members + + private readonly IShellPage associatedInstance; + + #endregion + + #region Constructor + + public BaseLayoutCommandImplementationModel(IShellPage associatedInstance) + { + this.associatedInstance = associatedInstance; + } + + #endregion + + #region IDisposable + + public void Dispose() + { + //associatedInstance = null; + } + + #endregion + + #region Command Implementation + + public virtual void RenameItem(RoutedEventArgs e) + { + associatedInstance.SlimContentPage.StartRenameItem(); + } + + public virtual async void CreateShortcut(RoutedEventArgs e) + { + foreach (ListedItem selectedItem in SlimContentPage.SelectedItems) + { + if (ServiceConnection != null) + { + var value = new ValueSet() + { + { "Arguments", "FileOperation" }, + { "fileop", "CreateLink" }, + { "targetpath", selectedItem.ItemPath }, + { "arguments", "" }, + { "workingdir", "" }, + { "runasadmin", false }, + { + "filepath", + System.IO.Path.Combine(associatedInstance.FilesystemViewModel.WorkingDirectory, + string.Format("ShortcutCreateNewSuffix".GetLocalized(), selectedItem.ItemName) + ".lnk") + } + }; + await ServiceConnection.SendMessageAsync(value); + } + } + } + + public virtual void SetAsLockscreenBackgroundItem(RoutedEventArgs e) + { + associatedInstance.InteractionOperations.SetAsBackground(WallpaperType.LockScreen, SlimContentPage.SelectedItem.ItemPath); + } + + public virtual void SetAsDesktopBackgroundItem(RoutedEventArgs e) + { + associatedInstance.InteractionOperations.SetAsBackground(WallpaperType.Desktop, SlimContentPage.SelectedItem.ItemPath); + } + + public virtual async void RunAsAdmin(RoutedEventArgs e) + { + if (ServiceConnection != null) + { + await ServiceConnection.SendMessageAsync(new ValueSet() + { + { "Arguments", "InvokeVerb" }, + { "FilePath", SlimContentPage.SelectedItem.ItemPath }, + { "Verb", "runas" } + }); + } + } + + public virtual async void RunAsAnotherUser(RoutedEventArgs e) + { + if (ServiceConnection != null) + { + await ServiceConnection.SendMessageAsync(new ValueSet() + { + { "Arguments", "InvokeVerb" }, + { "FilePath", SlimContentPage.SelectedItem.ItemPath }, + { "Verb", "runasuser" } + }); + } + } + + public virtual void SidebarPinItem(RoutedEventArgs e) + { + SidebarHelpers.PinItems(SlimContentPage.SelectedItems); + } + + public virtual void SidebarUnpinItem(RoutedEventArgs e) + { + SidebarHelpers.UnpinItems(SlimContentPage.SelectedItems); + } + + public virtual void OpenItem(RoutedEventArgs e) + { + associatedInstance.InteractionOperations.OpenSelectedItems(false); + } + + public virtual void UnpinDirectoryFromSidebar(RoutedEventArgs e) + { + App.SidebarPinnedController.Model.RemoveItem(associatedInstance.FilesystemViewModel.WorkingDirectory); + } + + public virtual void EmptyRecycleBin(RoutedEventArgs e) + { + RecycleBinHelpers.EmptyRecycleBin(associatedInstance); + } + + public virtual void QuickLook(RoutedEventArgs e) + { + QuickLookHelpers.ToggleQuickLook(associatedInstance); + } + + #endregion + } +} diff --git a/Files/Interacts/BaseLayoutCommandsViewModel.cs b/Files/Interacts/BaseLayoutCommandsViewModel.cs new file mode 100644 index 000000000000..115f749f9d36 --- /dev/null +++ b/Files/Interacts/BaseLayoutCommandsViewModel.cs @@ -0,0 +1,86 @@ +using Microsoft.Toolkit.Mvvm.Input; +using System; +using System.Windows.Input; +using Windows.UI.Xaml; + +namespace Files.Interacts +{ + public class BaseLayoutCommandsViewModel : IDisposable + { + #region Private Members + + private readonly IBaseLayoutCommandImplementationModel commandsModel; + + #endregion + + #region Constructor + + public BaseLayoutCommandsViewModel(IBaseLayoutCommandImplementationModel commandsModel) + { + this.commandsModel = commandsModel; + + InitializeCommands(); + } + + #endregion + + #region Command Initialization + + private void InitializeCommands() + { + RenameItemCommand = new RelayCommand(commandsModel.RenameItem); + CreateShortcutCommand = new RelayCommand(commandsModel.CreateShortcut); + SetAsLockscreenBackgroundItemCommand = new RelayCommand(commandsModel.SetAsLockscreenBackgroundItem); + SetAsDesktopBackgroundItemCommand = new RelayCommand(commandsModel.SetAsDesktopBackgroundItem); + RunAsAdminCommand = new RelayCommand(commandsModel.RunAsAdmin); + RunAsAnotherUserCommand = new RelayCommand(commandsModel.RunAsAnotherUser); + SidebarPinItemCommand = new RelayCommand(commandsModel.SidebarPinItem); + SidebarUnpinItemCommand = new RelayCommand(commandsModel.SidebarUnpinItem); + UnpinDirectoryFromSidebarCommand = new RelayCommand(commandsModel.UnpinDirectoryFromSidebar); + OpenItemCommand = new RelayCommand(commandsModel.OpenItem); + EmptyRecycleBinCommand = new RelayCommand(commandsModel.EmptyRecycleBin); + QuickLookCommand = new RelayCommand(commandsModel.QuickLook); + } + + #endregion + + #region Commands + + // TODO: We'll have there all BaseLayout commands to bind to -> and these will call implementation in commandsModel + + public ICommand RenameItemCommand { get; private set; } + + public ICommand CreateShortcutCommand { get; private set; } + + public ICommand SetAsLockscreenBackgroundItemCommand { get; private set; } + + public ICommand SetAsDesktopBackgroundItemCommand { get; private set; } + + public ICommand RunAsAdminCommand { get; private set; } + + public ICommand RunAsAnotherUserCommand { get; private set; } + + public ICommand SidebarPinItemCommand { get; private set; } + + public ICommand SidebarUnpinItemCommand { get; private set; } + + public ICommand OpenItemCommand { get; private set; } + + public ICommand UnpinDirectoryFromSidebarCommand { get; private set; } + + public ICommand EmptyRecycleBinCommand { get; private set; } + + public ICommand QuickLookCommand { get; private set; } + + #endregion + + #region IDisposable + + public void Dispose() + { + commandsModel?.Dispose(); + } + + #endregion + } +} diff --git a/Files/Interacts/IBaseLayoutCommandImplementationModel.cs b/Files/Interacts/IBaseLayoutCommandImplementationModel.cs new file mode 100644 index 000000000000..e1f0eb2df1c7 --- /dev/null +++ b/Files/Interacts/IBaseLayoutCommandImplementationModel.cs @@ -0,0 +1,32 @@ +using System; +using Windows.UI.Xaml; + +namespace Files.Interacts +{ + public interface IBaseLayoutCommandImplementationModel : IDisposable + { + void RenameItem(RoutedEventArgs e); + + void CreateShortcut(RoutedEventArgs e); + + void SetAsLockscreenBackgroundItem(RoutedEventArgs e); + + void SetAsDesktopBackgroundItem(RoutedEventArgs e); + + void RunAsAdmin(RoutedEventArgs e); + + void RunAsAnotherUser(RoutedEventArgs e); + + void SidebarPinItem(RoutedEventArgs e); + + void SidebarUnpinItem(RoutedEventArgs e); + + void UnpinDirectoryFromSidebar(RoutedEventArgs e); + + void OpenItem(RoutedEventArgs e); + + void EmptyRecycleBin(RoutedEventArgs e); + + void QuickLook(RoutedEventArgs e); + } +} diff --git a/Files/Interacts/Interaction.cs b/Files/Interacts/Interaction.cs index 3e70ce698cbf..871e977bfa52 100644 --- a/Files/Interacts/Interaction.cs +++ b/Files/Interacts/Interaction.cs @@ -83,9 +83,9 @@ public string JumpString // use FilesAndFolders because only displayed entries should be jumped to var candidateItems = AssociatedInstance.FilesystemViewModel.FilesAndFolders.Where(f => f.ItemName.Length >= value.Length && f.ItemName.Substring(0, value.Length).ToLower() == value); - if (AssociatedInstance.ContentPage != null && AssociatedInstance.ContentPage.IsItemSelected) + if (AssociatedInstance.SlimContentPage != null && AssociatedInstance.SlimContentPage.IsItemSelected) { - previouslySelectedItem = AssociatedInstance.ContentPage.SelectedItem; + previouslySelectedItem = AssociatedInstance.SlimContentPage.SelectedItem; } // If the user is trying to cycle through items @@ -102,8 +102,8 @@ public string JumpString if (jumpedToItem != null) { - AssociatedInstance.ContentPage.SetSelectedItemOnUi(jumpedToItem); - AssociatedInstance.ContentPage.ScrollIntoView(jumpedToItem); + AssociatedInstance.SlimContentPage.SetSelectedItemOnUi(jumpedToItem); + AssociatedInstance.SlimContentPage.ScrollIntoView(jumpedToItem); } // Restart the timer @@ -113,16 +113,6 @@ public string JumpString } } - public void SetAsDesktopBackgroundItem_Click(object sender, RoutedEventArgs e) - { - SetAsBackground(WallpaperType.Desktop, ((sender as MenuFlyoutItem).DataContext as ListedItem).ItemPath); - } - - public void SetAsLockscreenBackgroundItem_Click(object sender, RoutedEventArgs e) - { - SetAsBackground(WallpaperType.LockScreen, ((sender as MenuFlyoutItem).DataContext as ListedItem).ItemPath); - } - public async void SetAsBackground(WallpaperType type, string filePath) { if (UserProfilePersonalizationSettings.IsSupported()) @@ -170,7 +160,7 @@ private async void OpenNewTab() public async void OpenInNewWindowItem_Click() { - var items = AssociatedInstance.ContentPage.SelectedItems; + var items = AssociatedInstance.SlimContentPage.SelectedItems; foreach (ListedItem listedItem in items) { var selectedItemPath = (listedItem as ShortcutItem)?.TargetPath ?? listedItem.ItemPath; @@ -181,7 +171,7 @@ public async void OpenInNewWindowItem_Click() public void OpenDirectoryInNewPane_Click() { - var listedItem = AssociatedInstance.ContentPage.SelectedItems.FirstOrDefault(); + var listedItem = AssociatedInstance.SlimContentPage.SelectedItems.FirstOrDefault(); if (listedItem != null) { AssociatedInstance.PaneHolder?.OpenPathInNewPane((listedItem as ShortcutItem)?.TargetPath ?? listedItem.ItemPath); @@ -197,7 +187,7 @@ public void OpenNewPaneCommand() public async void OpenDirectoryInNewTab_Click() { - foreach (ListedItem listedItem in AssociatedInstance.ContentPage.SelectedItems) + foreach (ListedItem listedItem in AssociatedInstance.SlimContentPage.SelectedItems) { await CoreWindow.GetForCurrentThread().Dispatcher.RunAsync(CoreDispatcherPriority.Low, async () => { @@ -260,28 +250,6 @@ private async void OpenDirectoryInTerminal(string workingDir) } } - public void PinItem_Click(object sender, RoutedEventArgs e) - { - if (AssociatedInstance.ContentPage != null) - { - foreach (ListedItem listedItem in AssociatedInstance.ContentPage.SelectedItems) - { - App.SidebarPinnedController.Model.AddItem(listedItem.ItemPath); - } - } - } - - public void UnpinItem_Click(object sender, RoutedEventArgs e) - { - if (AssociatedInstance.ContentPage != null) - { - foreach (ListedItem listedItem in AssociatedInstance.ContentPage.SelectedItems) - { - App.SidebarPinnedController.Model.RemoveItem(listedItem.ItemPath); - } - } - } - public async Task InvokeWin32ComponentAsync(string applicationPath, string arguments = null, bool runAsAdmin = false, string workingDir = null) { await InvokeWin32ComponentsAsync(new List() { applicationPath }, arguments, runAsAdmin, workingDir); @@ -335,46 +303,6 @@ public static bool IsAnyContentDialogOpen() return openedPopups.Any(popup => popup.Child is ContentDialog); } - public static TEnum GetEnum(string text) where TEnum : struct - { - if (!typeof(TEnum).GetTypeInfo().IsEnum) - { - throw new InvalidOperationException("Generic parameter 'TEnum' must be an enum."); - } - return (TEnum)Enum.Parse(typeof(TEnum), text); - } - - public async void RunAsAdmin_Click() - { - if (Connection != null) - { - await Connection.SendMessageAsync(new ValueSet() - { - { "Arguments", "InvokeVerb" }, - { "FilePath", AssociatedInstance.ContentPage.SelectedItem.ItemPath }, - { "Verb", "runas" } - }); - } - } - - public async void RunAsAnotherUser_Click() - { - if (Connection != null) - { - await Connection.SendMessageAsync(new ValueSet() - { - { "Arguments", "InvokeVerb" }, - { "FilePath", AssociatedInstance.ContentPage.SelectedItem.ItemPath }, - { "Verb", "runasuser" } - }); - } - } - - public void OpenItem_Click(object sender, RoutedEventArgs e) - { - OpenSelectedItems(false); - } - public void OpenItemWithApplicationPicker_Click(object sender, RoutedEventArgs e) { OpenSelectedItems(true); @@ -681,11 +609,11 @@ public async void OpenSelectedItems(bool openViaApplicationPicker = false) // Do not open files and folders inside the recycle bin return; } - if (AssociatedInstance.ContentPage == null) + if (AssociatedInstance.SlimContentPage == null) { return; } - foreach (ListedItem item in AssociatedInstance.ContentPage.SelectedItems) + foreach (ListedItem item in AssociatedInstance.SlimContentPage.SelectedItems) { var type = item.PrimaryItemAttribute == StorageItemTypes.Folder ? FilesystemItemType.Directory : FilesystemItemType.File; @@ -710,15 +638,15 @@ public void ShareItem_Click(object sender, RoutedEventArgs e) private async void ShowProperties() { - if (AssociatedInstance.ContentPage.IsItemSelected) + if (AssociatedInstance.SlimContentPage.IsItemSelected) { - if (AssociatedInstance.ContentPage.SelectedItems.Count > 1) + if (AssociatedInstance.SlimContentPage.SelectedItems.Count > 1) { - await OpenPropertiesWindowAsync(AssociatedInstance.ContentPage.SelectedItems); + await OpenPropertiesWindowAsync(AssociatedInstance.SlimContentPage.SelectedItems); } else { - await OpenPropertiesWindowAsync(AssociatedInstance.ContentPage.SelectedItem); + await OpenPropertiesWindowAsync(AssociatedInstance.SlimContentPage.SelectedItem); } } else @@ -801,11 +729,6 @@ public void PinDirectoryToSidebar(object sender, RoutedEventArgs e) App.SidebarPinnedController.Model.AddItem(AssociatedInstance.FilesystemViewModel.WorkingDirectory); } - public void UnpinDirectoryFromSidebar(object sender, RoutedEventArgs e) - { - App.SidebarPinnedController.Model.RemoveItem(AssociatedInstance.FilesystemViewModel.WorkingDirectory); - } - private async void Manager_DataRequested(DataTransferManager sender, DataRequestedEventArgs args) { DataRequestDeferral dataRequestDeferral = args.Request.GetDeferral(); @@ -815,7 +738,7 @@ private async void Manager_DataRequested(DataTransferManager sender, DataRequest /*dataRequest.Data.Properties.Title = "Data Shared From Files"; dataRequest.Data.Properties.Description = "The items you selected will be shared";*/ - foreach (ListedItem item in AssociatedInstance.ContentPage.SelectedItems) + foreach (ListedItem item in AssociatedInstance.SlimContentPage.SelectedItems) { if (item.IsShortcutItem) { @@ -866,48 +789,15 @@ private async void Manager_DataRequested(DataTransferManager sender, DataRequest dataRequestDeferral.Complete(); } - public async void CreateShortcutFromItem_Click(object sender, RoutedEventArgs e) - { - foreach (ListedItem selectedItem in AssociatedInstance.ContentPage.SelectedItems) - { - if (Connection != null) - { - var value = new ValueSet - { - { "Arguments", "FileOperation" }, - { "fileop", "CreateLink" }, - { "targetpath", selectedItem.ItemPath }, - { "arguments", "" }, - { "workingdir", "" }, - { "runasadmin", false }, - { - "filepath", - Path.Combine(AssociatedInstance.FilesystemViewModel.WorkingDirectory, - string.Format("ShortcutCreateNewSuffix".GetLocalized(), selectedItem.ItemName) + ".lnk") - } - }; - await Connection.SendMessageAsync(value); - } - } - } - public async void DeleteItem_Click(object sender, RoutedEventArgs e) { await FilesystemHelpers.DeleteItemsAsync( - AssociatedInstance.ContentPage.SelectedItems.Select((item) => StorageItemHelpers.FromPathAndType( + AssociatedInstance.SlimContentPage.SelectedItems.Select((item) => StorageItemHelpers.FromPathAndType( item.ItemPath, item.PrimaryItemAttribute == StorageItemTypes.File ? FilesystemItemType.File : FilesystemItemType.Directory)).ToList(), true, false, true); } - public void RenameItem_Click(object sender, RoutedEventArgs e) - { - if (AssociatedInstance.ContentPage.IsItemSelected) - { - AssociatedInstance.ContentPage.StartRenameItem(); - } - } - public async Task RenameFileItemAsync(ListedItem item, string oldName, string newName) { if (oldName == newName) @@ -949,14 +839,14 @@ public async Task RenameFileItemAsync(ListedItem item, string oldName, str public void SetHiddenAttributeItem(ListedItem item, bool isHidden) { item.IsHiddenItem = isHidden; - AssociatedInstance.ContentPage.ResetItemOpacity(); + AssociatedInstance.SlimContentPage.ResetItemOpacity(); } public async void RestoreItem_Click(object sender, RoutedEventArgs e) { - if (AssociatedInstance.ContentPage.IsItemSelected) + if (AssociatedInstance.SlimContentPage.IsItemSelected) { - foreach (ListedItem listedItem in AssociatedInstance.ContentPage.SelectedItems) + foreach (ListedItem listedItem in AssociatedInstance.SlimContentPage.SelectedItems) { if (listedItem is RecycleBinItem binItem) { @@ -977,15 +867,15 @@ public async void CutItem_Click(object sender, RoutedEventArgs e) }; List items = new List(); var cut = (FilesystemResult)false; - if (AssociatedInstance.ContentPage.IsItemSelected) + if (AssociatedInstance.SlimContentPage.IsItemSelected) { // First, reset DataGrid Rows that may be in "cut" command mode - AssociatedInstance.ContentPage.ResetItemOpacity(); + AssociatedInstance.SlimContentPage.ResetItemOpacity(); - foreach (ListedItem listedItem in AssociatedInstance.ContentPage.SelectedItems) + foreach (ListedItem listedItem in AssociatedInstance.SlimContentPage.SelectedItems) { // Dim opacities accordingly - AssociatedInstance.ContentPage.SetItemOpacity(listedItem); + AssociatedInstance.SlimContentPage.SetItemOpacity(listedItem); if (listedItem.PrimaryItemAttribute == StorageItemTypes.File) { @@ -1008,7 +898,7 @@ public async void CutItem_Click(object sender, RoutedEventArgs e) } if (cut.ErrorCode == FileSystemStatusCode.NotFound) { - AssociatedInstance.ContentPage.ResetItemOpacity(); + AssociatedInstance.SlimContentPage.ResetItemOpacity(); return; } else if (cut.ErrorCode == FileSystemStatusCode.Unauthorized) @@ -1016,7 +906,7 @@ public async void CutItem_Click(object sender, RoutedEventArgs e) // Try again with fulltrust process if (Connection != null) { - var filePaths = string.Join('|', AssociatedInstance.ContentPage.SelectedItems.Select(x => x.ItemPath)); + var filePaths = string.Join('|', AssociatedInstance.SlimContentPage.SelectedItems.Select(x => x.ItemPath)); var status = await Connection.SendMessageAsync(new ValueSet() { { "Arguments", "FileOperation" }, @@ -1029,7 +919,7 @@ public async void CutItem_Click(object sender, RoutedEventArgs e) return; } } - AssociatedInstance.ContentPage.ResetItemOpacity(); + AssociatedInstance.SlimContentPage.ResetItemOpacity(); return; } } @@ -1062,9 +952,9 @@ public async void CopyItem_ClickAsync(object sender, RoutedEventArgs e) CopySourcePath = AssociatedInstance.FilesystemViewModel.WorkingDirectory; var copied = (FilesystemResult)false; - if (AssociatedInstance.ContentPage.IsItemSelected) + if (AssociatedInstance.SlimContentPage.IsItemSelected) { - foreach (ListedItem listedItem in AssociatedInstance.ContentPage.SelectedItems) + foreach (ListedItem listedItem in AssociatedInstance.SlimContentPage.SelectedItems) { if (listedItem.PrimaryItemAttribute == StorageItemTypes.File) { @@ -1090,7 +980,7 @@ public async void CopyItem_ClickAsync(object sender, RoutedEventArgs e) // Try again with fulltrust process if (Connection != null) { - var filePaths = string.Join('|', AssociatedInstance.ContentPage.SelectedItems.Select(x => x.ItemPath)); + var filePaths = string.Join('|', AssociatedInstance.SlimContentPage.SelectedItems.Select(x => x.ItemPath)); await Connection.SendMessageAsync(new ValueSet() { { "Arguments", "FileOperation" }, @@ -1124,10 +1014,10 @@ private void CopyLocation() { try { - if (AssociatedInstance.ContentPage != null) + if (AssociatedInstance.SlimContentPage != null) { DataPackage data = new DataPackage(); - data.SetText(AssociatedInstance.ContentPage.SelectedItem.ItemPath); + data.SetText(AssociatedInstance.SlimContentPage.SelectedItem.ItemPath); Clipboard.SetContent(data); Clipboard.Flush(); } @@ -1143,7 +1033,7 @@ private void CopyWorkingLocation() { try { - if (AssociatedInstance.ContentPage != null) + if (AssociatedInstance.SlimContentPage != null) { DataPackage data = new DataPackage(); data.SetText(AssociatedInstance.FilesystemViewModel.WorkingDirectory); @@ -1156,39 +1046,6 @@ private void CopyWorkingLocation() } } - private enum ImpossibleActionResponseTypes - { - Skip, - Abort - } - - public RelayCommand EmptyRecycleBin => new RelayCommand(() => EmptyRecycleBin_ClickAsync()); - - public async void EmptyRecycleBin_ClickAsync() - { - var ConfirmEmptyBinDialog = new ContentDialog() - { - Title = "ConfirmEmptyBinDialogTitle".GetLocalized(), - Content = "ConfirmEmptyBinDialogContent".GetLocalized(), - PrimaryButtonText = "ConfirmEmptyBinDialog/PrimaryButtonText".GetLocalized(), - SecondaryButtonText = "ConfirmEmptyBinDialog/SecondaryButtonText".GetLocalized() - }; - - ContentDialogResult result = await ConfirmEmptyBinDialog.ShowAsync(); - - if (result == ContentDialogResult.Primary) - { - if (Connection != null) - { - var value = new ValueSet(); - value.Add("Arguments", "RecycleBin"); - value.Add("action", "Empty"); - // Send request to fulltrust process to empty recyclebin - await Connection.SendMessageAsync(value); - } - } - } - public RelayCommand PasteItemsFromClipboard => new RelayCommand(async () => await PasteItemAsync(AssociatedInstance.FilesystemViewModel.WorkingDirectory)); public async Task PasteItemAsync(string destinationPath) @@ -1197,14 +1054,14 @@ public async Task PasteItemAsync(string destinationPath) if (packageView != null) { await FilesystemHelpers.PerformOperationTypeAsync(packageView.RequestedOperation, packageView, destinationPath, true); - AssociatedInstance.ContentPage.ResetItemOpacity(); + AssociatedInstance.SlimContentPage.ResetItemOpacity(); } } public async void CreateFileFromDialogResultType(AddItemType itemType, ShellNewEntry itemInfo) { string currentPath = null; - if (AssociatedInstance.ContentPage != null) + if (AssociatedInstance.SlimContentPage != null) { currentPath = AssociatedInstance.FilesystemViewModel.WorkingDirectory; } @@ -1266,48 +1123,17 @@ private void NewFile(ShellNewEntry itemType) CreateFileFromDialogResultType(AddItemType.File, itemType); } - public RelayCommand SelectAllContentPageItems => new RelayCommand(() => SelectAllItems(AssociatedInstance.ContentPage)); - - public void SelectAllItems(BaseLayout contentPage) => contentPage.SelectAllItems(); + public RelayCommand SelectAllContentPageItems => new RelayCommand(() => SelectAllItems(AssociatedInstance.SlimContentPage)); - public RelayCommand InvertContentPageSelction => new RelayCommand(() => InvertAllItems(AssociatedInstance.ContentPage)); + public void SelectAllItems(IBaseLayout contentPage) => contentPage.SelectAllItems(); - public void InvertAllItems(BaseLayout contentPage) => contentPage.InvertSelection(); + public RelayCommand InvertContentPageSelction => new RelayCommand(() => InvertAllItems(AssociatedInstance.SlimContentPage)); - public RelayCommand ClearContentPageSelection => new RelayCommand(() => ClearAllItems(AssociatedInstance.ContentPage)); + public void InvertAllItems(IBaseLayout contentPage) => contentPage.InvertSelection(); - public void ClearAllItems(BaseLayout contentPage) => contentPage.ClearSelection(); - - public async void ToggleQuickLook() - { - try - { - if (AssociatedInstance.ContentPage.IsItemSelected && !AssociatedInstance.ContentPage.IsRenamingItem) - { - var clickedOnItem = AssociatedInstance.ContentPage.SelectedItem; + public RelayCommand ClearContentPageSelection => new RelayCommand(() => ClearAllItems(AssociatedInstance.SlimContentPage)); - Logger.Info("Toggle QuickLook"); - Debug.WriteLine("Toggle QuickLook"); - if (Connection != null) - { - var value = new ValueSet(); - value.Add("path", clickedOnItem.ItemPath); - value.Add("Arguments", "ToggleQuickLook"); - await Connection.SendMessageAsync(value); - } - } - } - catch (FileNotFoundException) - { - await DialogDisplayHelper.ShowDialogAsync("FileNotFoundDialog/Title".GetLocalized(), "FileNotFoundPreviewDialog/Text".GetLocalized()); - AssociatedInstance.NavigationToolbar.CanRefresh = false; - await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => - { - var ContentOwnedViewModelInstance = AssociatedInstance.FilesystemViewModel; - ContentOwnedViewModelInstance?.RefreshItems(null); - }); - } - } + public void ClearAllItems(IBaseLayout contentPage) => contentPage.ClearSelection(); public void PushJumpChar(char letter) { @@ -1319,60 +1145,5 @@ private void JumpTimer_Tick(object sender, object e) jumpString = ""; jumpTimer.Stop(); } - - public async Task GetHashForFileAsync(ListedItem fileItem, string nameOfAlg, CancellationToken token, Microsoft.UI.Xaml.Controls.ProgressBar progress) - { - HashAlgorithmProvider algorithmProvider = HashAlgorithmProvider.OpenAlgorithm(nameOfAlg); - StorageFile file = await StorageItemHelpers.ToStorageItem((fileItem as ShortcutItem)?.TargetPath ?? fileItem.ItemPath, AssociatedInstance); - if (file == null) - { - return ""; - } - - Stream stream = await FilesystemTasks.Wrap(() => file.OpenStreamForReadAsync()); - if (stream == null) - { - return ""; - } - - var inputStream = stream.AsInputStream(); - var str = inputStream.AsStreamForRead(); - var cap = (long)(0.5 * str.Length) / 100; - uint capacity; - if (cap >= uint.MaxValue) - { - capacity = uint.MaxValue; - } - else - { - capacity = Convert.ToUInt32(cap); - } - - Windows.Storage.Streams.Buffer buffer = new Windows.Storage.Streams.Buffer(capacity); - var hash = algorithmProvider.CreateHash(); - while (!token.IsCancellationRequested) - { - await inputStream.ReadAsync(buffer, capacity, InputStreamOptions.None); - if (buffer.Length > 0) - { - hash.Append(buffer); - } - else - { - break; - } - if (progress != null) - { - progress.Value = (double)str.Position / str.Length * 100; - } - } - inputStream.Dispose(); - stream.Dispose(); - if (token.IsCancellationRequested) - { - return ""; - } - return CryptographicBuffer.EncodeToHexString(hash.GetValueAndReset()).ToLower(); - } } } \ No newline at end of file diff --git a/Files/ViewModels/Properties/FileProperties.cs b/Files/ViewModels/Properties/FileProperties.cs index 605b7788e5ef..31f9b8fc285f 100644 --- a/Files/ViewModels/Properties/FileProperties.cs +++ b/Files/ViewModels/Properties/FileProperties.cs @@ -15,9 +15,11 @@ using System.Threading.Tasks; using Windows.Devices.Geolocation; using Windows.Foundation.Collections; +using Windows.Security.Cryptography; using Windows.Security.Cryptography.Core; using Windows.Services.Maps; using Windows.Storage; +using Windows.Storage.Streams; using Windows.UI.Core; using Windows.UI.Xaml; @@ -144,8 +146,7 @@ public override async void GetSpecialProperties() ViewModel.ItemMD5HashVisibility = Visibility.Visible; try { - ViewModel.ItemMD5Hash = await AppInstance.InteractionOperations - .GetHashForFileAsync(Item, hashAlgTypeName, TokenSource.Token, ProgressBar); + ViewModel.ItemMD5Hash = await GetHashForFileAsync(Item, hashAlgTypeName, TokenSource.Token, ProgressBar, AppInstance); } catch (Exception ex) { @@ -337,5 +338,60 @@ private async void ViewModel_PropertyChanged(object sender, System.ComponentMode break; } } + + private async Task GetHashForFileAsync(ListedItem fileItem, string nameOfAlg, CancellationToken token, ProgressBar progress, IShellPage associatedInstance) + { + HashAlgorithmProvider algorithmProvider = HashAlgorithmProvider.OpenAlgorithm(nameOfAlg); + StorageFile file = await StorageItemHelpers.ToStorageItem((fileItem as ShortcutItem)?.TargetPath ?? fileItem.ItemPath, associatedInstance); + if (file == null) + { + return ""; + } + + Stream stream = await FilesystemTasks.Wrap(() => file.OpenStreamForReadAsync()); + if (stream == null) + { + return ""; + } + + var inputStream = stream.AsInputStream(); + var str = inputStream.AsStreamForRead(); + var cap = (long)(0.5 * str.Length) / 100; + uint capacity; + if (cap >= uint.MaxValue) + { + capacity = uint.MaxValue; + } + else + { + capacity = Convert.ToUInt32(cap); + } + + Windows.Storage.Streams.Buffer buffer = new Windows.Storage.Streams.Buffer(capacity); + var hash = algorithmProvider.CreateHash(); + while (!token.IsCancellationRequested) + { + await inputStream.ReadAsync(buffer, capacity, InputStreamOptions.None); + if (buffer.Length > 0) + { + hash.Append(buffer); + } + else + { + break; + } + if (progress != null) + { + progress.Value = (double)str.Position / str.Length * 100; + } + } + inputStream.Dispose(); + stream.Dispose(); + if (token.IsCancellationRequested) + { + return ""; + } + return CryptographicBuffer.EncodeToHexString(hash.GetValueAndReset()).ToLower(); + } } } \ No newline at end of file diff --git a/Files/ViewModels/Properties/PropertiesTab.cs b/Files/ViewModels/Properties/PropertiesTab.cs index a2cff04b81e3..cc9fc75d0e00 100644 --- a/Files/ViewModels/Properties/PropertiesTab.cs +++ b/Files/ViewModels/Properties/PropertiesTab.cs @@ -30,7 +30,7 @@ protected override void OnNavigatedTo(NavigationEventArgs e) var np = e.Parameter as Views.Properties.PropertyNavParam; AppInstance = np.AppInstanceArgument; - ViewModel = new SelectedItemsPropertiesViewModel(AppInstance.ContentPage); + ViewModel = new SelectedItemsPropertiesViewModel(AppInstance.SlimContentPage); if (np.navParameter is ListedItem) { diff --git a/Files/ViewModels/SelectedItemsPropertiesViewModel.cs b/Files/ViewModels/SelectedItemsPropertiesViewModel.cs index d073710a1f06..225d4834f1f4 100644 --- a/Files/ViewModels/SelectedItemsPropertiesViewModel.cs +++ b/Files/ViewModels/SelectedItemsPropertiesViewModel.cs @@ -507,11 +507,11 @@ public bool IsItemSelected set => SetProperty(ref isItemSelected, value); } - private BaseLayout contentPage = null; + private IBaseLayout contentPage; - public SelectedItemsPropertiesViewModel(BaseLayout contentPageParam) + public SelectedItemsPropertiesViewModel(IBaseLayout contentPage) { - contentPage = contentPageParam; + this.contentPage = contentPage; } private bool isSelectedItemImage = false; diff --git a/Files/Views/LayoutModes/GenericFileBrowser.xaml b/Files/Views/LayoutModes/GenericFileBrowser.xaml index 221df5bb7028..91521b8e0780 100644 --- a/Files/Views/LayoutModes/GenericFileBrowser.xaml +++ b/Files/Views/LayoutModes/GenericFileBrowser.xaml @@ -15,6 +15,8 @@ xmlns:local3="using:Files.Filesystem.Cloud" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:muxc="using:Microsoft.UI.Xaml.Controls" + xmlns:i="using:Microsoft.Xaml.Interactivity" + xmlns:icore="using:Microsoft.Xaml.Interactions.Core" xmlns:xh="using:Files.Helpers.XamlHelpers" xmlns:usercontrols="using:Files.UserControls" NavigationCacheMode="Enabled" @@ -237,8 +239,12 @@ x:Name="UnpinDirectoryFromSidebar" x:Uid="BaseLayoutContextFlyoutUnpinDirectoryFromSidebar" x:Load="False" - Click="{x:Bind ParentShellPageInstance.InteractionOperations.UnpinDirectoryFromSidebar}" Text="Unpin directory from sidebar"> + + + + + @@ -343,9 +349,13 @@ + + + + + @@ -361,9 +371,13 @@ x:Name="OpenItem" x:Uid="BaseLayoutItemContextFlyoutOpenItem" x:Load="False" - Click="{x:Bind ParentShellPageInstance.InteractionOperations.OpenItem_Click}" Tag="Open_FlyoutItem" Text="Open"> + + + + + @@ -428,8 +442,12 @@ + + + + + @@ -437,8 +455,12 @@ + + + + + @@ -449,8 +471,12 @@ x:Name="RunAsAdmin" x:Uid="BaseLayoutContextFlyoutRunAsAdmin" x:Load="False" - Click="{x:Bind ParentShellPageInstance.InteractionOperations.RunAsAdmin_Click}" Text="Run as another user"> + + + + + @@ -459,8 +485,12 @@ x:Name="RunAsAnotherUser" x:Uid="BaseLayoutContextFlyoutRunAsAnotherUser" x:Load="False" - Click="{x:Bind ParentShellPageInstance.InteractionOperations.RunAsAnotherUser_Click}" Text="RunAsAnotherUser"> + + + + + @@ -518,8 +548,12 @@ + + + + + @@ -539,10 +573,14 @@ + + + + + - + @@ -553,9 +591,13 @@ x:Name="SidebarPinItem" x:Uid="BaseLayoutItemContextFlyoutPinToSidebar" x:Load="False" - Click="{x:Bind ParentShellPageInstance.InteractionOperations.PinItem_Click}" Tag="PinItem_FlyoutItem" Text="Pin to sidebar"> + + + + + @@ -564,9 +606,13 @@ x:Name="SidebarUnpinItem" x:Uid="SideBarUnpinFromSideBar" x:Load="False" - Click="{x:Bind ParentShellPageInstance.InteractionOperations.UnpinItem_Click}" Tag="PinItem_FlyoutItem" Text="Unpin from sidebar"> + + + + + @@ -583,9 +629,13 @@ + + + + + @@ -640,11 +690,11 @@ diff --git a/Files/Views/LayoutModes/GenericFileBrowser.xaml.cs b/Files/Views/LayoutModes/GenericFileBrowser.xaml.cs index e832e45502ed..d456808d53be 100644 --- a/Files/Views/LayoutModes/GenericFileBrowser.xaml.cs +++ b/Files/Views/LayoutModes/GenericFileBrowser.xaml.cs @@ -4,6 +4,7 @@ using Files.Helpers.XamlHelpers; using Files.Interacts; using Files.UserControls.Selection; +using Microsoft.Toolkit.Uwp; using Microsoft.Toolkit.Uwp.UI; using Microsoft.Toolkit.Uwp.UI.Controls; using Microsoft.Toolkit.Uwp; @@ -12,9 +13,12 @@ using System.Collections; using System.Collections.Generic; using System.ComponentModel; +using System.Diagnostics; +using System.IO; using System.Linq; using System.Reflection; using System.Threading.Tasks; +using Windows.Foundation.Collections; using Windows.System; using Windows.UI.Core; using Windows.UI.Xaml; @@ -94,6 +98,7 @@ public DataGridColumn SortedColumn private DispatcherQueueTimer tapDebounceTimer; public GenericFileBrowser() + : base() { InitializeComponent(); base.BaseLayoutContextFlyout = BaseLayoutContextFlyout; @@ -109,6 +114,11 @@ public GenericFileBrowser() tapDebounceTimer = timerQueue.CreateTimer(); } + protected override void InitializeCommandsViewModel() + { + CommandsViewModel = new BaseLayoutCommandsViewModel(new BaseLayoutCommandImplementationModel(ParentShellPageInstance)); + } + private void SelectionRectangle_SelectionStarted(object sender, EventArgs e) { // If drag selection is active do not trigger file open on pointer release @@ -239,8 +249,11 @@ public override void StartRenameItem() { try { - AllView.CurrentColumn = AllView.Columns[1]; - AllView.BeginEdit(); + if (IsItemSelected) + { + AllView.CurrentColumn = AllView.Columns[1]; + AllView.BeginEdit(); + } } catch (InvalidOperationException) { @@ -436,7 +449,7 @@ private async void AllView_ItemPress(object sender, PointerRoutedEventArgs e) { tapDebounceTimer.Stop(); await Task.Delay(200); // The delay gives time for the item to be selected - ParentShellPageInstance.InteractionOperations.OpenItem_Click(null, null); + ParentShellPageInstance.InteractionOperations.OpenSelectedItems(false); } } @@ -479,7 +492,7 @@ private void AllView_PreviewKeyDown(object sender, KeyRoutedEventArgs e) } else { - ParentShellPageInstance.InteractionOperations.OpenItem_Click(null, null); + ParentShellPageInstance.InteractionOperations.OpenSelectedItems(false); } e.Handled = true; } @@ -636,7 +649,17 @@ private void RadioMenuSortDirection_Click(object sender, RoutedEventArgs e) private void AllView_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e) { tapDebounceTimer.Stop(); - ParentShellPageInstance.InteractionOperations.OpenItem_Click(null, null); + ParentShellPageInstance.InteractionOperations.OpenSelectedItems(false); + } + + #region IDisposable + + public override void Dispose() + { + Debugger.Break(); // Not Implemented + CommandsViewModel?.Dispose(); } + + #endregion } } diff --git a/Files/Views/LayoutModes/GridViewBrowser.xaml b/Files/Views/LayoutModes/GridViewBrowser.xaml index 0be7a54985c9..a1319917c171 100644 --- a/Files/Views/LayoutModes/GridViewBrowser.xaml +++ b/Files/Views/LayoutModes/GridViewBrowser.xaml @@ -12,6 +12,8 @@ xmlns:local2="using:Files.Filesystem" xmlns:local3="using:Files.Filesystem.Cloud" xmlns:xh="using:Files.Helpers.XamlHelpers" + xmlns:i="using:Microsoft.Xaml.Interactivity" + xmlns:icore="using:Microsoft.Xaml.Interactions.Core" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:muxc="using:Microsoft.UI.Xaml.Controls" x:Name="PageRoot" @@ -218,8 +220,12 @@ x:Name="UnpinDirectoryFromSidebar" x:Uid="BaseLayoutContextFlyoutUnpinDirectoryFromSidebar" x:Load="False" - Click="{x:Bind ParentShellPageInstance.InteractionOperations.UnpinDirectoryFromSidebar}" Text="Unpin directory from sidebar"> + + + + + @@ -306,9 +312,13 @@ + + + + + @@ -324,9 +334,13 @@ x:Name="OpenItem" x:Uid="BaseLayoutItemContextFlyoutOpenItem" x:Load="False" - Click="{x:Bind ParentShellPageInstance.InteractionOperations.OpenItem_Click}" Tag="Open_FlyoutItem" Text="Open"> + + + + + @@ -391,17 +405,25 @@ + + + + + - + + + + + + @@ -412,8 +434,12 @@ x:Name="RunAsAdmin" x:Uid="BaseLayoutContextFlyoutRunAsAdmin" x:Load="False" - Click="{x:Bind ParentShellPageInstance.InteractionOperations.RunAsAdmin_Click}" Text="Run as another user"> + + + + + @@ -422,8 +448,12 @@ x:Name="RunAsAnotherUser" x:Uid="BaseLayoutContextFlyoutRunAsAnotherUser" x:Load="False" - Click="{x:Bind ParentShellPageInstance.InteractionOperations.RunAsAnotherUser_Click}" Text="RunAsAnotherUser"> + + + + + @@ -481,8 +511,12 @@ + + + + + @@ -502,8 +536,12 @@ + + + + + @@ -516,9 +554,13 @@ x:Name="SidebarPinItem" x:Uid="BaseLayoutItemContextFlyoutPinToSidebar" x:Load="False" - Click="{x:Bind ParentShellPageInstance.InteractionOperations.PinItem_Click}" Tag="PinItem_FlyoutItem" Text="Pin to sidebar"> + + + + + @@ -527,9 +569,13 @@ x:Name="SidebarUnpinItem" x:Uid="SideBarUnpinFromSideBar" x:Load="False" - Click="{x:Bind ParentShellPageInstance.InteractionOperations.UnpinItem_Click}" Tag="PinItem_FlyoutItem" Text="Unpin from sidebar"> + + + + + @@ -546,9 +592,13 @@ + + + + + @@ -899,19 +949,19 @@ diff --git a/Files/Views/LayoutModes/GridViewBrowser.xaml.cs b/Files/Views/LayoutModes/GridViewBrowser.xaml.cs index 433b9433be3c..df870f620ff3 100644 --- a/Files/Views/LayoutModes/GridViewBrowser.xaml.cs +++ b/Files/Views/LayoutModes/GridViewBrowser.xaml.cs @@ -1,13 +1,19 @@ using Files.Enums; using Files.EventArguments; using Files.Filesystem; +using Files.Helpers; using Files.Helpers.XamlHelpers; +using Files.Interacts; using Files.UserControls.Selection; +using Microsoft.Toolkit.Uwp; using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics; +using System.IO; using System.Linq; using System.Threading.Tasks; +using Windows.Foundation.Collections; using Windows.System; using Windows.UI.Core; using Windows.UI.Xaml; @@ -25,6 +31,7 @@ public sealed partial class GridViewBrowser : BaseLayout public string oldItemName; public GridViewBrowser() + : base() { InitializeComponent(); this.DataContext = this; @@ -35,6 +42,11 @@ public GridViewBrowser() selectionRectangle.SelectionEnded += SelectionRectangle_SelectionEnded; } + protected override void InitializeCommandsViewModel() + { + CommandsViewModel = new BaseLayoutCommandsViewModel(new BaseLayoutCommandImplementationModel(ParentShellPageInstance)); + } + protected override void OnNavigatedTo(NavigationEventArgs eventArgs) { base.OnNavigatedTo(eventArgs); @@ -311,7 +323,7 @@ private void FileList_PreviewKeyDown(object sender, KeyRoutedEventArgs e) { if (!IsRenamingItem) { - ParentShellPageInstance.InteractionOperations.OpenItem_Click(null, null); + ParentShellPageInstance.InteractionOperations.OpenSelectedItems(false); e.Handled = true; } } @@ -326,7 +338,7 @@ private void FileList_PreviewKeyDown(object sender, KeyRoutedEventArgs e) { if (IsQuickLookEnabled) { - ParentShellPageInstance.InteractionOperations.ToggleQuickLook(); + QuickLookHelpers.ToggleQuickLook(ParentShellPageInstance); } e.Handled = true; } @@ -439,7 +451,7 @@ private async void FileList_ItemClick(object sender, ItemClickEventArgs e) if (AppSettings.OpenItemsWithOneclick) { await Task.Delay(200); // The delay gives time for the item to be selected - ParentShellPageInstance.InteractionOperations.OpenItem_Click(null, null); + ParentShellPageInstance.InteractionOperations.OpenSelectedItems(false); } } @@ -471,5 +483,15 @@ private void FileList_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e) ParentShellPageInstance.InteractionOperations.OpenSelectedItems(false); } } + + #region IDisposable + + public override void Dispose() + { + Debugger.Break(); // Not Implemented + CommandsViewModel?.Dispose(); + } + + #endregion } } \ No newline at end of file diff --git a/Files/Views/ModernShellPage.xaml.cs b/Files/Views/ModernShellPage.xaml.cs index 494248f18778..08cc36fc62c3 100644 --- a/Files/Views/ModernShellPage.xaml.cs +++ b/Files/Views/ModernShellPage.xaml.cs @@ -43,7 +43,7 @@ namespace Files.Views public sealed partial class ModernShellPage : Page, IShellPage, INotifyPropertyChanged { private readonly StorageHistoryHelpers storageHistoryHelpers; - + public IBaseLayout SlimContentPage => ContentPage; public IFilesystemHelpers FilesystemHelpers { get; private set; } private CancellationTokenSource cancellationTokenSource; public SettingsViewModel AppSettings => App.AppSettings; @@ -983,7 +983,7 @@ await FilesystemHelpers.DeleteItemsAsync( { if (ContentPage.IsQuickLookEnabled) { - InteractionOperations.ToggleQuickLook(); + QuickLookHelpers.ToggleQuickLook(this); } } break; @@ -1016,7 +1016,7 @@ await FilesystemHelpers.DeleteItemsAsync( { if (ContentPage.IsItemSelected) { - InteractionOperations.RenameItem_Click(null, null); + ContentPage.StartRenameItem(); } } break; diff --git a/Files/Views/PaneHolderPage.xaml b/Files/Views/PaneHolderPage.xaml index 0fee3bc0c0da..c4f78ccce7f6 100644 --- a/Files/Views/PaneHolderPage.xaml +++ b/Files/Views/PaneHolderPage.xaml @@ -105,7 +105,7 @@ IsOpen="{x:Bind IsSidebarOpen, Mode=TwoWay}" IsCompact="{x:Bind IsWindowCompactSize, Mode=OneWay}" CanOpenInNewPane="{x:Bind IsMultiPaneEnabled, Mode=OneWay}" - EmptyRecycleBinCommand="{x:Bind InteractionOperations.EmptyRecycleBin, Mode=OneWay}" + EmptyRecycleBinCommand="{x:Bind EmptyRecycleBinCommand, Mode=OneWay}" Loaded="SidebarControl_Loaded" />