Skip to content

Code Quality: Removed WidgetsListControl #13941

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

Merged
merged 5 commits into from
Nov 29, 2023
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Files.App/Helpers/Application/AppLifecycleHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ public static IHost ConfigureHost()
.AddSingleton<NetworkDrivesViewModel>()
.AddSingleton<StatusCenterViewModel>()
.AddSingleton<AppearanceViewModel>()
.AddTransient<HomeViewModel>()
// Utilities
.AddSingleton<QuickAccessManager>()
.AddSingleton<StorageHistoryWrapper>()
Expand Down
2 changes: 1 addition & 1 deletion src/Files.App/UserControls/Widgets/DrivesWidget.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public async Task LoadCardThumbnailAsync()
public int CompareTo(DriveCardItem? other) => Item.Path.CompareTo(other?.Item?.Path);
}

public sealed partial class DrivesWidget : HomePageWidget, IWidgetItemModel, INotifyPropertyChanged
public sealed partial class DrivesWidget : HomePageWidget, IWidgetItem, INotifyPropertyChanged
{
public IUserSettingsService userSettingsService { get; } = Ioc.Default.GetRequiredService<IUserSettingsService>();

Expand Down
2 changes: 1 addition & 1 deletion src/Files.App/UserControls/Widgets/FileTagsWidget.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

namespace Files.App.UserControls.Widgets
{
public sealed partial class FileTagsWidget : HomePageWidget, IWidgetItemModel
public sealed partial class FileTagsWidget : HomePageWidget, IWidgetItem
{
private readonly IUserSettingsService userSettingsService;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public async Task LoadCardThumbnailAsync()
}
}

public sealed partial class QuickAccessWidget : HomePageWidget, IWidgetItemModel, INotifyPropertyChanged
public sealed partial class QuickAccessWidget : HomePageWidget, IWidgetItem, INotifyPropertyChanged
{
public IUserSettingsService userSettingsService { get; } = Ioc.Default.GetRequiredService<IUserSettingsService>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

namespace Files.App.UserControls.Widgets
{
public sealed partial class RecentFilesWidget : HomePageWidget, IWidgetItemModel, INotifyPropertyChanged
public sealed partial class RecentFilesWidget : HomePageWidget, IWidgetItem, INotifyPropertyChanged
{
public delegate void RecentFilesOpenLocationInvokedEventHandler(object sender, PathNavigationEventArgs e);

Expand Down
510 changes: 0 additions & 510 deletions src/Files.App/UserControls/Widgets/WidgetsListControl.xaml

This file was deleted.

26 changes: 0 additions & 26 deletions src/Files.App/UserControls/Widgets/WidgetsListControl.xaml.cs

This file was deleted.

11 changes: 4 additions & 7 deletions src/Files.App/Utils/Widgets/WidgetsHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@

using Files.App.UserControls.Widgets;
using Files.App.ViewModels.Widgets;
using Files.Core.Services.Settings;
using System.Collections.Generic;

namespace Files.App.Helpers
{
public static class WidgetsHelpers
{
public static TWidget? TryGetWidget<TWidget>(IGeneralSettingsService generalSettingsService, WidgetsListControlViewModel widgetsViewModel, out bool shouldReload, TWidget? defaultValue = default) where TWidget : IWidgetItemModel, new()
public static TWidget? TryGetWidget<TWidget>(IGeneralSettingsService generalSettingsService, HomeViewModel widgetsViewModel, out bool shouldReload, TWidget? defaultValue = default) where TWidget : IWidgetItem, new()
{
bool canAddWidget = widgetsViewModel.CanAddWidget(typeof(TWidget).Name);
bool isWidgetSettingEnabled = TryGetIsWidgetSettingEnabled<TWidget>(generalSettingsService);
Expand Down Expand Up @@ -38,7 +36,7 @@ public static class WidgetsHelpers
return (defaultValue);
}

public static bool TryGetIsWidgetSettingEnabled<TWidget>(IGeneralSettingsService generalSettingsService) where TWidget : IWidgetItemModel
public static bool TryGetIsWidgetSettingEnabled<TWidget>(IGeneralSettingsService generalSettingsService) where TWidget : IWidgetItem
{
if (typeof(TWidget) == typeof(QuickAccessWidget))
{
Expand All @@ -57,8 +55,7 @@ public static bool TryGetIsWidgetSettingEnabled<TWidget>(IGeneralSettingsService
return generalSettingsService.ShowRecentFilesWidget;
}

// A custom widget it is - TWidget implements ICustomWidgetItemModel
return typeof(ICustomWidgetItemModel).IsAssignableFrom(typeof(TWidget)); // Return true for custom widgets - they're always enabled
return false;
}
}
}
}
104 changes: 90 additions & 14 deletions src/Files.App/ViewModels/HomeViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,112 @@ namespace Files.App.ViewModels
{
public class HomeViewModel : ObservableObject, IDisposable
{
private readonly WidgetsListControlViewModel widgetsViewModel;
public ObservableCollection<WidgetItem> WidgetItems { get; } = new();

private IShellPage associatedInstance;
public ICommand HomePageLoadedCommand { get; }

public event EventHandler<RoutedEventArgs> YourHomeLoadedInvoked;
public event EventHandler<RoutedEventArgs>? HomePageLoadedInvoked;
public event EventHandler? WidgetListRefreshRequestedInvoked;

public ICommand YourHomeLoadedCommand { get; private set; }
public HomeViewModel()
{
HomePageLoadedCommand = new RelayCommand<RoutedEventArgs>(ExecuteHomePageLoadedCommand);
}

private void ExecuteHomePageLoadedCommand(RoutedEventArgs? e)
{
HomePageLoadedInvoked?.Invoke(this, e!);
}

public void RefreshWidgetList()
{
for (int i = 0; i < WidgetItems.Count; i++)
{
if (!WidgetItems[i].WidgetItemModel.IsWidgetSettingEnabled)
{
RemoveWidgetAt(i);
}
}

WidgetListRefreshRequestedInvoked?.Invoke(this, EventArgs.Empty);
}

public bool AddWidget(WidgetItem widgetModel)
{
return InsertWidget(widgetModel, WidgetItems.Count + 1);
}

public HomeViewModel(WidgetsListControlViewModel widgetsViewModel, IShellPage associatedInstance)
public bool InsertWidget(WidgetItem widgetModel, int atIndex)
{
this.widgetsViewModel = widgetsViewModel;
this.associatedInstance = associatedInstance;
// The widget must not be null and must implement IWidgetItemModel
if (widgetModel.WidgetItemModel is not IWidgetItem widgetItemModel)
{
return false;
}

// Create commands
YourHomeLoadedCommand = new RelayCommand<RoutedEventArgs>(YourHomeLoaded);
// Don't add existing ones!
if (!CanAddWidget(widgetItemModel.WidgetName))
{
return false;
}

if (atIndex > WidgetItems.Count)
{
WidgetItems.Add(widgetModel);
}
else
{
WidgetItems.Insert(atIndex, widgetModel);
}

return true;
}

public bool CanAddWidget(string widgetName)
{
return !(WidgetItems.Any((item) => item.WidgetItemModel.WidgetName == widgetName));
}

public void RemoveWidgetAt(int index)
{
if (index < 0)
{
return;
}

WidgetItems[index].Dispose();
WidgetItems.RemoveAt(index);
}

public void ChangeAppInstance(IShellPage associatedInstance)
public void RemoveWidget<TWidget>() where TWidget : IWidgetItem
{
this.associatedInstance = associatedInstance;
int indexToRemove = -1;

for (int i = 0; i < WidgetItems.Count; i++)
{
if (typeof(TWidget).IsAssignableFrom(WidgetItems[i].WidgetControl.GetType()))
{
// Found matching types
indexToRemove = i;
break;
}
}

RemoveWidgetAt(indexToRemove);
}

private void YourHomeLoaded(RoutedEventArgs e)
public void ReorderWidget(WidgetItem widgetModel, int place)
{
YourHomeLoadedInvoked?.Invoke(this, e);
int widgetIndex = WidgetItems.IndexOf(widgetModel);
WidgetItems.Move(widgetIndex, place);
}

public void Dispose()
{
widgetsViewModel?.Dispose();
for (int i = 0; i < WidgetItems.Count; i++)
WidgetItems[i].Dispose();

WidgetItems.Clear();
}
}
}
24 changes: 24 additions & 0 deletions src/Files.App/ViewModels/Widgets/IWidgetItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.

using Microsoft.UI.Xaml.Controls;

namespace Files.App.ViewModels.Widgets
{
public interface IWidgetItem : IDisposable
{
string WidgetName { get; }

string WidgetHeader { get; }

string AutomationProperties { get; }

bool IsWidgetSettingEnabled { get; }

bool ShowMenuFlyout { get; }

MenuFlyoutItem MenuFlyoutItem { get; }

Task RefreshWidgetAsync();
}
}
62 changes: 62 additions & 0 deletions src/Files.App/ViewModels/Widgets/WidgetItem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.

using Microsoft.UI.Xaml.Controls;

namespace Files.App.ViewModels.Widgets
{
public class WidgetItem : ObservableObject, IDisposable
{
private readonly Action<bool> _expanderValueChangedCallback;
private readonly Func<bool> _expanderValueRequestedCallback;

private object _WidgetControl;
public object WidgetControl
{
get => _WidgetControl;
set => SetProperty(ref _WidgetControl, value);
}

public bool IsExpanded
{
get => _expanderValueRequestedCallback?.Invoke() ?? true;
set
{
_expanderValueChangedCallback?.Invoke(value);
OnPropertyChanged();
}
}

public IWidgetItem WidgetItemModel
{
get => WidgetControl as IWidgetItem;
}

public string WidgetAutomationProperties
{
get => WidgetItemModel.AutomationProperties;
}

public bool ShowMenuFlyout
{
get => WidgetItemModel.ShowMenuFlyout;
}

public MenuFlyoutItem MenuFlyoutItem
{
get => WidgetItemModel.MenuFlyoutItem;
}

public WidgetItem(object widgetControl, Action<bool> expanderValueChangedCallback, Func<bool> expanderValueRequestedCallback)
{
WidgetControl = widgetControl;
_expanderValueChangedCallback = expanderValueChangedCallback;
_expanderValueRequestedCallback = expanderValueRequestedCallback;
}

public void Dispose()
{
(WidgetControl as IDisposable)?.Dispose();
}
}
}
Loading