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

Feature/quick search #66

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
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
15 changes: 15 additions & 0 deletions src/Camelot.Services.Abstractions/IQuickSearchService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using Camelot.Services.Abstractions.Models;

namespace Camelot.Services.Abstractions;

public interface IQuickSearchService
{
bool IsEnabled { get; }

event EventHandler<EventArgs> QuickSearchModeChanged;

QuickSearchModel GetQuickSearchSettings();

void SaveQuickSearchSettings(QuickSearchModel quickSearchModel);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;

namespace Camelot.Services.Abstractions.Models.Enums.Input;

/// <summary>
/// Needed to be duplicated here, since nor Avalonia, nor Windows.Forms, etc
/// are referenced in "Camelot.Services.Abstractions"
/// Used in feature of 'quick search' to determine if shift key is down.
/// </summary>

[Flags]
public enum KeyModifiers
{
None = 0,
Alt = 1,
Control = 2,
Shift = 4,
Meta = 8,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@

namespace Camelot.Services.Abstractions.Models.Enums;

public enum QuickSearchMode : byte
{
Disabled,
Letter,
Word
}
13 changes: 13 additions & 0 deletions src/Camelot.Services.Abstractions/Models/QuickSearchModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Camelot.Services.Abstractions.Models.Enums;

namespace Camelot.Services.Abstractions.Models;

public class QuickSearchModel
{
public QuickSearchMode SelectedMode { get; }

public QuickSearchModel(QuickSearchMode selectedMode)
{
SelectedMode = selectedMode;
}
}
55 changes: 55 additions & 0 deletions src/Camelot.Services/QuickSearchService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
using System;
using Camelot.DataAccess.UnitOfWork;
using Camelot.Extensions;
using Camelot.Services.Abstractions;
using Camelot.Services.Abstractions.Models;
using Camelot.Services.Abstractions.Models.Enums;

namespace Camelot.Services;

public class QuickSearchService : IQuickSearchService
{
private const string SettingsId = "QuickSearchSettings";

private readonly IUnitOfWorkFactory _unitOfWorkFactory;

private QuickSearchModel _cachedSettingsValue;

public bool IsEnabled => _cachedSettingsValue.SelectedMode != QuickSearchMode.Disabled;

public event EventHandler<EventArgs> QuickSearchModeChanged;

public QuickSearchService(IUnitOfWorkFactory unitOfWorkFactory)
{
_unitOfWorkFactory = unitOfWorkFactory;

GetQuickSearchSettings();
}

public QuickSearchModel GetQuickSearchSettings()
{
if (_cachedSettingsValue is not null)
{
return _cachedSettingsValue;
}

using var uow = _unitOfWorkFactory.Create();
var repository = uow.GetRepository<QuickSearchModel>();
var dbModel = repository.GetById(SettingsId) ?? new QuickSearchModel(QuickSearchMode.Disabled);

return _cachedSettingsValue = dbModel;
}

public void SaveQuickSearchSettings(QuickSearchModel quickSearchModel)
{
using var uow = _unitOfWorkFactory.Create();
var repository = uow.GetRepository<QuickSearchModel>();

repository.Upsert(SettingsId, quickSearchModel);
_cachedSettingsValue = quickSearchModel;

RaiseQuickSearchModeChangedEvent();
}

private void RaiseQuickSearchModeChangedEvent() => QuickSearchModeChanged.Raise(this, EventArgs.Empty);
}
1 change: 0 additions & 1 deletion src/Camelot.ViewModels.Windows/WinApi/ShellIcon.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Camelot.Services.Windows.WinApi;
using System.Diagnostics;

namespace Camelot.ViewModels.Windows.WinApi;

Original file line number Diff line number Diff line change
@@ -15,8 +15,11 @@ public class SettingsDialogViewModel : DialogViewModelBase
public ISettingsViewModel TerminalSettingsViewModel { get; set; }

public ISettingsViewModel GeneralSettingsViewModel { get; set; }

public ISettingsViewModel IconsSettingsViewModel { get; set; }

public ISettingsViewModel KeyboardSettingsViewModel { get; set; }

public int SelectedIndex
{
get => _selectedIndex;
@@ -32,17 +35,20 @@ public int SelectedIndex
public SettingsDialogViewModel(
ISettingsViewModel generalSettingsViewModel,
ISettingsViewModel terminalSettingsViewModel,
ISettingsViewModel iconsSettingsViewModel)
ISettingsViewModel iconsSettingsViewModel,
ISettingsViewModel keyboardSettingsViewModel)
{
TerminalSettingsViewModel = terminalSettingsViewModel;
GeneralSettingsViewModel = generalSettingsViewModel;
IconsSettingsViewModel = iconsSettingsViewModel;
KeyboardSettingsViewModel = keyboardSettingsViewModel;

_settingsViewModels = new[]
{
generalSettingsViewModel,
terminalSettingsViewModel,
iconsSettingsViewModel
iconsSettingsViewModel,
keyboardSettingsViewModel
};

Activate(_settingsViewModels.First());
Original file line number Diff line number Diff line change
@@ -18,10 +18,12 @@
using Camelot.ViewModels.Implementations.Dialogs;
using Camelot.ViewModels.Implementations.Dialogs.NavigationParameters;
using Camelot.ViewModels.Interfaces.MainWindow.FilePanels;
using Camelot.ViewModels.Interfaces.MainWindow.FilePanels.EventArgs;
using Camelot.ViewModels.Interfaces.MainWindow.FilePanels.Nodes;
using Camelot.ViewModels.Interfaces.MainWindow.FilePanels.Tabs;
using Camelot.ViewModels.Interfaces.MainWindow.Operations;
using Camelot.ViewModels.Services.Interfaces;

using DynamicData;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
@@ -49,7 +51,8 @@ public class FilesPanelViewModel : ViewModelBase, IFilesPanelViewModel

private CancellationTokenSource _cancellationTokenSource;
private string _currentDirectory;
private INodeSpecification _specification;
private INodeSpecification _searchSpecification;
private ISpecification<IFileSystemNodeViewModel> _filterSpecification;

private IEnumerable<IFileViewModel> SelectedFiles => _selectedFileSystemNodes.OfType<IFileViewModel>();

@@ -63,6 +66,8 @@ public class FilesPanelViewModel : ViewModelBase, IFilesPanelViewModel

public ISearchViewModel SearchViewModel { get; }

public IQuickSearchViewModel QuickSearchViewModel { get; }

public ITabsListViewModel TabsListViewModel { get; }

public IOperationsViewModel OperationsViewModel { get; }
@@ -129,6 +134,7 @@ public FilesPanelViewModel(
IPermissionsService permissionsService,
IDialogService dialogService,
ISearchViewModel searchViewModel,
IQuickSearchViewModel quickSearchViewModel,
ITabsListViewModel tabsListViewModel,
IOperationsViewModel operationsViewModel,
IDirectorySelectorViewModel directorySelectorViewModel,
@@ -150,6 +156,7 @@ public FilesPanelViewModel(
_dialogService = dialogService;

SearchViewModel = searchViewModel;
QuickSearchViewModel = quickSearchViewModel;
TabsListViewModel = tabsListViewModel;
OperationsViewModel = operationsViewModel;
DirectorySelectorViewModel = directorySelectorViewModel;
@@ -165,7 +172,6 @@ public FilesPanelViewModel(
(DirectoryModel dm) => dm is not null);
GoToParentDirectoryCommand = ReactiveCommand.Create(GoToParentDirectory, canGoToParentDirectory);
SortFilesCommand = ReactiveCommand.Create<SortingMode>(SortFiles);

SubscribeToEvents();
UpdateStateAsync().Forget();
}
@@ -209,6 +215,7 @@ private void SubscribeToEvents()
SearchViewModel.SearchSettingsChanged += SearchViewModelOnSearchSettingsChanged;
_filePanelDirectoryObserver.CurrentDirectoryChanged += async (_, _) => await UpdateStateAsync();
_selectedFileSystemNodes.CollectionChanged += SelectedFileSystemNodesOnCollectionChanged;
QuickSearchViewModel.QuickSearchFilterChanged += QuickSearchViewModelOnQuickSearchFilterChanged;

_fileSystemWatchingService.NodeCreated += (_, args) =>
ExecuteInUiThread(() => InsertNode(args.Node));
@@ -257,6 +264,8 @@ private async Task UpdateStateAsync()

CurrentDirectoryChanged.Raise(this, EventArgs.Empty);
this.RaisePropertyChanged(nameof(ParentDirectory));

QuickSearchViewModel.ClearQuickSearch();
}

private void UpdateNode(string nodePath) => RecreateNode(nodePath, nodePath);
@@ -283,6 +292,7 @@ private void InsertNode(string nodePath, bool isSelected = false)

var index = GetInsertIndex(newNodeModel);
_fileSystemNodes.Insert(index, newNodeModel);
UpdateNodeFiltering(newNodeModel);

if (isSelected)
{
@@ -328,14 +338,14 @@ private void ReloadFiles()
{
CancelPreviousSearchIfNeeded();

_specification = SearchViewModel.GetSpecification();
if (_specification.IsRecursive)
_searchSpecification = SearchViewModel.GetSpecification();
if (_searchSpecification.IsRecursive)
{
RecursiveSearch(_specification);
RecursiveSearch(_searchSpecification);
}
else
{
Search(_specification);
Search(_searchSpecification);
}

InsertParentDirectory();
@@ -420,6 +430,27 @@ private void SelectedFileSystemNodesOnCollectionChanged(object sender, NotifyCol
this.RaisePropertyChanged(nameof(AreAnyFileSystemNodesSelected));
}

private void QuickSearchViewModelOnQuickSearchFilterChanged(object sender, QuickSearchFilterChangedEventArgs e)
{
_filterSpecification = QuickSearchViewModel.GetSpecification();
_fileSystemNodes.ForEach(UpdateNodeFiltering);

MoveSelection(e.Direction);
}

private void MoveSelection(SelectionChangeDirection direction)
{
switch (direction)
{
case SelectionChangeDirection.Backward:
MoveSelection(-1);
break;
case SelectionChangeDirection.Forward:
MoveSelection(1);
break;
}
}

private int GetInsertIndex(IFileSystemNodeViewModel newNodeViewModel)
{
var comparer = GetComparer();
@@ -428,14 +459,71 @@ private int GetInsertIndex(IFileSystemNodeViewModel newNodeViewModel)
return index < 0 ? index ^ -1 : index;
}

private IComparer<IFileSystemNodeViewModel> GetComparer() =>
_comparerFactory.Create(SelectedTab.SortingViewModel);
private IComparer<IFileSystemNodeViewModel> GetComparer() => _comparerFactory.Create(SelectedTab.SortingViewModel);

private IFileSystemNodeViewModel GetViewModel(string nodePath) =>
_fileSystemNodes.FirstOrDefault(n => n.FullPath == nodePath);

private void ExecuteInUiThread(Action action) => _applicationDispatcher.Dispatch(action);

private bool CheckIfShouldShowNode(string nodePath) =>
_specification?.IsSatisfiedBy(_nodeService.GetNode(nodePath)) ?? true;
}
_searchSpecification?.IsSatisfiedBy(_nodeService.GetNode(nodePath)) ?? true;

private void MoveSelection(int step)
{
var (selectedIndex, selectedNode) = GetSelectedNodeWithIndex();
var newNode = GetNewSelectedNode(selectedIndex, step);

ChangeSelectedNode(selectedNode, newNode);
}

private IFileSystemNodeViewModel GetNewSelectedNode(int selectedIndex, int step)
{
var count = _fileSystemNodes.Count;

var start = selectedIndex > -1 ? selectedIndex + step : 0;
start = (start + count) % count;

for (var i = start; i != start - step; i = (i + step + count) % count)
{
var file = _fileSystemNodes[i];
if (!file.IsFilteredOut)
{
return file;
}
}

return null;
}

private (int, IFileSystemNodeViewModel) GetSelectedNodeWithIndex()
{
// TODO: check if possible to improve
var currentSelectedNode = _selectedFileSystemNodes.FirstOrDefault();

return currentSelectedNode is null
? (-1, null)
: (_fileSystemNodes.IndexOf(currentSelectedNode), currentSelectedNode);
}

private void ChangeSelectedNode(IFileSystemNodeViewModel oldNode, IFileSystemNodeViewModel newNode)
{
if (newNode is null)
{
return;
}

if (oldNode is not null)
{
UnselectNode(oldNode.FullPath);
}

SelectNode(newNode.FullPath);
}

private void UpdateNodeFiltering(IFileSystemNodeViewModel nodeViewModel) =>
nodeViewModel.IsFilteredOut = CheckIfShouldFilterOutNode(nodeViewModel);

private bool CheckIfShouldFilterOutNode(IFileSystemNodeViewModel nodeViewModel) =>
!_filterSpecification?.IsSatisfiedBy(nodeViewModel) ?? false;
}
Original file line number Diff line number Diff line change
@@ -28,6 +28,9 @@ public abstract class FileSystemNodeViewModelBase : ViewModelBase, IFileSystemNo
[Reactive]
public bool IsEditing { get; set; }

[Reactive]
public bool IsFilteredOut { get; set; }

public bool IsArchive => _fileSystemNodeFacade.CheckIfNodeIsArchive(FullPath);

public bool ShouldShowOpenSubmenu { get; }
Loading

Unchanged files with check annotations Beta

return null;
}
var bitmapTmp = new System.Drawing.Bitmap(image);

Check warning on line 21 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (ubuntu-latest)

This call site is reachable on all platforms. 'Bitmap' is only supported on: 'windows'.
var bitmapData = bitmapTmp.LockBits(

Check warning on line 22 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (macos-latest)

This call site is reachable on all platforms. 'Bitmap.LockBits(Rectangle, ImageLockMode, PixelFormat)' is only supported on: 'windows'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
new Rectangle(0, 0, bitmapTmp.Width, bitmapTmp.Height),

Check warning on line 23 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (ubuntu-latest)

This call site is reachable on all platforms. 'Image.Width' is only supported on: 'windows'.

Check warning on line 23 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (macos-latest)

This call site is reachable on all platforms. 'Image.Height' is only supported on: 'windows'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)

Check warning on line 23 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (macos-latest)

This call site is reachable on all platforms. 'Image.Width' is only supported on: 'windows'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);

Check warning on line 24 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (macos-latest)

This call site is reachable on all platforms. 'ImageLockMode.ReadWrite' is only supported on: 'windows'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
var bitmap = new AvaloniaBitmap(AvaloniaPixelFormat.Bgra8888,
AlphaFormat.Unpremul,
bitmapData.Scan0,

Check warning on line 27 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (macos-latest)

This call site is reachable on all platforms. 'BitmapData.Scan0' is only supported on: 'windows'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
new PixelSize(bitmapData.Width, bitmapData.Height),

Check warning on line 28 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (ubuntu-latest)

This call site is reachable on all platforms. 'BitmapData.Height' is only supported on: 'windows'.

Check warning on line 28 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (windows-latest)

This call site is reachable on all platforms. 'BitmapData.Width' is only supported on: 'windows'.
new Vector(96, 96),
bitmapData.Stride);

Check warning on line 30 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (ubuntu-latest)

This call site is reachable on all platforms. 'BitmapData.Stride' is only supported on: 'windows'.

Check warning on line 30 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (macos-latest)

This call site is reachable on all platforms. 'BitmapData.Stride' is only supported on: 'windows'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
bitmapTmp.UnlockBits(bitmapData);

Check warning on line 31 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (ubuntu-latest)

This call site is reachable on all platforms. 'Bitmap.UnlockBits(BitmapData)' is only supported on: 'windows'.

Check warning on line 31 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (macos-latest)

This call site is reachable on all platforms. 'Bitmap.UnlockBits(BitmapData)' is only supported on: 'windows'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
bitmapTmp.Dispose();

Check warning on line 32 in src/Camelot.ViewModels.Windows/ShellIcons/SystemImageToAvaloniaBitmapConverter.cs

GitHub Actions / build (ubuntu-latest)

This call site is reachable on all platforms. 'Image.Dispose()' is only supported on: 'windows'.
return bitmap;
}
var icon = IconExtractor.ExtractIcon(path);
// TODO: check if lossy and/or try other options, see url below. (iksi4prs).
// https://learn.microsoft.com/en-us/dotnet/api/system.drawing.imageconverter.canconvertfrom?view=dotnet-plat-ext-7.0
var systemBitmap = icon.ToBitmap();

Check warning on line 87 in src/Camelot.ViewModels.Windows/ShellIcons/WindowsShellIconsService.cs

GitHub Actions / build (ubuntu-latest)

This call site is reachable on all platforms. 'Icon.ToBitmap()' is only supported on: 'windows'.

Check warning on line 87 in src/Camelot.ViewModels.Windows/ShellIcons/WindowsShellIconsService.cs

GitHub Actions / build (macos-latest)

This call site is reachable on all platforms. 'Icon.ToBitmap()' is only supported on: 'windows'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)

Check warning on line 87 in src/Camelot.ViewModels.Windows/ShellIcons/WindowsShellIconsService.cs

GitHub Actions / build (windows-latest)

This call site is reachable on all platforms. 'Icon.ToBitmap()' is only supported on: 'windows'.
var avaloniaBitmap = SystemImageToAvaloniaBitmapConverter.Convert(systemBitmap);
result = new ImageModel(avaloniaBitmap);
}
throw new ArgumentException(nameof(fileName));
}
return Icon.ExtractAssociatedIcon(fileName);

Check warning on line 66 in src/Camelot.ViewModels.Windows/WinApi/IconExtractor.cs

GitHub Actions / build (ubuntu-latest)

This call site is reachable on all platforms. 'Icon.ExtractAssociatedIcon(string)' is only supported on: 'windows'.
}
// needed for indexed icons (when more than one in file, and there's a number/index for the icon we need)
// https://stackoverflow.com/questions/30979653/icon-fromhandle-should-i-dispose-it-or-call-destroyicon
if (largeIcon)
{
result = Icon.FromHandle(large);

Check warning on line 89 in src/Camelot.ViewModels.Windows/WinApi/IconExtractor.cs

GitHub Actions / build (ubuntu-latest)

This call site is reachable on all platforms. 'Icon.FromHandle(IntPtr)' is only supported on: 'windows'.

Check warning on line 89 in src/Camelot.ViewModels.Windows/WinApi/IconExtractor.cs

GitHub Actions / build (macos-latest)

This call site is reachable on all platforms. 'Icon.FromHandle(IntPtr)' is only supported on: 'windows'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
DestroyIcon(small);
}
else
{
result = Icon.FromHandle(small);

Check warning on line 94 in src/Camelot.ViewModels.Windows/WinApi/IconExtractor.cs

GitHub Actions / build (ubuntu-latest)

This call site is reachable on all platforms. 'Icon.FromHandle(IntPtr)' is only supported on: 'windows'.

Check warning on line 94 in src/Camelot.ViewModels.Windows/WinApi/IconExtractor.cs

GitHub Actions / build (macos-latest)

This call site is reachable on all platforms. 'Icon.FromHandle(IntPtr)' is only supported on: 'windows'. (https://learn.microsoft.com/dotnet/fundamentals/code-analysis/quality-rules/ca1416)
DestroyIcon(large);
}
var node = factory.Create(fileModel);
Assert.NotNull(node);
Assert.Equal(node.Name, Name);

Check warning on line 50 in tests/Camelot.ViewModels.Tests/Factories/FileSystemNodeViewModelFactoryTests.cs

GitHub Actions / build (windows-latest)

The literal or constant value Name should be passed as the 'expected' argument in the call to 'Assert.Equal(expected, actual)' in method 'TestCreateFile' on type 'FileSystemNodeViewModelFactoryTests'. Swap the parameter values.
Assert.Equal(node.FullPath, FullPath);

Check warning on line 51 in tests/Camelot.ViewModels.Tests/Factories/FileSystemNodeViewModelFactoryTests.cs

GitHub Actions / build (windows-latest)

The literal or constant value FullPath should be passed as the 'expected' argument in the call to 'Assert.Equal(expected, actual)' in method 'TestCreateFile' on type 'FileSystemNodeViewModelFactoryTests'. Swap the parameter values.
Assert.False(node.IsEditing);
}
}
Assert.NotNull(node);
Assert.Equal(node.Name, Name);

Check warning on line 97 in tests/Camelot.ViewModels.Tests/Factories/FileSystemNodeViewModelFactoryTests.cs

GitHub Actions / build (windows-latest)

The literal or constant value Name should be passed as the 'expected' argument in the call to 'Assert.Equal(expected, actual)' in method 'TestCreateFileByPath' on type 'FileSystemNodeViewModelFactoryTests'. Swap the parameter values.
Assert.Equal(node.FullPath, FullPath);

Check warning on line 98 in tests/Camelot.ViewModels.Tests/Factories/FileSystemNodeViewModelFactoryTests.cs

GitHub Actions / build (windows-latest)

The literal or constant value FullPath should be passed as the 'expected' argument in the call to 'Assert.Equal(expected, actual)' in method 'TestCreateFileByPath' on type 'FileSystemNodeViewModelFactoryTests'. Swap the parameter values.
Assert.False(node.IsEditing);
}
var node = factory.Create(directoryModel, isParentDirectory);
Assert.NotNull(node);
Assert.Equal(node.Name, Name);

Check warning on line 122 in tests/Camelot.ViewModels.Tests/Factories/FileSystemNodeViewModelFactoryTests.cs

GitHub Actions / build (windows-latest)

The literal or constant value Name should be passed as the 'expected' argument in the call to 'Assert.Equal(expected, actual)' in method 'TestCreateDirectory' on type 'FileSystemNodeViewModelFactoryTests'. Swap the parameter values.
Assert.Equal(node.FullPath, FullPath);

Check warning on line 123 in tests/Camelot.ViewModels.Tests/Factories/FileSystemNodeViewModelFactoryTests.cs

GitHub Actions / build (windows-latest)

The literal or constant value FullPath should be passed as the 'expected' argument in the call to 'Assert.Equal(expected, actual)' in method 'TestCreateDirectory' on type 'FileSystemNodeViewModelFactoryTests'. Swap the parameter values.
Assert.False(node.IsEditing);
}
}
Assert.NotNull(node);
Assert.Equal(node.Name, Name);

Check warning on line 160 in tests/Camelot.ViewModels.Tests/Factories/FileSystemNodeViewModelFactoryTests.cs

GitHub Actions / build (windows-latest)

The literal or constant value Name should be passed as the 'expected' argument in the call to 'Assert.Equal(expected, actual)' in method 'TestCreateDirectoryByPath' on type 'FileSystemNodeViewModelFactoryTests'. Swap the parameter values.
Assert.Equal(node.FullPath, FullPath);

Check warning on line 161 in tests/Camelot.ViewModels.Tests/Factories/FileSystemNodeViewModelFactoryTests.cs

GitHub Actions / build (windows-latest)

The literal or constant value FullPath should be passed as the 'expected' argument in the call to 'Assert.Equal(expected, actual)' in method 'TestCreateDirectoryByPath' on type 'FileSystemNodeViewModelFactoryTests'. Swap the parameter values.
Assert.False(node.IsEditing);
}