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: Use view models in Widgets #14926

Merged
merged 20 commits into from May 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/Files.App/Data/Contexts/HomePage/HomePageContext.cs
Expand Up @@ -7,7 +7,7 @@

namespace Files.App.Data.Contexts
{
internal sealed class HomePageContext : ObservableObject, IHomePageContext
public sealed class HomePageContext : ObservableObject, IHomePageContext
{
private static readonly ImmutableList<WidgetFileTagCardItem> emptyTaggedItems = Enumerable.Empty<WidgetFileTagCardItem>().ToImmutableList();

Expand All @@ -29,7 +29,7 @@ public IReadOnlyList<WidgetFileTagCardItem> SelectedTaggedItems
public HomePageContext()
{
BaseWidgetViewModel.RightClickedItemChanged += HomePageWidget_RightClickedItemChanged;
FileTagsWidget.SelectedTaggedItemsChanged += FileTagsWidget_SelectedTaggedItemsChanged;
FileTagsWidgetViewModel.SelectedTaggedItemsChanged += FileTagsWidget_SelectedTaggedItemsChanged;
}

private void FileTagsWidget_SelectedTaggedItemsChanged(object? sender, IEnumerable<WidgetFileTagCardItem> e)
Expand Down
2 changes: 1 addition & 1 deletion src/Files.App/Data/Contexts/HomePage/IHomePageContext.cs
Expand Up @@ -5,7 +5,7 @@

namespace Files.App.Data.Contexts
{
internal interface IHomePageContext
public interface IHomePageContext
{
/// <summary>
/// The last right clicked item
Expand Down
1 change: 0 additions & 1 deletion src/Files.App/Data/Contracts/IFileTagsService.cs
@@ -1,7 +1,6 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

using Files.App.ViewModels.FileTags;
using Files.Core.Storage.LocatableStorage;

namespace Files.App.Data.Contracts
Expand Down
2 changes: 1 addition & 1 deletion src/Files.App/Data/Contracts/IWidgetViewModel.cs
Expand Up @@ -17,7 +17,7 @@ public interface IWidgetViewModel : IDisposable

bool ShowMenuFlyout { get; }

MenuFlyoutItem MenuFlyoutItem { get; }
MenuFlyoutItem? MenuFlyoutItem { get; }

Task RefreshWidgetAsync();
}
Expand Down
10 changes: 0 additions & 10 deletions src/Files.App/Data/EventArguments/QuickAccessCardEventArgs.cs
Expand Up @@ -3,16 +3,6 @@

namespace Files.App.Data.EventArguments
{
public sealed class QuickAccessCardEventArgs : EventArgs
{
public LocationItem? Item { get; set; }
}

public sealed class QuickAccessCardInvokedEventArgs : EventArgs
{
public string? Path { get; set; }
}

public sealed class ModifyQuickAccessEventArgs : EventArgs
{
public string[]? Paths { get; set; }
Expand Down
12 changes: 10 additions & 2 deletions src/Files.App/Data/Factories/ShellContextFlyoutHelper.cs
Expand Up @@ -341,10 +341,14 @@ async Task InvokeShellMenuItemAsync(ContextMenu contextMenu, object? tag)
OpacityIconStyle = "ColorIconOpenWith",
};
var (_, openWithItems) = ContextFlyoutModelToElementHelper.GetAppBarItemsFromModel([openWithItem]);
var index = 0;
var placeholder = itemContextMenuFlyout.SecondaryCommands.FirstOrDefault(x => Equals((x as AppBarButton)?.Tag, "OpenWithPlaceholder")) as AppBarButton;
if (placeholder is not null)
{
placeholder.Visibility = Visibility.Collapsed;
itemContextMenuFlyout.SecondaryCommands.Insert(0, openWithItems.FirstOrDefault());
index = itemContextMenuFlyout.SecondaryCommands.IndexOf(placeholder);
}
itemContextMenuFlyout.SecondaryCommands.Insert(index, openWithItems.FirstOrDefault());
}

// Add items to sendto dropdown
Expand All @@ -353,10 +357,14 @@ async Task InvokeShellMenuItemAsync(ContextMenu contextMenu, object? tag)
await sendToItem.LoadSubMenuAction();

var (_, sendToItems) = ContextFlyoutModelToElementHelper.GetAppBarItemsFromModel([sendToItem]);
var index = 1;
var placeholder = itemContextMenuFlyout.SecondaryCommands.FirstOrDefault(x => Equals((x as AppBarButton)?.Tag, "SendToPlaceholder")) as AppBarButton;
if (placeholder is not null)
{
placeholder.Visibility = Visibility.Collapsed;
itemContextMenuFlyout.SecondaryCommands.Insert(1, sendToItems.FirstOrDefault());
index = itemContextMenuFlyout.SecondaryCommands.IndexOf(placeholder);
}
itemContextMenuFlyout.SecondaryCommands.Insert(index, sendToItems.FirstOrDefault());
}

// Add items to shell submenu
Expand Down
9 changes: 7 additions & 2 deletions src/Files.App/Data/Items/WidgetContainerItem.cs
Expand Up @@ -17,8 +17,12 @@ public sealed class WidgetContainerItem : ObservableObject, IDisposable

// Properties

public IWidgetViewModel _WidgetItemModel;
public IWidgetViewModel WidgetItemModel
=> WidgetControl as IWidgetViewModel;
{
get => _WidgetItemModel;
set => SetProperty(ref _WidgetItemModel, value);
}

public string WidgetAutomationProperties
=> WidgetItemModel.AutomationProperties;
Expand Down Expand Up @@ -48,11 +52,12 @@ public bool IsExpanded

// Constructor

public WidgetContainerItem(object widgetControl, Action<bool> expanderValueChangedCallback, Func<bool> expanderValueRequestedCallback)
public WidgetContainerItem(object widgetControl, IWidgetViewModel widgetItemModel, Action<bool> expanderValueChangedCallback, Func<bool> expanderValueRequestedCallback)
{
_expanderValueChangedCallback = expanderValueChangedCallback;
_expanderValueRequestedCallback = expanderValueRequestedCallback;

WidgetItemModel = widgetItemModel;
WidgetControl = widgetControl;
}

Expand Down
13 changes: 6 additions & 7 deletions src/Files.App/Data/Items/WidgetFileTagCardItem.cs
Expand Up @@ -9,14 +9,14 @@ namespace Files.App.Data.Items
{
public sealed partial class WidgetFileTagCardItem : WidgetCardItem
{
// Dependency injections

private IContentPageContext ContentPageContext { get; } = Ioc.Default.GetRequiredService<IContentPageContext>();

// 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<string, Task> _openAction;

// Properties

public bool IsFolder
Expand Down Expand Up @@ -47,10 +47,9 @@ public override string Path

public ICommand ClickCommand { get; }

public WidgetFileTagCardItem(IStorable associatedStorable, Func<string, Task> openAction, IImage? icon)
public WidgetFileTagCardItem(IStorable associatedStorable, IImage? icon)
{
_associatedStorable = associatedStorable;
_openAction = openAction;
_Icon = icon;
_Name = associatedStorable.Name;
_Path = associatedStorable.TryGetPath();
Expand All @@ -61,7 +60,7 @@ public WidgetFileTagCardItem(IStorable associatedStorable, Func<string, Task> op

private Task ClickAsync()
{
return _openAction(_associatedStorable.Id);
return NavigationHelpers.OpenPath(_associatedStorable.Id, ContentPageContext.ShellPage!);
}
}
}
20 changes: 9 additions & 11 deletions src/Files.App/Data/Items/WidgetFileTagsContainerItem.cs
Expand Up @@ -13,11 +13,10 @@ public sealed partial class WidgetFileTagsContainerItem : ObservableObject, IAsy
private readonly IFileTagsService FileTagsService = Ioc.Default.GetRequiredService<IFileTagsService>();
private readonly IImageService ImageService = Ioc.Default.GetRequiredService<IImageService>();
private readonly ICommandManager Commands = Ioc.Default.GetRequiredService<ICommandManager>();
private IContentPageContext ContentPageContext { get; } = Ioc.Default.GetRequiredService<IContentPageContext>();

private readonly string _tagUid;

private readonly Func<string, Task> _openAction;

// Properties

public ObservableCollection<WidgetFileTagCardItem> Tags { get; }
Expand Down Expand Up @@ -46,11 +45,10 @@ public sealed partial class WidgetFileTagsContainerItem : ObservableObject, IAsy
public ICommand ViewMoreCommand { get; }
public ICommand OpenAllCommand { get; }

public WidgetFileTagsContainerItem(string tagUid, Func<string, Task> openAction)
public WidgetFileTagsContainerItem(string tagUid)
{
_tagUid = tagUid;
_openAction = openAction;
Tags = [];
Tags = new();

ViewMoreCommand = new AsyncRelayCommand(ViewMore);
OpenAllCommand = new AsyncRelayCommand(OpenAll);
Expand All @@ -59,21 +57,21 @@ public WidgetFileTagsContainerItem(string tagUid, Func<string, Task> openAction)
/// <inheritdoc/>
public async Task InitAsync(CancellationToken cancellationToken = default)
{
await foreach (var item in FileTagsService.GetItemsForTagAsync(_tagUid, cancellationToken))
await foreach (var item in FileTagsService.GetItemsForTagAsync(_tagUid))
{
var icon = await ImageService.GetIconAsync(item.Storable, cancellationToken);
Tags.Add(new(item.Storable, _openAction, icon));
var icon = await ImageService.GetIconAsync(item.Storable, default);
Tags.Add(new(item.Storable, icon));
}
}

private Task ViewMore()
private Task<bool> ViewMore()
{
return _openAction($"tag:{Name}");
return NavigationHelpers.OpenPath($"tag:{Name}", ContentPageContext.ShellPage!);
}

private Task OpenAll()
{
SelectedTagChanged?.Invoke(this, new SelectedTagChangedEventArgs(Tags.Select(tag => (tag.Path, tag.IsFolder))));
SelectedTagChanged?.Invoke(this, new(Tags.Select(tag => (tag.Path, tag.IsFolder))));

return Commands.OpenAllTaggedItems.ExecuteAsync();
}
Expand Down
@@ -1,7 +1,7 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

namespace Files.App.ViewModels.FileTags
namespace Files.App.Data.Models
{
public sealed class ListedTagViewModel : ObservableObject
{
Expand Down
Expand Up @@ -3,7 +3,7 @@

using System.Text.Json.Serialization;

namespace Files.App.ViewModels.FileTags
namespace Files.App.Data.Models
{
[Serializable]
public sealed partial class TagViewModel : ObservableObject
Expand Down
3 changes: 1 addition & 2 deletions src/Files.App/GlobalUsings.cs
Expand Up @@ -64,8 +64,7 @@
global using global::Files.App.ViewModels.Dialogs;
global using global::Files.App.ViewModels.Dialogs.AddItemDialog;
global using global::Files.App.ViewModels.Dialogs.FileSystemDialog;
global using global::Files.App.ViewModels.FileTags;
global using global::Files.App.ViewModels.Widgets;
global using global::Files.App.ViewModels.UserControls.Widgets;
global using global::Files.App.Utils.CommandLine;

// Files.Core.Storage
Expand Down
4 changes: 4 additions & 0 deletions src/Files.App/Helpers/Application/AppLifecycleHelper.cs
Expand Up @@ -199,6 +199,10 @@ public static IHost ConfigureHost()
.AddSingleton<StatusCenterViewModel>()
.AddSingleton<AppearanceViewModel>()
.AddTransient<HomeViewModel>()
.AddSingleton<QuickAccessWidgetViewModel>()
.AddSingleton<DrivesWidgetViewModel>()
.AddSingleton<FileTagsWidgetViewModel>()
.AddSingleton<RecentFilesWidgetViewModel>()
// Utilities
.AddSingleton<QuickAccessManager>()
.AddSingleton<StorageHistoryWrapper>()
Expand Down
1 change: 0 additions & 1 deletion src/Files.App/Services/Settings/FileTagsSettingsService.cs
Expand Up @@ -7,7 +7,6 @@
using Files.App.Utils.Serialization;
using Files.App.Utils.Serialization.Implementation;
using Files.App.Services.Settings;
using Files.App.ViewModels.FileTags;
using Microsoft.Extensions.Logging;
using System.IO;
using Windows.Storage;
Expand Down
2 changes: 0 additions & 2 deletions src/Files.App/Services/Settings/IFileTagsSettingsService.cs
@@ -1,8 +1,6 @@
// Copyright (c) 2024 Files Community
// Licensed under the MIT License. See the LICENSE.

using Files.App.ViewModels.FileTags;

namespace Files.App.Services.Settings
{
public interface IFileTagsSettingsService : IBaseSettingsService
Expand Down
6 changes: 0 additions & 6 deletions src/Files.App/Strings/en-US/Resources.resw
Expand Up @@ -1698,12 +1698,6 @@
<data name="CredentialDialogUserName.PlaceholderText" xml:space="preserve">
<value>UserName</value>
</data>
<data name="DrivesWidgetAutomationProperties.Name" xml:space="preserve">
<value>Drives widget</value>
</data>
<data name="RecentFilesWidgetAutomationProperties.Name" xml:space="preserve">
<value>Recent Files widget</value>
</data>
yaira2 marked this conversation as resolved.
Show resolved Hide resolved
<data name="NoSearchResultsFound" xml:space="preserve">
<value>No items found</value>
</data>
Expand Down
11 changes: 3 additions & 8 deletions src/Files.App/UserControls/Widgets/DrivesWidget.xaml
@@ -1,22 +1,17 @@
<!-- Copyright (c) 2024 Files Community. Licensed under the MIT License. See the LICENSE. -->
<local:BaseWidgetViewModel
<UserControl
x:Class="Files.App.UserControls.Widgets.DrivesWidget"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:dataitems="using:Files.App.Data.Items"
xmlns:helpers="using:Files.App.Helpers"
xmlns:local="using:Files.App.UserControls.Widgets"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
DataContext="{x:Bind ViewModel, Mode=OneWay}"
mc:Ignorable="d">

<Grid>
<ItemsRepeater
x:Name="CardsList"
HorizontalAlignment="Stretch"
VerticalAlignment="Top"
ItemsSource="{x:Bind local:DrivesWidget.ItemsAdded, Mode=OneWay}">
<ItemsRepeater ItemsSource="{x:Bind ViewModel.Items, Mode=OneWay}">

<ItemsRepeater.Layout>
<UniformGridLayout
Expand Down Expand Up @@ -138,4 +133,4 @@

</ItemsRepeater>
</Grid>
</local:BaseWidgetViewModel>
</UserControl>