Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code Quality: Introduced view models to widgets #14723

Closed
wants to merge 35 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
ba49c61
Initial commit
0x5bfa Feb 13, 2024
d614253
Moved almost all code behinds to respective ViewModels
0x5bfa Feb 13, 2024
2d54e70
Removed all events hooked by HomeViewModel
0x5bfa Feb 13, 2024
0640e86
Fix displaying issues 1
0x5bfa Feb 13, 2024
93f6572
Fixed quick access display issue
0x5bfa Feb 14, 2024
69dd264
Move xaml resources out from home page xaml
0x5bfa Feb 14, 2024
abf4f5c
Brush up
0x5bfa Feb 14, 2024
0e631eb
Removed IAsyncInitialize
0x5bfa Feb 15, 2024
11f2eeb
Replace drive card item context flyout with RichCommand
0x5bfa Feb 15, 2024
c6b1044
Remove unused command methods
0x5bfa Feb 15, 2024
e63d620
Update
0x5bfa Feb 15, 2024
5c43dae
Replace all with RichCommand
0x5bfa Feb 15, 2024
ce5f1e5
Removed unused command methods
0x5bfa Feb 15, 2024
b8b94db
Removed unnecessary abstraction
0x5bfa Feb 15, 2024
5430efd
Simplify initialization
0x5bfa Feb 15, 2024
a698067
Fixed error
0x5bfa Feb 15, 2024
32f0292
Add support invokation from Home to RichCommands 1
0x5bfa Feb 15, 2024
7717abd
Remove widget-related code from Sidebar
0x5bfa Feb 15, 2024
6bceda8
Expand the useage of pin/unpin to/from favorites
0x5bfa Feb 15, 2024
4d21319
FormatDriveAction activated
0x5bfa Feb 15, 2024
d125d77
Added EjectDriveAction
0x5bfa Feb 15, 2024
a52146e
FormatDriveAction activated
0x5bfa Feb 15, 2024
88b7a73
OpenProperties activated
0x5bfa Feb 15, 2024
d32eaf2
Revert UI change
0x5bfa Feb 15, 2024
73f2972
Added RemoveRecentItem & ClearRecentItem
0x5bfa Feb 17, 2024
902636f
Activated Clear/RemoveRecentItem actions
0x5bfa Feb 17, 2024
fde60a0
Await OpenShortcutLocation
0x5bfa Feb 17, 2024
6c355f0
Brush up
0x5bfa Feb 17, 2024
6dc741f
Merge remote-tracking branch 'upstream/main' into 5bfa/Add-WidgetView…
0x5bfa Feb 17, 2024
5d99aad
Simplify
0x5bfa Feb 17, 2024
8262a52
Added cacellation token and semaphore
0x5bfa Feb 17, 2024
576c8e0
Revert
0x5bfa Feb 17, 2024
2e9300b
Check if collection is empty
0x5bfa Feb 17, 2024
e3c659d
Update
0x5bfa Feb 17, 2024
f39971a
Update & fix
0x5bfa Feb 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions src/Files.App/Actions/ActionExecutableType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Actions
{
/// <summary>
/// Defines constants that specifies what context the action can be executed through.
/// </summary>
public enum ActionExecutableType
{
/// <summary>
/// The action is executable through <see cref="IDisplayPageContext"/>.
/// </summary>
DisplayPageContext,

/// <summary>
/// The action is executable through <see cref="IHomePageContext"/>.
/// </summary>
HomePageContext,

/// <summary>
/// The action is executable through <see cref="ISidebarContext"/>.
/// </summary>
SidebarContext
}
}
8 changes: 5 additions & 3 deletions src/Files.App/Actions/Content/RefreshItemsAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@ public RefreshItemsAction()
context.PropertyChanged += Context_PropertyChanged;
}

public async Task ExecuteAsync()
public Task ExecuteAsync()
{
if (context.ShellPage is null)
return;
return Task.CompletedTask;

await context.ShellPage.Refresh_Click();
context.ShellPage.ToolbarViewModel.InvokeRefreshRequested();

return Task.CompletedTask;
}

private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
Expand Down
71 changes: 42 additions & 29 deletions src/Files.App/Actions/Favorites/PinItemAction.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,15 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.

using Files.App.Services;
using Files.App.UserControls.Widgets;
using Windows.Storage;

namespace Files.App.Actions
{
internal class PinItemAction : ObservableObject, IAction
{
private readonly IContentPageContext context;
private IContentPageContext ContentPageContext { get; } = Ioc.Default.GetRequiredService<IContentPageContext>();
private IQuickAccessService QuickAccessService { get; } = Ioc.Default.GetRequiredService<IQuickAccessService>();
private IHomePageContext HomePageContext { get; } = Ioc.Default.GetRequiredService<IHomePageContext>();

private readonly IQuickAccessService service;
private ActionExecutableType ExecutableType { get; set; }

public string Label
=> "PinToFavorites".GetLocalizedResource();
Expand All @@ -27,44 +25,59 @@ public bool IsExecutable

public PinItemAction()
{
context = Ioc.Default.GetRequiredService<IContentPageContext>();
service = Ioc.Default.GetRequiredService<IQuickAccessService>();

context.PropertyChanged += Context_PropertyChanged;
ContentPageContext.PropertyChanged += ContentPageContext_PropertyChanged;
App.QuickAccessManager.UpdateQuickAccessWidget += QuickAccessManager_DataChanged;
}

public async Task ExecuteAsync()
{
if (context.HasSelection)
{
var items = context.SelectedItems.Select(x => x.ItemPath).ToArray();

await service.PinToSidebarAsync(items);
}
else if (context.Folder is not null)
switch (ExecutableType)
{
await service.PinToSidebarAsync(context.Folder.ItemPath);
case ActionExecutableType.DisplayPageContext:
{
if (ContentPageContext.HasSelection)
{
var items = ContentPageContext.SelectedItems.Select(x => x.ItemPath).ToArray();
await QuickAccessService.PinToSidebarAsync(items);
}
else if (ContentPageContext.Folder is not null)
{
await QuickAccessService.PinToSidebarAsync(ContentPageContext.Folder.ItemPath);
}
break;
}
case ActionExecutableType.HomePageContext:
{
await QuickAccessService.PinToSidebarAsync(HomePageContext.RightClickedItem!.Path ?? string.Empty);
break;
}
}
}

private bool GetIsExecutable()
{
string[] favorites = App.QuickAccessManager.Model.FavoriteItems.ToArray();
var favorites = App.QuickAccessManager.Model.FavoriteItems;

return context.HasSelection
? context.SelectedItems.All(IsPinnable)
: context.Folder is not null && IsPinnable(context.Folder);
var executableInDisplayPage =
ContentPageContext.HasSelection
? ContentPageContext.SelectedItems.All(x => !favorites.Contains(x.ItemPath)) && ContentPageContext.SelectedItems.All(x => x.IsFolder)
: ContentPageContext.Folder is not null && !favorites.Contains(ContentPageContext.Folder.ItemPath);

bool IsPinnable(ListedItem item)
{
return
item.PrimaryItemAttribute is StorageItemTypes.Folder &&
!favorites.Contains(item.ItemPath);
}
if (executableInDisplayPage)
ExecutableType = ActionExecutableType.DisplayPageContext;

// TODO: Check if the item is folder
var executableInHomePage =
HomePageContext.IsAnyItemRightClicked &&
!favorites.Contains(HomePageContext.RightClickedItem!.Path ?? string.Empty);

if (executableInHomePage)
ExecutableType = ActionExecutableType.HomePageContext;

return executableInDisplayPage || executableInHomePage;
}

private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
private void ContentPageContext_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
Expand Down
67 changes: 42 additions & 25 deletions src/Files.App/Actions/Favorites/UnpinItemAction.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.

using Files.App.Services;
using Files.App.UserControls.Widgets;

namespace Files.App.Actions
{
internal class UnpinItemAction : ObservableObject, IAction
{
private readonly IContentPageContext context;
private IContentPageContext ContentPageContext { get; } = Ioc.Default.GetRequiredService<IContentPageContext>();
private IQuickAccessService QuickAccessService { get; } = Ioc.Default.GetRequiredService<IQuickAccessService>();
private IHomePageContext HomePageContext { get; } = Ioc.Default.GetRequiredService<IHomePageContext>();

private readonly IQuickAccessService service;
private ActionExecutableType ExecutableType { get; set; }

public string Label
=> "UnpinFromFavorites".GetLocalizedResource();
Expand All @@ -26,41 +25,59 @@ public bool IsExecutable

public UnpinItemAction()
{
context = Ioc.Default.GetRequiredService<IContentPageContext>();
service = Ioc.Default.GetRequiredService<IQuickAccessService>();

context.PropertyChanged += Context_PropertyChanged;
ContentPageContext.PropertyChanged += ContentPageContext_PropertyChanged;
App.QuickAccessManager.UpdateQuickAccessWidget += QuickAccessManager_DataChanged;
}

public async Task ExecuteAsync()
{
if (context.HasSelection)
switch (ExecutableType)
{
var items = context.SelectedItems.Select(x => x.ItemPath).ToArray();
await service.UnpinFromSidebarAsync(items);
}
else if (context.Folder is not null)
{
await service.UnpinFromSidebarAsync(context.Folder.ItemPath);
case ActionExecutableType.DisplayPageContext:
{
if (ContentPageContext.HasSelection)
{
var items = ContentPageContext.SelectedItems.Select(x => x.ItemPath).ToArray();
await QuickAccessService.UnpinFromSidebarAsync(items);
}
else if (ContentPageContext.Folder is not null)
{
await QuickAccessService.UnpinFromSidebarAsync(ContentPageContext.Folder.ItemPath);
}
break;
}
case ActionExecutableType.HomePageContext:
{
await QuickAccessService.UnpinFromSidebarAsync(HomePageContext.RightClickedItem!.Path ?? string.Empty);
break;
}
}
}

private bool GetIsExecutable()
{
string[] favorites = App.QuickAccessManager.Model.FavoriteItems.ToArray();
var favorites = App.QuickAccessManager.Model.FavoriteItems;

return context.HasSelection
? context.SelectedItems.All(IsPinned)
: context.Folder is not null && IsPinned(context.Folder);
var executableInDisplayPage =
ContentPageContext.HasSelection
? ContentPageContext.SelectedItems.All(x => favorites.Contains(x.ItemPath)) && ContentPageContext.SelectedItems.All(x => x.IsFolder)
: ContentPageContext.Folder is not null && favorites.Contains(ContentPageContext.Folder.ItemPath);

bool IsPinned(ListedItem item)
{
return favorites.Contains(item.ItemPath);
}
if (executableInDisplayPage)
ExecutableType = ActionExecutableType.DisplayPageContext;

// TODO: Check if the item is folder
var executableInHomePage =
HomePageContext.IsAnyItemRightClicked &&
favorites.Contains(HomePageContext.RightClickedItem!.Path ?? string.Empty);

if (executableInHomePage)
ExecutableType = ActionExecutableType.HomePageContext;

return executableInDisplayPage || executableInHomePage;
}

private void Context_PropertyChanged(object? sender, PropertyChangedEventArgs e)
private void ContentPageContext_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
Expand Down
51 changes: 51 additions & 0 deletions src/Files.App/Actions/FileSystem/ClearRecentItemAction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Actions
{
internal class ClearRecentItemAction : ObservableObject, IAction
{
private IContentPageContext ContentPageContext { get; } = Ioc.Default.GetRequiredService<IContentPageContext>();
private IHomePageContext HomePageContext { get; } = Ioc.Default.GetRequiredService<IHomePageContext>();

public string Label
=> "RecentItemClearAll/Text".GetLocalizedResource();

public string Description
=> "RecentItemClearAll/Text".GetLocalizedResource();

public bool IsExecutable
=> GetIsExecutable();

public ClearRecentItemAction()
{
ContentPageContext.PropertyChanged += ContentPageContext_PropertyChanged;
}

public Task ExecuteAsync()
{
try
{
App.RecentItemsManager.ClearRecentItems();
}
catch (Exception) { }

return Task.CompletedTask;
}

private bool GetIsExecutable()
{
var executableInHomePage =
HomePageContext.IsAnyItemRightClicked &&
HomePageContext.RightClickedItem is WidgetRecentItem;

return executableInHomePage;
}

public void ContentPageContext_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName is nameof(IContentPageContext.HasItem))
OnPropertyChanged(nameof(IsExecutable));
}
}
}
52 changes: 52 additions & 0 deletions src/Files.App/Actions/FileSystem/EjectDriveAction.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.Actions
{
internal class EjectDriveAction : ObservableObject, IAction
{
private IContentPageContext ContentPageContext { get; } = Ioc.Default.GetRequiredService<IContentPageContext>();
private IHomePageContext HomePageContext { get; } = Ioc.Default.GetRequiredService<IHomePageContext>();
private DrivesViewModel DrivesViewModel { get; } = Ioc.Default.GetRequiredService<DrivesViewModel>();

public string Label
=> "EjectDrive".GetLocalizedResource();

public string Description
=> "EjectDrive".GetLocalizedResource();

public bool IsExecutable
=> GetIsExecutable();

public EjectDriveAction()
{
ContentPageContext.PropertyChanged += ContentPageContext_PropertyChanged;
}

public async Task ExecuteAsync()
{
var result = await DriveHelpers.EjectDeviceAsync(HomePageContext.RightClickedItem?.Path ?? string.Empty);

if (HomePageContext.RightClickedItem is WidgetDriveCardItem driveCardItem &&
driveCardItem.Item is DriveItem driveItem)
await UIHelpers.ShowDeviceEjectResultAsync(driveItem.Type, result);
}

private bool GetIsExecutable()
{
var executableInHomePage =
HomePageContext.IsAnyItemRightClicked &&
HomePageContext.RightClickedItem is WidgetDriveCardItem driveCardItem &&
driveCardItem.Item is DriveItem driveItem &&
driveItem.MenuOptions.ShowEjectDevice;

return executableInHomePage;
}

public void ContentPageContext_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
if (e.PropertyName is nameof(IContentPageContext.HasItem))
OnPropertyChanged(nameof(IsExecutable));
}
}
}
Loading
Loading