From 03184ccc4fee4781927549d6a903a9b2eabadb2d Mon Sep 17 00:00:00 2001 From: 0x5BFA <62196528+0x5bfa@users.noreply.github.com> Date: Sun, 14 Jan 2024 22:38:46 +0900 Subject: [PATCH 01/11] Initial commit --- .../Actions/FileSystem/FormatDriveAction.cs | 2 +- .../Data/Contexts/HomePage/HomePageContext.cs | 10 +- .../Contexts/HomePage/IHomePageContext.cs | 3 +- .../Data/Contexts/SideBar/ISideBarContext.cs | 2 +- .../Data/Contexts/SideBar/SideBarContext.cs | 4 +- .../Data/Contexts/Tags/TagsContext.cs | 4 +- .../Contracts}/IWidgetCardItem.cs | 5 +- .../Contracts/IWidgetViewModel.cs} | 4 +- .../QuickAccessCardEventArgs.cs | 38 ++++++ ...WidgetsRightClickedItemChangedEventArgs.cs | 1 - .../PropertiesNavigationViewItemFactory.cs | 2 +- .../{DriveItem.cs => SideBarDriveItem.cs} | 8 +- .../{FileTagItem.cs => SideBarFileTagItem.cs} | 2 +- ...LocationItem.cs => SideBarLocationItem.cs} | 6 +- .../{WslDistroItem.cs => SideBarWSLItem.cs} | 2 +- src/Files.App/Data/Items/TagsListItem.cs | 1 - src/Files.App/Data/Items/WidgetCardItem.cs | 15 +++ .../Items/WidgetContainerItem.cs} | 47 ++++--- .../Data/Items/WidgetDriveCardItem.cs | 61 ++++++++++ .../Data/Items/WidgetFileTagsContainerItem.cs | 81 ++++++++++++ .../Items/WidgetFileTagsItem.cs} | 39 ++++-- .../Data/Items/WidgetFolderCardItem.cs | 67 ++++++++++ .../Data/Models/NetworkDrivesViewModel.cs | 6 +- .../Data/Models/SidebarPinnedModel.cs | 12 +- .../Dialogs/ReorderSidebarItemsDialog.xaml.cs | 12 +- src/Files.App/GlobalUsings.cs | 9 ++ .../Helpers/Navigation/NavigationHelpers.cs | 6 +- src/Files.App/Services/JumpListService.cs | 2 +- .../Services/NetworkDrivesService.cs | 2 +- .../Services/RemovableDrivesService.cs | 4 +- ...mePageWidget.cs => BaseWidgetViewModel.cs} | 28 +++-- .../UserControls/Widgets/DrivesWidget.xaml | 8 +- .../UserControls/Widgets/DrivesWidget.xaml.cs | 83 +++---------- .../UserControls/Widgets/FileTagsWidget.xaml | 11 +- .../Widgets/FileTagsWidget.xaml.cs | 21 ++-- .../Widgets/QuickAccessWidget.xaml | 7 +- .../Widgets/QuickAccessWidget.xaml.cs | 115 ++++-------------- .../Widgets/RecentFilesWidget.xaml | 5 +- .../Widgets/RecentFilesWidget.xaml.cs | 12 +- .../UserControls/Widgets/WidgetCardItem.cs | 14 --- .../Utils/Cloud/CloudDrivesManager.cs | 6 +- .../Utils/FileTags/FileTagsManager.cs | 6 +- .../Utils/Global/WSLDistroManager.cs | 8 +- .../Global/WindowsStorageDeviceWatcher.cs | 4 +- .../Utils/Library/LibraryLocationItem.cs | 2 +- src/Files.App/Utils/RecentItem/RecentItem.cs | 1 - .../Utils/Storage/Helpers/DriveHelpers.cs | 4 +- .../Storage/Helpers/StorageFileExtensions.cs | 2 +- .../Utils/Storage/Search/FolderSearch.cs | 2 +- src/Files.App/Utils/Widgets/WidgetsHelpers.cs | 5 +- .../ReorderSidebarItemsDialogViewModel.cs | 6 +- src/Files.App/ViewModels/HomeViewModel.cs | 13 +- .../Properties/BasePropertiesPage.cs | 2 +- .../Properties/Items/DriveProperties.cs | 4 +- .../Properties/SecurityAdvancedViewModel.cs | 2 +- .../Properties/SecurityViewModel.cs | 2 +- .../UserControls/SidebarViewModel.cs | 72 +++++------ .../UserControls/ToolbarViewModel.cs | 2 +- .../Widgets/FileTagsContainerViewModel.cs | 68 ----------- .../Widgets/FileTagsWidgetViewModel.cs | 19 ++- .../Widgets/ICustomWidgetItemModel.cs | 12 -- .../UserControls/Widgets/IWidgetItemModel.cs | 24 ---- .../Widgets/WidgetsListControlViewModel.cs | 105 ---------------- .../ViewModels/Widgets/WidgetItem.cs | 62 ---------- .../Views/Properties/GeneralPage.xaml.cs | 2 +- 65 files changed, 546 insertions(+), 650 deletions(-) rename src/Files.App/{UserControls/Widgets => Data/Contracts}/IWidgetCardItem.cs (80%) rename src/Files.App/{ViewModels/Widgets/IWidgetItem.cs => Data/Contracts/IWidgetViewModel.cs} (81%) create mode 100644 src/Files.App/Data/EventArguments/QuickAccessCardEventArgs.cs rename src/Files.App/Data/Items/{DriveItem.cs => SideBarDriveItem.cs} (96%) rename src/Files.App/Data/Items/{FileTagItem.cs => SideBarFileTagItem.cs} (94%) rename src/Files.App/Data/Items/{LocationItem.cs => SideBarLocationItem.cs} (93%) rename src/Files.App/Data/Items/{WslDistroItem.cs => SideBarWSLItem.cs} (94%) create mode 100644 src/Files.App/Data/Items/WidgetCardItem.cs rename src/Files.App/{ViewModels/UserControls/Widgets/WidgetsListControlItemViewModel.cs => Data/Items/WidgetContainerItem.cs} (65%) create mode 100644 src/Files.App/Data/Items/WidgetDriveCardItem.cs create mode 100644 src/Files.App/Data/Items/WidgetFileTagsContainerItem.cs rename src/Files.App/{ViewModels/UserControls/Widgets/FileTagsItemViewModel.cs => Data/Items/WidgetFileTagsItem.cs} (54%) create mode 100644 src/Files.App/Data/Items/WidgetFolderCardItem.cs rename src/Files.App/UserControls/Widgets/{HomePageWidget.cs => BaseWidgetViewModel.cs} (80%) delete mode 100644 src/Files.App/UserControls/Widgets/WidgetCardItem.cs delete mode 100644 src/Files.App/ViewModels/UserControls/Widgets/FileTagsContainerViewModel.cs delete mode 100644 src/Files.App/ViewModels/UserControls/Widgets/ICustomWidgetItemModel.cs delete mode 100644 src/Files.App/ViewModels/UserControls/Widgets/IWidgetItemModel.cs delete mode 100644 src/Files.App/ViewModels/UserControls/Widgets/WidgetsListControlViewModel.cs delete mode 100644 src/Files.App/ViewModels/Widgets/WidgetItem.cs diff --git a/src/Files.App/Actions/FileSystem/FormatDriveAction.cs b/src/Files.App/Actions/FileSystem/FormatDriveAction.cs index 2cff61b4f5de..dcdf3a6d1683 100644 --- a/src/Files.App/Actions/FileSystem/FormatDriveAction.cs +++ b/src/Files.App/Actions/FileSystem/FormatDriveAction.cs @@ -20,7 +20,7 @@ public string Description public bool IsExecutable => context.HasItem && !context.HasSelection && - (drivesViewModel.Drives.Cast().FirstOrDefault(x => + (drivesViewModel.Drives.Cast().FirstOrDefault(x => string.Equals(x.Path, context.Folder?.ItemPath))?.MenuOptions.ShowFormatDrive ?? false); public FormatDriveAction() diff --git a/src/Files.App/Data/Contexts/HomePage/HomePageContext.cs b/src/Files.App/Data/Contexts/HomePage/HomePageContext.cs index 0fb7531dddb3..ca8f78be38b7 100644 --- a/src/Files.App/Data/Contexts/HomePage/HomePageContext.cs +++ b/src/Files.App/Data/Contexts/HomePage/HomePageContext.cs @@ -10,7 +10,7 @@ namespace Files.App.Data.Contexts { internal class HomePageContext : ObservableObject, IHomePageContext { - private static readonly IImmutableList emptyTaggedItems = Enumerable.Empty().ToImmutableList(); + private static readonly IImmutableList emptyTaggedItems = Enumerable.Empty().ToImmutableList(); public bool IsAnyItemRightClicked => rightClickedItem is not null; @@ -20,8 +20,8 @@ internal class HomePageContext : ObservableObject, IHomePageContext private CommandBarFlyout? itemContextFlyoutMenu = null; public CommandBarFlyout? ItemContextFlyoutMenu => itemContextFlyoutMenu; - private IReadOnlyList selectedTaggedItems = emptyTaggedItems; - public IReadOnlyList SelectedTaggedItems + private IReadOnlyList selectedTaggedItems = emptyTaggedItems; + public IReadOnlyList SelectedTaggedItems { get => selectedTaggedItems; set => selectedTaggedItems = value ?? emptyTaggedItems; @@ -29,11 +29,11 @@ public IReadOnlyList SelectedTaggedItems public HomePageContext() { - HomePageWidget.RightClickedItemChanged += HomePageWidget_RightClickedItemChanged; + BaseWidgetViewModel.RightClickedItemChanged += HomePageWidget_RightClickedItemChanged; FileTagsWidget.SelectedTaggedItemsChanged += FileTagsWidget_SelectedTaggedItemsChanged; } - private void FileTagsWidget_SelectedTaggedItemsChanged(object? sender, IEnumerable e) + private void FileTagsWidget_SelectedTaggedItemsChanged(object? sender, IEnumerable e) { SetProperty(ref selectedTaggedItems, e.ToList()); } diff --git a/src/Files.App/Data/Contexts/HomePage/IHomePageContext.cs b/src/Files.App/Data/Contexts/HomePage/IHomePageContext.cs index a08a26185482..2f0197863a9d 100644 --- a/src/Files.App/Data/Contexts/HomePage/IHomePageContext.cs +++ b/src/Files.App/Data/Contexts/HomePage/IHomePageContext.cs @@ -1,7 +1,6 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. -using Files.App.UserControls.Widgets; using Files.App.ViewModels.Widgets; using Microsoft.UI.Xaml.Controls; @@ -22,7 +21,7 @@ internal interface IHomePageContext /// /// An list containing all the selected tagged items /// - IReadOnlyList SelectedTaggedItems { get; } + IReadOnlyList SelectedTaggedItems { get; } /// /// Tells whether any item has been right clicked diff --git a/src/Files.App/Data/Contexts/SideBar/ISideBarContext.cs b/src/Files.App/Data/Contexts/SideBar/ISideBarContext.cs index 73897d0ddd65..c5a537e1ff2c 100644 --- a/src/Files.App/Data/Contexts/SideBar/ISideBarContext.cs +++ b/src/Files.App/Data/Contexts/SideBar/ISideBarContext.cs @@ -26,6 +26,6 @@ public interface ISidebarContext /// /// Gets the drive item to open if any /// - DriveItem? OpenDriveItem { get; } + SideBarDriveItem? OpenDriveItem { get; } } } diff --git a/src/Files.App/Data/Contexts/SideBar/SideBarContext.cs b/src/Files.App/Data/Contexts/SideBar/SideBarContext.cs index 3a8f2f8f03dc..296075b9fa8b 100644 --- a/src/Files.App/Data/Contexts/SideBar/SideBarContext.cs +++ b/src/Files.App/Data/Contexts/SideBar/SideBarContext.cs @@ -24,8 +24,8 @@ internal class SidebarContext : ObservableObject, ISidebarContext _RightClickedItem!.Section is SectionType.Favorites && FavoriteIndex is not -1; - public DriveItem? OpenDriveItem - => _RightClickedItem as DriveItem; + public SideBarDriveItem? OpenDriveItem + => _RightClickedItem as SideBarDriveItem; public SidebarContext() { diff --git a/src/Files.App/Data/Contexts/Tags/TagsContext.cs b/src/Files.App/Data/Contexts/Tags/TagsContext.cs index 6564e22a4e16..ff7d156d44a0 100644 --- a/src/Files.App/Data/Contexts/Tags/TagsContext.cs +++ b/src/Files.App/Data/Contexts/Tags/TagsContext.cs @@ -6,7 +6,7 @@ namespace Files.App.Data.Contexts { - sealed class TagsContext : ITagsContext + sealed class TagsContext : ITagsContext { private static readonly IReadOnlyList<(string path, bool isFolder)> _emptyTaggedItemsList = Enumerable.Empty<(string path, bool isFolder)>().ToImmutableList(); @@ -29,7 +29,7 @@ sealed class TagsContext : ITagsContext public TagsContext() { - FileTagsContainerViewModel.SelectedTagChanged += SelectedTagsChanged; + WidgetFileTagsContainerItem.SelectedTagChanged += SelectedTagsChanged; SidebarViewModel.SelectedTagChanged += SelectedTagsChanged; } diff --git a/src/Files.App/UserControls/Widgets/IWidgetCardItem.cs b/src/Files.App/Data/Contracts/IWidgetCardItem.cs similarity index 80% rename from src/Files.App/UserControls/Widgets/IWidgetCardItem.cs rename to src/Files.App/Data/Contracts/IWidgetCardItem.cs index bb6ab0c2abb3..efae7aba132a 100644 --- a/src/Files.App/UserControls/Widgets/IWidgetCardItem.cs +++ b/src/Files.App/Data/Contracts/IWidgetCardItem.cs @@ -2,9 +2,8 @@ // Licensed under the MIT License. See the LICENSE. using Microsoft.UI.Xaml.Media.Imaging; -using System.Threading.Tasks; -namespace Files.App.UserControls.Widgets +namespace Files.App.Data.Contracts { public interface IWidgetCardItem { @@ -16,4 +15,4 @@ public interface IWidgetCardItem Task LoadCardThumbnailAsync(); } -} \ No newline at end of file +} diff --git a/src/Files.App/ViewModels/Widgets/IWidgetItem.cs b/src/Files.App/Data/Contracts/IWidgetViewModel.cs similarity index 81% rename from src/Files.App/ViewModels/Widgets/IWidgetItem.cs rename to src/Files.App/Data/Contracts/IWidgetViewModel.cs index 971ef80c38f3..f890b1fb45dc 100644 --- a/src/Files.App/ViewModels/Widgets/IWidgetItem.cs +++ b/src/Files.App/Data/Contracts/IWidgetViewModel.cs @@ -3,9 +3,9 @@ using Microsoft.UI.Xaml.Controls; -namespace Files.App.ViewModels.Widgets +namespace Files.App.Data.Contracts { - public interface IWidgetItem : IDisposable + public interface IWidgetViewModel : IDisposable { string WidgetName { get; } diff --git a/src/Files.App/Data/EventArguments/QuickAccessCardEventArgs.cs b/src/Files.App/Data/EventArguments/QuickAccessCardEventArgs.cs new file mode 100644 index 000000000000..9914a87cc0e3 --- /dev/null +++ b/src/Files.App/Data/EventArguments/QuickAccessCardEventArgs.cs @@ -0,0 +1,38 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +namespace Files.App.Data.EventArguments +{ + public class QuickAccessCardEventArgs : EventArgs + { + public SideBarLocationItem? Item { get; set; } + } + + public class QuickAccessCardInvokedEventArgs : EventArgs + { + public string? Path { get; set; } + } + + public class ModifyQuickAccessEventArgs : EventArgs + { + public string[]? Paths { get; set; } + public ShellFileItem[]? Items { get; set; } + public bool Add; + public bool Pin = true; + public bool Reset = false; + public bool Reorder = false; + + public ModifyQuickAccessEventArgs(string[] paths, bool add) + { + Paths = paths; + Add = add; + } + + public ModifyQuickAccessEventArgs(ShellFileItem[] items, bool add) + { + Paths = items.Select(x => x.FilePath).ToArray(); + Items = items; + Add = add; + } + } +} diff --git a/src/Files.App/Data/EventArguments/WidgetsRightClickedItemChangedEventArgs.cs b/src/Files.App/Data/EventArguments/WidgetsRightClickedItemChangedEventArgs.cs index e820d3ae2bac..1ecd49dde0da 100644 --- a/src/Files.App/Data/EventArguments/WidgetsRightClickedItemChangedEventArgs.cs +++ b/src/Files.App/Data/EventArguments/WidgetsRightClickedItemChangedEventArgs.cs @@ -1,7 +1,6 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. -using Files.App.UserControls.Widgets; using Microsoft.UI.Xaml.Controls; namespace Files.App.Data.EventArguments diff --git a/src/Files.App/Data/Factories/PropertiesNavigationViewItemFactory.cs b/src/Files.App/Data/Factories/PropertiesNavigationViewItemFactory.cs index 4c5753bcb44d..ab13b6aec515 100644 --- a/src/Files.App/Data/Factories/PropertiesNavigationViewItemFactory.cs +++ b/src/Files.App/Data/Factories/PropertiesNavigationViewItemFactory.cs @@ -124,7 +124,7 @@ public static ObservableCollection Initialize if (!compatibilityItemEnabled) PropertiesNavigationViewItems.Remove(compatibilityItem); } - else if (item is DriveItem) + else if (item is SideBarDriveItem) { PropertiesNavigationViewItems.Remove(hashesItem); PropertiesNavigationViewItems.Remove(shortcutItem); diff --git a/src/Files.App/Data/Items/DriveItem.cs b/src/Files.App/Data/Items/SideBarDriveItem.cs similarity index 96% rename from src/Files.App/Data/Items/DriveItem.cs rename to src/Files.App/Data/Items/SideBarDriveItem.cs index 92767f8c584a..a674c15991e8 100644 --- a/src/Files.App/Data/Items/DriveItem.cs +++ b/src/Files.App/Data/Items/SideBarDriveItem.cs @@ -15,7 +15,7 @@ namespace Files.App.Data.Items { - public class DriveItem : ObservableObject, INavigationControlItem, ILocatableFolder + public class SideBarDriveItem : ObservableObject, INavigationControlItem, ILocatableFolder { private BitmapImage icon; public BitmapImage Icon @@ -230,9 +230,9 @@ private async void ItemDecorator_Click(object sender, RoutedEventArgs e) await UIHelpers.ShowDeviceEjectResultAsync(Type, result); } - public static async Task CreateFromPropertiesAsync(StorageFolder root, string deviceId, string label, DriveType type, IRandomAccessStream imageStream = null) + public static async Task CreateFromPropertiesAsync(StorageFolder root, string deviceId, string label, DriveType type, IRandomAccessStream imageStream = null) { - var item = new DriveItem(); + var item = new SideBarDriveItem(); if (imageStream is not null) item.IconData = await imageStream.ToByteArrayAsync(); @@ -310,7 +310,7 @@ public async Task UpdatePropertiesAsync() public int CompareTo(INavigationControlItem other) { - var result = Type.CompareTo((other as DriveItem)?.Type ?? Type); + var result = Type.CompareTo((other as SideBarDriveItem)?.Type ?? Type); return result == 0 ? Text.CompareTo(other.Text) : result; } diff --git a/src/Files.App/Data/Items/FileTagItem.cs b/src/Files.App/Data/Items/SideBarFileTagItem.cs similarity index 94% rename from src/Files.App/Data/Items/FileTagItem.cs rename to src/Files.App/Data/Items/SideBarFileTagItem.cs index 9752fcf67efc..ca0ed3c2468e 100644 --- a/src/Files.App/Data/Items/FileTagItem.cs +++ b/src/Files.App/Data/Items/SideBarFileTagItem.cs @@ -9,7 +9,7 @@ namespace Files.App.Data.Items { - public class FileTagItem : ObservableObject, INavigationControlItem + public class SideBarFileTagItem : ObservableObject, INavigationControlItem { public string Text { get; set; } diff --git a/src/Files.App/Data/Items/LocationItem.cs b/src/Files.App/Data/Items/SideBarLocationItem.cs similarity index 93% rename from src/Files.App/Data/Items/LocationItem.cs rename to src/Files.App/Data/Items/SideBarLocationItem.cs index d73003b021c0..83c766f34f8a 100644 --- a/src/Files.App/Data/Items/LocationItem.cs +++ b/src/Files.App/Data/Items/SideBarLocationItem.cs @@ -8,7 +8,7 @@ namespace Files.App.Data.Items { - public class LocationItem : ObservableObject, INavigationControlItem + public class SideBarLocationItem : ObservableObject, INavigationControlItem { public BitmapImage icon; public BitmapImage Icon @@ -115,13 +115,13 @@ public FrameworkElement? ItemDecorator public int CompareTo(INavigationControlItem other) => Text.CompareTo(other.Text); - public static T Create() where T : LocationItem, new() + public static T Create() where T : SideBarLocationItem, new() { return new T(); } } - public class RecycleBinLocationItem : LocationItem + public class RecycleBinLocationItem : SideBarLocationItem { public void RefreshSpaceUsed(object sender, FileSystemEventArgs e) { diff --git a/src/Files.App/Data/Items/WslDistroItem.cs b/src/Files.App/Data/Items/SideBarWSLItem.cs similarity index 94% rename from src/Files.App/Data/Items/WslDistroItem.cs rename to src/Files.App/Data/Items/SideBarWSLItem.cs index 6f373323d9df..b40b887956c9 100644 --- a/src/Files.App/Data/Items/WslDistroItem.cs +++ b/src/Files.App/Data/Items/SideBarWSLItem.cs @@ -5,7 +5,7 @@ namespace Files.App.Data.Items { - public class WslDistroItem : ObservableObject, INavigationControlItem + public class SideBarWSLItem : ObservableObject, INavigationControlItem { public string Text { get; set; } diff --git a/src/Files.App/Data/Items/TagsListItem.cs b/src/Files.App/Data/Items/TagsListItem.cs index 18d44e9c5d1e..62affbbe8645 100644 --- a/src/Files.App/Data/Items/TagsListItem.cs +++ b/src/Files.App/Data/Items/TagsListItem.cs @@ -5,7 +5,6 @@ namespace Files.App.Data.Items { - public class TagsListItem { public bool IsTag diff --git a/src/Files.App/Data/Items/WidgetCardItem.cs b/src/Files.App/Data/Items/WidgetCardItem.cs new file mode 100644 index 000000000000..4eaa7a9ffb19 --- /dev/null +++ b/src/Files.App/Data/Items/WidgetCardItem.cs @@ -0,0 +1,15 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +namespace Files.App.Data.Items +{ + /// + /// Represents base item for widget card item. + /// + public abstract class WidgetCardItem : ObservableObject + { + public virtual string? Path { get; set; } + + public virtual object? Item { get; set; } + } +} diff --git a/src/Files.App/ViewModels/UserControls/Widgets/WidgetsListControlItemViewModel.cs b/src/Files.App/Data/Items/WidgetContainerItem.cs similarity index 65% rename from src/Files.App/ViewModels/UserControls/Widgets/WidgetsListControlItemViewModel.cs rename to src/Files.App/Data/Items/WidgetContainerItem.cs index d459c5917967..ce4722a3cba5 100644 --- a/src/Files.App/ViewModels/UserControls/Widgets/WidgetsListControlItemViewModel.cs +++ b/src/Files.App/Data/Items/WidgetContainerItem.cs @@ -3,14 +3,28 @@ using Microsoft.UI.Xaml.Controls; -namespace Files.App.ViewModels.Widgets +namespace Files.App.Data.Items { - public class WidgetsListControlItemViewModel : ObservableObject, IDisposable + /// + /// Represents an item of Files widget container. + /// + public class WidgetContainerItem : ObservableObject, IDisposable { private readonly Action _expanderValueChangedCallback; - private readonly Func _expanderValueRequestedCallback; + public IWidgetViewModel WidgetItemModel + => WidgetControl as IWidgetViewModel; + + public string WidgetAutomationProperties + => WidgetItemModel.AutomationProperties; + + public bool ShowMenuFlyout + => WidgetItemModel.ShowMenuFlyout; + + public MenuFlyoutItem MenuFlyoutItem + => WidgetItemModel.MenuFlyoutItem; + private object _WidgetControl; public object WidgetControl { @@ -18,13 +32,6 @@ public object WidgetControl set => SetProperty(ref _WidgetControl, value); } - public WidgetsListControlItemViewModel(object widgetControl, Action expanderValueChangedCallback, Func expanderValueRequestedCallback) - { - WidgetControl = widgetControl; - _expanderValueChangedCallback = expanderValueChangedCallback; - _expanderValueRequestedCallback = expanderValueRequestedCallback; - } - public bool IsExpanded { get => _expanderValueRequestedCallback?.Invoke() ?? true; @@ -35,24 +42,12 @@ public bool IsExpanded } } - public IWidgetItemModel WidgetItemModel + public WidgetContainerItem(object widgetControl, Action expanderValueChangedCallback, Func expanderValueRequestedCallback) { - get => WidgetControl as IWidgetItemModel; - } - - public string WidgetAutomationProperties - { - get => WidgetItemModel.AutomationProperties; - } + _expanderValueChangedCallback = expanderValueChangedCallback; + _expanderValueRequestedCallback = expanderValueRequestedCallback; - public bool ShowMenuFlyout - { - get => WidgetItemModel.ShowMenuFlyout; - } - - public MenuFlyoutItem MenuFlyoutItem - { - get => WidgetItemModel.MenuFlyoutItem; + WidgetControl = widgetControl; } public void Dispose() diff --git a/src/Files.App/Data/Items/WidgetDriveCardItem.cs b/src/Files.App/Data/Items/WidgetDriveCardItem.cs new file mode 100644 index 000000000000..617cc195dd16 --- /dev/null +++ b/src/Files.App/Data/Items/WidgetDriveCardItem.cs @@ -0,0 +1,61 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +using Microsoft.UI.Xaml.Media.Imaging; + +namespace Files.App.Data.Items +{ + public class WidgetDriveCardItem : WidgetCardItem, IWidgetCardItem, IComparable + { + // Fields + + private byte[] _thumbnailData; + + // Properties + + public new SideBarDriveItem Item { get; private set; } + + public bool HasThumbnail + => _Thumbnail is not null && _thumbnailData is not null; + + private BitmapImage _Thumbnail; + public BitmapImage Thumbnail + { + get => _Thumbnail; + set => SetProperty(ref _Thumbnail, value); + } + + // Constructor + + public WidgetDriveCardItem(SideBarDriveItem item) + { + Item = item; + Path = item.Path; + } + + // Methods + + public async Task LoadCardThumbnailAsync() + { + // Try load thumbnail using ListView mode + if (_thumbnailData is null || _thumbnailData.Length == 0) + _thumbnailData = await FileThumbnailHelper.LoadIconFromPathAsync(Item.Path, Convert.ToUInt32(Constants.DefaultIconSizes.Jumbo), Windows.Storage.FileProperties.ThumbnailMode.SingleItem, Windows.Storage.FileProperties.ThumbnailOptions.ResizeThumbnail); + + // Thumbnail is still null, use DriveItem icon (loaded using SingleItem mode) + if (_thumbnailData is null || _thumbnailData.Length == 0) + { + await Item.LoadThumbnailAsync(); + _thumbnailData = Item.IconData; + } + + // Thumbnail data is valid, set the item icon + if (_thumbnailData is not null && _thumbnailData.Length > 0) + Thumbnail = await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => _thumbnailData.ToBitmapAsync(Constants.DefaultIconSizes.Jumbo)); + } + + public int CompareTo(WidgetDriveCardItem? other) + { + return Item.Path.CompareTo(other?.Item?.Path); + } + } +} diff --git a/src/Files.App/Data/Items/WidgetFileTagsContainerItem.cs b/src/Files.App/Data/Items/WidgetFileTagsContainerItem.cs new file mode 100644 index 000000000000..3d02af682a73 --- /dev/null +++ b/src/Files.App/Data/Items/WidgetFileTagsContainerItem.cs @@ -0,0 +1,81 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +using Files.Shared.Utils; +using System.Windows.Input; + +namespace Files.App.Data.Items +{ + public sealed partial class WidgetFileTagsContainerItem : ObservableObject, IAsyncInitialize + { + // Fields + + private readonly IFileTagsService FileTagsService = Ioc.Default.GetRequiredService(); + private readonly IImageService ImageService = Ioc.Default.GetRequiredService(); + private readonly ICommandManager Commands = Ioc.Default.GetRequiredService(); + + private readonly string _tagUid; + + private readonly Func _openAction; + + // Properties + + public ObservableCollection Tags { get; } + + private string? _Color; + public string? Color + { + get => _Color; + set => SetProperty(ref _Color, value); + } + + private string? _Name; + public string? Name + { + get => _Name; + set => SetProperty(ref _Name, value); + } + + // Events + + public delegate void SelectedTagChangedEventHandler(object sender, SelectedTagChangedEventArgs e); + public static event SelectedTagChangedEventHandler? SelectedTagChanged; + + // Commands + + public ICommand ViewMoreCommand { get; } + public ICommand OpenAllCommand { get; } + + public WidgetFileTagsContainerItem(string tagUid, Func openAction) + { + _tagUid = tagUid; + _openAction = openAction; + Tags = new(); + + ViewMoreCommand = new AsyncRelayCommand(ViewMore); + OpenAllCommand = new AsyncRelayCommand(OpenAll); + } + + /// + public async Task InitAsync(CancellationToken cancellationToken = default) + { + await foreach (var item in FileTagsService.GetItemsForTagAsync(_tagUid, cancellationToken)) + { + var icon = await ImageService.GetIconAsync(item.Storable, cancellationToken); + Tags.Add(new(item.Storable, _openAction, icon)); + } + } + + private Task ViewMore(CancellationToken cancellationToken) + { + return _openAction($"tag:{Name}"); + } + + private Task OpenAll(CancellationToken cancellationToken) + { + SelectedTagChanged?.Invoke(this, new SelectedTagChangedEventArgs(Tags.Select(tag => (tag.Path, tag.IsFolder)))); + + return Commands.OpenAllTaggedItems.ExecuteAsync(); + } + } +} diff --git a/src/Files.App/ViewModels/UserControls/Widgets/FileTagsItemViewModel.cs b/src/Files.App/Data/Items/WidgetFileTagsItem.cs similarity index 54% rename from src/Files.App/ViewModels/UserControls/Widgets/FileTagsItemViewModel.cs rename to src/Files.App/Data/Items/WidgetFileTagsItem.cs index 5138c454b158..7a88613c05b5 100644 --- a/src/Files.App/ViewModels/UserControls/Widgets/FileTagsItemViewModel.cs +++ b/src/Files.App/Data/Items/WidgetFileTagsItem.cs @@ -1,37 +1,53 @@ // Copyright (c) 2023 Files Community // Licensed under the MIT License. See the LICENSE. -using Files.App.UserControls.Widgets; -using Files.Core.Storage; using Files.Core.Storage.Extensions; using Files.Shared.Utils; +using System.Windows.Input; -namespace Files.App.ViewModels.Widgets +namespace Files.App.Data.Items { - public sealed partial class FileTagsItemViewModel : WidgetCardItem + public sealed partial class WidgetFileTagsItem : WidgetCardItem { + // Fields + private readonly IStorable _associatedStorable; // A workaround for lack of MVVM-compliant navigation support. // This workaround must be kept until further refactor of navigation code is completed. private readonly Func _openAction; - [ObservableProperty] + // Properties + + public bool IsFolder + => _associatedStorable is IFolder; + private IImage? _Icon; + public IImage? Icon + { + get => _Icon; + set => SetProperty(ref _Icon, value); + } - [ObservableProperty] - private string _Name; + private string? _Name; + public string? Name + { + get => _Name; + set => SetProperty(ref _Name, value); + } private string _Path; public override string Path { get => _Path; - set => SetProperty(ref _Path, value); + set => SetProperty(ref _Path, value); } - public bool IsFolder => _associatedStorable is IFolder; + // Commands - public FileTagsItemViewModel(IStorable associatedStorable, Func openAction, IImage? icon) + public ICommand ClickAsyncCommand { get; } + + public WidgetFileTagsItem(IStorable associatedStorable, Func openAction, IImage? icon) { _associatedStorable = associatedStorable; _openAction = openAction; @@ -39,9 +55,10 @@ public FileTagsItemViewModel(IStorable associatedStorable, Func op _Name = associatedStorable.Name; _Path = associatedStorable.TryGetPath(); Item = this; + + ClickAsyncCommand = new AsyncRelayCommand(ClickAsync); } - [RelayCommand] private Task ClickAsync(CancellationToken cancellationToken) { return _openAction(_associatedStorable.Id); diff --git a/src/Files.App/Data/Items/WidgetFolderCardItem.cs b/src/Files.App/Data/Items/WidgetFolderCardItem.cs new file mode 100644 index 000000000000..44e0e1fd84b2 --- /dev/null +++ b/src/Files.App/Data/Items/WidgetFolderCardItem.cs @@ -0,0 +1,67 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +using Microsoft.UI.Xaml.Media.Imaging; + +namespace Files.App.Data.Items +{ + public class WidgetFolderCardItem : WidgetCardItem, IWidgetCardItem + { + // Fields + + private byte[] _thumbnailData; + + // Properties + + public string? AutomationProperties { get; set; } + + public SideBarLocationItem? Item { get; private set; } + + public string? Text { get; set; } + + public bool IsPinned { get; set; } + + public bool HasPath + => !string.IsNullOrEmpty(Path); + + public bool HasThumbnail + => Thumbnail is not null && _thumbnailData is not null; + + private BitmapImage? _Thumbnail; + public BitmapImage? Thumbnail + { + get => _Thumbnail; + set => SetProperty(ref _Thumbnail, value); + } + + // Constructor + + public WidgetFolderCardItem(SideBarLocationItem item, string text, bool isPinned) + { + if (!string.IsNullOrWhiteSpace(text)) + { + Text = text; + AutomationProperties = Text; + } + + IsPinned = isPinned; + Item = item; + Path = item.Path; + } + + // Methods + + public async Task LoadCardThumbnailAsync() + { + if (_thumbnailData is null || _thumbnailData.Length == 0) + { + _thumbnailData = await FileThumbnailHelper.LoadIconFromPathAsync(Path, Convert.ToUInt32(Constants.DefaultIconSizes.Jumbo), Windows.Storage.FileProperties.ThumbnailMode.SingleItem, Windows.Storage.FileProperties.ThumbnailOptions.ResizeThumbnail); + } + + if (_thumbnailData is not null && _thumbnailData.Length > 0) + { + Thumbnail = await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => _thumbnailData.ToBitmapAsync(Constants.DefaultIconSizes.Jumbo)); + } + } + } +} diff --git a/src/Files.App/Data/Models/NetworkDrivesViewModel.cs b/src/Files.App/Data/Models/NetworkDrivesViewModel.cs index 7a2f871d0a41..701c2e6a2108 100644 --- a/src/Files.App/Data/Models/NetworkDrivesViewModel.cs +++ b/src/Files.App/Data/Models/NetworkDrivesViewModel.cs @@ -23,7 +23,7 @@ public NetworkDrivesViewModel(INetworkDrivesService networkDrivesService) this.networkDrivesService = networkDrivesService; drives = new ObservableCollection(); - var networkItem = new DriveItem + var networkItem = new SideBarDriveItem { DeviceID = "network-folder", Text = "Network".GetLocalizedResource(), @@ -48,13 +48,13 @@ public NetworkDrivesViewModel(INetworkDrivesService networkDrivesService) public async Task UpdateDrivesAsync() { var unsortedDrives = new List(); - unsortedDrives.Add(drives.Single(x => x is DriveItem o && o.DeviceID == "network-folder")); + unsortedDrives.Add(drives.Single(x => x is SideBarDriveItem o && o.DeviceID == "network-folder")); await foreach (ILocatableFolder item in networkDrivesService.GetDrivesAsync()) { unsortedDrives.Add(item); } - var orderedDrives = unsortedDrives.Cast() + var orderedDrives = unsortedDrives.Cast() .OrderByDescending(o => o.DeviceID == "network-folder") .ThenBy(o => o.Text); diff --git a/src/Files.App/Data/Models/SidebarPinnedModel.cs b/src/Files.App/Data/Models/SidebarPinnedModel.cs index f356f8729dcb..528f833b262f 100644 --- a/src/Files.App/Data/Models/SidebarPinnedModel.cs +++ b/src/Files.App/Data/Models/SidebarPinnedModel.cs @@ -66,17 +66,17 @@ public int IndexOfItem(INavigationControlItem locationItem) } } - public async Task CreateLocationItemFromPathAsync(string path) + public async Task CreateLocationItemFromPathAsync(string path) { var item = await FilesystemTasks.Wrap(() => DriveHelpers.GetRootFromPathAsync(path)); var res = await FilesystemTasks.Wrap(() => StorageFileExtensions.DangerousGetFolderFromPathAsync(path, item)); - LocationItem locationItem; + SideBarLocationItem locationItem; if (string.Equals(path, Constants.UserEnvironmentPaths.RecycleBinPath, StringComparison.OrdinalIgnoreCase)) - locationItem = LocationItem.Create(); + locationItem = SideBarLocationItem.Create(); else { - locationItem = LocationItem.Create(); + locationItem = SideBarLocationItem.Create(); if (path.Equals(Constants.UserEnvironmentPaths.MyComputerPath, StringComparison.OrdinalIgnoreCase)) locationItem.Text = "ThisPC".GetLocalizedResource(); @@ -143,7 +143,7 @@ public async Task AddItemToSidebarAsync(string path) /// Adds the location item to the navigation sidebar /// /// The location item which to save - private void AddLocationItemToSidebar(LocationItem locationItem) + private void AddLocationItemToSidebar(SideBarLocationItem locationItem) { int insertIndex = -1; lock (favoriteList) @@ -177,7 +177,7 @@ public void RemoveStaleSidebarItems() // Remove unpinned items from favoriteList foreach (var childItem in Favorites) { - if (childItem is LocationItem item && !item.IsDefaultLocation && !FavoriteItems.Contains(item.Path)) + if (childItem is SideBarLocationItem item && !item.IsDefaultLocation && !FavoriteItems.Contains(item.Path)) { lock (favoriteList) { diff --git a/src/Files.App/Dialogs/ReorderSidebarItemsDialog.xaml.cs b/src/Files.App/Dialogs/ReorderSidebarItemsDialog.xaml.cs index 4b032415ee6f..0eb719317862 100644 --- a/src/Files.App/Dialogs/ReorderSidebarItemsDialog.xaml.cs +++ b/src/Files.App/Dialogs/ReorderSidebarItemsDialog.xaml.cs @@ -43,7 +43,7 @@ private async void MoveItemAsync(object sender, PointerRoutedEventArgs e) private void ListViewItem_DragStarting(object sender, DragStartingEventArgs e) { - if (sender is not Grid nav || nav.DataContext is not LocationItem) + if (sender is not Grid nav || nav.DataContext is not SideBarLocationItem) return; // Adding the original Location item dragged to the DragEvents data view @@ -53,11 +53,11 @@ private void ListViewItem_DragStarting(object sender, DragStartingEventArgs e) private void ListViewItem_DragOver(object sender, DragEventArgs e) { - if ((sender as Grid)?.DataContext is not LocationItem locationItem) + if ((sender as Grid)?.DataContext is not SideBarLocationItem locationItem) return; var deferral = e.GetDeferral(); - if ((e.DataView.Properties["sourceLocationItem"] as Grid)?.DataContext is LocationItem sourceLocationItem) + if ((e.DataView.Properties["sourceLocationItem"] as Grid)?.DataContext is SideBarLocationItem sourceLocationItem) { DragOver_SetCaptions(sourceLocationItem, locationItem, e); } @@ -65,7 +65,7 @@ private void ListViewItem_DragOver(object sender, DragEventArgs e) deferral.Complete(); } - private void DragOver_SetCaptions(LocationItem senderLocationItem, LocationItem sourceLocationItem, DragEventArgs e) + private void DragOver_SetCaptions(SideBarLocationItem senderLocationItem, SideBarLocationItem sourceLocationItem, DragEventArgs e) { // If the location item is the same as the original dragged item if (sourceLocationItem.CompareTo(senderLocationItem) == 0) @@ -83,10 +83,10 @@ private void DragOver_SetCaptions(LocationItem senderLocationItem, LocationItem private void ListViewItem_Drop(object sender, DragEventArgs e) { - if (sender is not Grid navView || navView.DataContext is not LocationItem locationItem) + if (sender is not Grid navView || navView.DataContext is not SideBarLocationItem locationItem) return; - if ((e.DataView.Properties["sourceLocationItem"] as Grid)?.DataContext is LocationItem sourceLocationItem) + if ((e.DataView.Properties["sourceLocationItem"] as Grid)?.DataContext is SideBarLocationItem sourceLocationItem) ViewModel.SidebarFavoriteItems.Move(ViewModel.SidebarFavoriteItems.IndexOf(sourceLocationItem), ViewModel.SidebarFavoriteItems.IndexOf(locationItem)); } diff --git a/src/Files.App/GlobalUsings.cs b/src/Files.App/GlobalUsings.cs index a7982d7863a1..c62e70b0fb46 100644 --- a/src/Files.App/GlobalUsings.cs +++ b/src/Files.App/GlobalUsings.cs @@ -39,6 +39,7 @@ global using global::Files.App.Data.Behaviors; global using global::Files.App.Data.Commands; global using global::Files.App.Data.Contexts; +global using global::Files.App.Data.Contracts; global using global::Files.App.Data.EventArguments; global using global::Files.App.Data.Exceptions; global using global::Files.App.Data.Factories; @@ -49,6 +50,7 @@ global using global::Files.App.Services; global using global::Files.App.UserControls; global using global::Files.App.UserControls.TabBar; +global using global::Files.App.UserControls.ViewModels.Widgets; global using global::Files.App.ViewModels; global using global::Files.App.ViewModels.UserControls; global using global::Files.App.Views; @@ -76,6 +78,13 @@ global using global::Files.Core.Utils.Cloud; global using global::Files.Core.Utils.CommandLine; +// Files.Core.Storage + +global using global::Files.Core.Storage; +global using global::Files.Core.Storage.Enums; +global using global::Files.Core.Storage.LocatableStorage; +global using global::Files.Core.Storage.NestedStorage; + // Files.Shared global using global::Files.Shared; global using global::Files.Shared.Extensions; diff --git a/src/Files.App/Helpers/Navigation/NavigationHelpers.cs b/src/Files.App/Helpers/Navigation/NavigationHelpers.cs index c390ecd40a43..681f9d06573f 100644 --- a/src/Files.App/Helpers/Navigation/NavigationHelpers.cs +++ b/src/Files.App/Helpers/Navigation/NavigationHelpers.cs @@ -167,7 +167,7 @@ private static async Task UpdateTabInfoAsync(TabBarItem tabItem, object navigati // If localized string is empty use the library name. tabLocationHeader = string.IsNullOrEmpty(libName) ? library.Text : libName; } - else if (WSLDistroManager.TryGetDistro(currentPath, out WslDistroItem? wslDistro) && currentPath.Equals(wslDistro.Path)) + else if (WSLDistroManager.TryGetDistro(currentPath, out SideBarWSLItem? wslDistro) && currentPath.Equals(wslDistro.Path)) { tabLocationHeader = wslDistro.Text; iconSource.ImageSource = new BitmapImage(wslDistro.Icon); @@ -183,8 +183,8 @@ private static async Task UpdateTabInfoAsync(TabBarItem tabItem, object navigati } else if (PathNormalization.NormalizePath(PathNormalization.GetPathRoot(currentPath)) == normalizedCurrentPath) // If path is a drive's root { - var matchingDrive = NetworkDrivesViewModel.Drives.Cast().FirstOrDefault(netDrive => normalizedCurrentPath.Contains(PathNormalization.NormalizePath(netDrive.Path), StringComparison.OrdinalIgnoreCase)); - matchingDrive ??= DrivesViewModel.Drives.Cast().FirstOrDefault(drive => normalizedCurrentPath.Contains(PathNormalization.NormalizePath(drive.Path), StringComparison.OrdinalIgnoreCase)); + var matchingDrive = NetworkDrivesViewModel.Drives.Cast().FirstOrDefault(netDrive => normalizedCurrentPath.Contains(PathNormalization.NormalizePath(netDrive.Path), StringComparison.OrdinalIgnoreCase)); + matchingDrive ??= DrivesViewModel.Drives.Cast().FirstOrDefault(drive => normalizedCurrentPath.Contains(PathNormalization.NormalizePath(drive.Path), StringComparison.OrdinalIgnoreCase)); tabLocationHeader = matchingDrive is not null ? matchingDrive.Text : normalizedCurrentPath; } else diff --git a/src/Files.App/Services/JumpListService.cs b/src/Files.App/Services/JumpListService.cs index 92b8fa1051ad..979ea84f7c11 100644 --- a/src/Files.App/Services/JumpListService.cs +++ b/src/Files.App/Services/JumpListService.cs @@ -117,7 +117,7 @@ private void AddFolder(string path, string group, JumpList instance) if (drive is null) return; - displayName = (drive as DriveItem)?.Text; + displayName = (drive as SideBarDriveItem)?.Text; path += '?'; } diff --git a/src/Files.App/Services/NetworkDrivesService.cs b/src/Files.App/Services/NetworkDrivesService.cs index c4bd426f9aa7..fcb9e0328e0c 100644 --- a/src/Files.App/Services/NetworkDrivesService.cs +++ b/src/Files.App/Services/NetworkDrivesService.cs @@ -44,7 +44,7 @@ public async IAsyncEnumerable GetDrivesAsync() foreach (var item in networkLocations ?? Enumerable.Empty()) { - var networkItem = new DriveItem + var networkItem = new SideBarDriveItem { Text = System.IO.Path.GetFileNameWithoutExtension(item.FileName), Path = item.TargetPath, diff --git a/src/Files.App/Services/RemovableDrivesService.cs b/src/Files.App/Services/RemovableDrivesService.cs index d603f5e254d2..885996a8666d 100644 --- a/src/Files.App/Services/RemovableDrivesService.cs +++ b/src/Files.App/Services/RemovableDrivesService.cs @@ -41,7 +41,7 @@ public async IAsyncEnumerable GetDrivesAsync() using var thumbnail = await DriveHelpers.GetThumbnailAsync(res.Result); var type = DriveHelpers.GetDriveType(drive); var label = DriveHelpers.GetExtendedDriveLabel(drive); - var driveItem = await DriveItem.CreateFromPropertiesAsync(res.Result, drive.Name.TrimEnd('\\'), label, type, thumbnail); + var driveItem = await SideBarDriveItem.CreateFromPropertiesAsync(res.Result, drive.Name.TrimEnd('\\'), label, type, thumbnail); // Don't add here because Google Drive is already displayed under cloud drives if (drive.Name == googleDrivePath || drive.Name == pCloudDrivePath) @@ -62,7 +62,7 @@ public async Task GetPrimaryDriveAsync() public async Task UpdateDrivePropertiesAsync(ILocatableFolder drive) { var rootModified = await FilesystemTasks.Wrap(() => StorageFolder.GetFolderFromPathAsync(drive.Path).AsTask()); - if (rootModified && drive is DriveItem matchingDriveEjected) + if (rootModified && drive is SideBarDriveItem matchingDriveEjected) { _ = MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(() => { diff --git a/src/Files.App/UserControls/Widgets/HomePageWidget.cs b/src/Files.App/UserControls/Widgets/BaseWidgetViewModel.cs similarity index 80% rename from src/Files.App/UserControls/Widgets/HomePageWidget.cs rename to src/Files.App/UserControls/Widgets/BaseWidgetViewModel.cs index c0ddd993940a..377bb9798878 100644 --- a/src/Files.App/UserControls/Widgets/HomePageWidget.cs +++ b/src/Files.App/UserControls/Widgets/BaseWidgetViewModel.cs @@ -2,7 +2,6 @@ // Licensed under the MIT License. See the LICENSE. using Files.App.Helpers.ContextFlyouts; -using Files.Core.Storage; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Controls.Primitives; @@ -11,7 +10,10 @@ namespace Files.App.UserControls.Widgets { - public abstract class HomePageWidget : UserControl + /// + /// Represents base ViewModel for widget ViewModels. + /// + public abstract class BaseWidgetViewModel : UserControl { // Dependency injections @@ -21,18 +23,18 @@ public abstract class HomePageWidget : UserControl // Fields - protected string? FlyoutItemPath; + protected string? _flyoutItemPath; // Commands - public ICommand? RemoveRecentItemCommand { get; protected set; } - public ICommand? ClearAllItemsCommand { get; protected set; } - public ICommand? OpenFileLocationCommand { get; protected set; } - public ICommand? OpenInNewTabCommand { get; protected set; } - public ICommand? OpenInNewWindowCommand { get; protected set; } - public ICommand? OpenPropertiesCommand { get; protected set; } - public ICommand? PinToFavoritesCommand { get; protected set; } - public ICommand? UnpinFromFavoritesCommand { get; protected set; } + protected ICommand? RemoveRecentItemCommand { get; set; } + protected ICommand? ClearAllItemsCommand { get; set; } + protected ICommand? OpenFileLocationCommand { get; set; } + protected ICommand? OpenInNewTabCommand { get; set; } + protected ICommand? OpenInNewWindowCommand { get; set; } + protected ICommand? OpenPropertiesCommand { get; set; } + protected ICommand? PinToFavoritesCommand { get; set; } + protected ICommand? UnpinFromFavoritesCommand { get; set; } // Events @@ -61,7 +63,7 @@ public void Button_RightTapped(object sender, RightTappedRoutedEventArgs e) itemContextMenuFlyout.Opening += (sender, e) => App.LastOpenedFlyout = sender as CommandBarFlyout; itemContextMenuFlyout.Closed += (sender, e) => OnRightClickedItemChanged(null, null); - FlyoutItemPath = item.Path; + _flyoutItemPath = item.Path; // Notify of the change on right clicked item OnRightClickedItemChanged(item, itemContextMenuFlyout); @@ -82,7 +84,7 @@ public void Button_RightTapped(object sender, RightTappedRoutedEventArgs e) itemContextMenuFlyout.ShowAt(widgetCardItem, new() { Position = e.GetPosition(widgetCardItem) }); // Load shell menu items - _ = ShellContextmenuHelper.LoadShellMenuItemsAsync(FlyoutItemPath, itemContextMenuFlyout); + _ = ShellContextmenuHelper.LoadShellMenuItemsAsync(_flyoutItemPath, itemContextMenuFlyout); e.Handled = true; } diff --git a/src/Files.App/UserControls/Widgets/DrivesWidget.xaml b/src/Files.App/UserControls/Widgets/DrivesWidget.xaml index 086bbf5a898d..e8f5258f354d 100644 --- a/src/Files.App/UserControls/Widgets/DrivesWidget.xaml +++ b/src/Files.App/UserControls/Widgets/DrivesWidget.xaml @@ -1,9 +1,10 @@ - - +