Skip to content

Feature: Added Tags section in settings #11320

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 6 commits into from
Feb 16, 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
13 changes: 11 additions & 2 deletions src/Files.App/Dialogs/SettingsDialog.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,21 @@
<FontIcon Glyph="&#xE8B7;" />
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem
AccessKey="T"
AutomationProperties.AutomationId="SettingsItemTags"
Content="{helpers:ResourceString Name=FileTags}"
Tag="3">
<NavigationViewItem.Icon>
<FontIcon Glyph="&#xE1CB;" />
</NavigationViewItem.Icon>
</NavigationViewItem>
<NavigationViewItem
AccessKey="E"
AutomationProperties.AutomationId="SettingsItemAdvanced"
Content="{helpers:ResourceString Name=Advanced}"
CornerRadius="0"
Tag="3">
Tag="4">
<NavigationViewItem.Icon>
<FontIcon Glyph="&#xF1AD;" />
</NavigationViewItem.Icon>
Expand All @@ -109,7 +118,7 @@
AccessKey="B"
AutomationProperties.AutomationId="SettingsItemAbout"
Content="{helpers:ResourceString Name=About}"
Tag="4">
Tag="5">
<NavigationViewItem.Icon>
<FontIcon FontSize="16" Glyph="&#xE946;" />
</NavigationViewItem.Icon>
Expand Down
5 changes: 3 additions & 2 deletions src/Files.App/Dialogs/SettingsDialog.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,9 @@ private void SettingsPane_SelectionChanged(NavigationView sender, NavigationView
0 => SettingsContentFrame.Navigate(typeof(Appearance)),
1 => SettingsContentFrame.Navigate(typeof(Preferences)),
2 => SettingsContentFrame.Navigate(typeof(Folders)),
3 => SettingsContentFrame.Navigate(typeof(Advanced)),
4 => SettingsContentFrame.Navigate(typeof(About)),
3 => SettingsContentFrame.Navigate(typeof(Tags)),
4 => SettingsContentFrame.Navigate(typeof(Advanced)),
5 => SettingsContentFrame.Navigate(typeof(About)),
_ => SettingsContentFrame.Navigate(typeof(Appearance))
};
}
Expand Down
128 changes: 1 addition & 127 deletions src/Files.App/ViewModels/SettingsViewModels/AdvancedViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,12 @@
using Files.App.Helpers;
using Files.App.Shell;
using Files.Backend.Services.Settings;
using Files.Backend.ViewModels.FileTags;
using Files.Shared.Extensions;
using Microsoft.Win32;
using SevenZip;
using System;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
Expand All @@ -31,25 +28,14 @@ public class AdvancedViewModel : ObservableObject
private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetRequiredService<IUserSettingsService>();

private readonly IBundlesSettingsService bundlesSettingsService = Ioc.Default.GetRequiredService<IBundlesSettingsService>();

private readonly IFileTagsSettingsService fileTagsSettingsService = Ioc.Default.GetRequiredService<IFileTagsSettingsService>();

private bool isBulkOperation = true;

private bool isDragStarting = true;

public ICommand SetAsDefaultExplorerCommand { get; }
public ICommand SetAsOpenFileDialogCommand { get; }
public ICommand ExportSettingsCommand { get; }
public ICommand ImportSettingsCommand { get; }
public ICommand OpenSettingsJsonCommand { get; }
public ICommand AddTagCommand { get; }
public ICommand SaveNewTagCommand { get; }
public ICommand CancelNewTagCommand { get; }

public NewTagViewModel NewTag = new();

public ObservableCollection<ListedTagViewModel> Tags { get; set; }

public AdvancedViewModel()
{
Expand All @@ -61,35 +47,6 @@ public AdvancedViewModel()
ExportSettingsCommand = new AsyncRelayCommand(ExportSettings);
ImportSettingsCommand = new AsyncRelayCommand(ImportSettings);
OpenSettingsJsonCommand = new AsyncRelayCommand(OpenSettingsJson);

// Tags Commands
AddTagCommand = new RelayCommand(DoAddNewTag);
SaveNewTagCommand = new RelayCommand(DoSaveNewTag);
CancelNewTagCommand = new RelayCommand(DoCancelNewTag);

Tags = new ObservableCollection<ListedTagViewModel>();
Tags.CollectionChanged += Tags_CollectionChanged;
fileTagsSettingsService.FileTagList?.ForEach(tag => Tags.Add(new ListedTagViewModel(tag)));

isBulkOperation = false;
}

private void Tags_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (isBulkOperation)
return;

// Reaordering ListView has no events, but its collection is updated twice,
// first to remove the selected item, and second to add the item at the selected position.
if (isDragStarting)
{
isDragStarting = false;
return;
}

isDragStarting = true;

fileTagsSettingsService.FileTagList = Tags.Select(tagVM => tagVM.Tag).ToList();
}

private async Task OpenSettingsJson()
Expand Down Expand Up @@ -322,13 +279,6 @@ public bool IsSetAsOpenFileDialog
set => SetProperty(ref isSetAsOpenFileDialog, value);
}

private bool isCreatingNewTag;
public bool IsCreatingNewTag
{
get => isCreatingNewTag;
set => SetProperty(ref isCreatingNewTag, value);
}

private FileSavePicker InitializeWithWindow(FileSavePicker obj)
{
WinRT.Interop.InitializeWithWindow.Initialize(obj, App.WindowHandle);
Expand All @@ -342,81 +292,5 @@ private FileOpenPicker InitializeWithWindow(FileOpenPicker obj)

return obj;
}

private void DoAddNewTag()
{
NewTag.Reset();
IsCreatingNewTag = true;
}

private void DoSaveNewTag()
{
IsCreatingNewTag = false;

fileTagsSettingsService.CreateNewTag(NewTag.Name, NewTag.Color);

isBulkOperation = true;
Tags.Clear();
fileTagsSettingsService.FileTagList?.ForEach(tag => Tags.Add(new ListedTagViewModel(tag)));
isBulkOperation = false;
}

private void DoCancelNewTag()
{
IsCreatingNewTag = false;
}

public void EditExistingTag(ListedTagViewModel item, string newName, string color)
{
fileTagsSettingsService.EditTag(item.Tag.Uid, newName, color);

isBulkOperation = true;
Tags.Clear();
fileTagsSettingsService.FileTagList?.ForEach(tag => Tags.Add(new ListedTagViewModel(tag)));
isBulkOperation = false;
}

public void DeleteExistingTag(ListedTagViewModel item)
{
isBulkOperation = true;
Tags.Remove(item);
isBulkOperation = false;

fileTagsSettingsService.DeleteTag(item.Tag.Uid);
}
}

public class NewTagViewModel : ObservableObject
{
private string name = string.Empty;
public string Name
{
get => name;
set
{
if (SetProperty(ref name, value))
OnPropertyChanged(nameof(IsNameValid));
}
}

private string color = "#FFFFFFFF";
public string Color
{
get => color;
set => SetProperty(ref color, value);
}

private bool isNameValid;
public bool IsNameValid
{
get => isNameValid;
set => SetProperty(ref isNameValid, value);
}

public void Reset()
{
Name = string.Empty;
Color = ColorHelpers.RandomColor();
}
}
}
144 changes: 144 additions & 0 deletions src/Files.App/ViewModels/SettingsViewModels/TagsSettingsViewModel.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.Mvvm.Input;
using Files.App.Helpers;
using Files.Backend.Services.Settings;
using Files.Backend.ViewModels.FileTags;
using Files.Shared.Extensions;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;

namespace Files.App.ViewModels.SettingsViewModels
{
public class TagsSettingsViewModel : ObservableObject
{
private readonly IFileTagsSettingsService fileTagsSettingsService = Ioc.Default.GetRequiredService<IFileTagsSettingsService>();

private bool isBulkOperation = true;

private bool isDragStarting = true;

private bool isCreatingNewTag;
public bool IsCreatingNewTag
{
get => isCreatingNewTag;
set => SetProperty(ref isCreatingNewTag, value);
}

public ObservableCollection<ListedTagViewModel> Tags { get; set; }

public ICommand AddTagCommand { get; }
public ICommand SaveNewTagCommand { get; }
public ICommand CancelNewTagCommand { get; }

public NewTagViewModel NewTag = new();

public TagsSettingsViewModel()
{
// Tags Commands
AddTagCommand = new RelayCommand(DoAddNewTag);
SaveNewTagCommand = new RelayCommand(DoSaveNewTag);
CancelNewTagCommand = new RelayCommand(DoCancelNewTag);

Tags = new ObservableCollection<ListedTagViewModel>();
Tags.CollectionChanged += Tags_CollectionChanged;
fileTagsSettingsService.FileTagList?.ForEach(tag => Tags.Add(new ListedTagViewModel(tag)));

isBulkOperation = false;
}

private void Tags_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
if (isBulkOperation)
return;

// Reaordering ListView has no events, but its collection is updated twice,
// first to remove the selected item, and second to add the item at the selected position.
if (isDragStarting)
{
isDragStarting = false;
return;
}
isDragStarting = true;

fileTagsSettingsService.FileTagList = Tags.Select(tagVM => tagVM.Tag).ToList();
}

private void DoAddNewTag()
{
NewTag.Reset();
IsCreatingNewTag = true;
}

private void DoSaveNewTag()
{
IsCreatingNewTag = false;

fileTagsSettingsService.CreateNewTag(NewTag.Name, NewTag.Color);

isBulkOperation = true;
Tags.Clear();
fileTagsSettingsService.FileTagList?.ForEach(tag => Tags.Add(new ListedTagViewModel(tag)));
isBulkOperation = false;
}

private void DoCancelNewTag()
{
IsCreatingNewTag = false;
}

public void EditExistingTag(ListedTagViewModel item, string newName, string color)
{
fileTagsSettingsService.EditTag(item.Tag.Uid, newName, color);

isBulkOperation = true;
Tags.Clear();
fileTagsSettingsService.FileTagList?.ForEach(tag => Tags.Add(new ListedTagViewModel(tag)));
isBulkOperation = false;
}

public void DeleteExistingTag(ListedTagViewModel item)
{
isBulkOperation = true;
Tags.Remove(item);
isBulkOperation = false;

fileTagsSettingsService.DeleteTag(item.Tag.Uid);
}
}

public class NewTagViewModel : ObservableObject
{
private string name = string.Empty;
public string Name
{
get => name;
set
{
if (SetProperty(ref name, value))
OnPropertyChanged(nameof(IsNameValid));
}
}

private string color = "#FFFFFFFF";
public string Color
{
get => color;
set => SetProperty(ref color, value);
}

private bool isNameValid;
public bool IsNameValid
{
get => isNameValid;
set => SetProperty(ref isNameValid, value);
}

public void Reset()
{
Name = string.Empty;
Color = ColorHelpers.RandomColor();
}
}
}
Loading