diff --git a/src/Files.App/Data/Contexts/DisplayPage/DisplayPageContext.cs b/src/Files.App/Data/Contexts/DisplayPage/DisplayPageContext.cs index 5901a98cf098..e15fb2e47162 100644 --- a/src/Files.App/Data/Contexts/DisplayPage/DisplayPageContext.cs +++ b/src/Files.App/Data/Contexts/DisplayPage/DisplayPageContext.cs @@ -55,7 +55,7 @@ public SortOption SortOption get => _SortOption; set { - if (FolderSettings is FolderSettingsViewModel viewModel) + if (FolderSettings is LayoutPreferencesManager viewModel) viewModel.DirectorySortOption = value; } } @@ -66,7 +66,7 @@ public SortDirection SortDirection get => _SortDirection; set { - if (FolderSettings is FolderSettingsViewModel viewModel) + if (FolderSettings is LayoutPreferencesManager viewModel) viewModel.DirectorySortDirection = value; } } @@ -77,7 +77,7 @@ public GroupOption GroupOption get => _GroupOption; set { - if (FolderSettings is FolderSettingsViewModel viewModel) + if (FolderSettings is LayoutPreferencesManager viewModel) viewModel.DirectoryGroupOption = value; } } @@ -88,7 +88,7 @@ public SortDirection GroupDirection get => _GroupDirection; set { - if (FolderSettings is FolderSettingsViewModel viewModel) + if (FolderSettings is LayoutPreferencesManager viewModel) viewModel.DirectoryGroupDirection = value; } } @@ -99,7 +99,7 @@ public GroupByDateUnit GroupByDateUnit get => _GroupByDateUnit; set { - if (FolderSettings is FolderSettingsViewModel viewModel) + if (FolderSettings is LayoutPreferencesManager viewModel) viewModel.DirectoryGroupByDateUnit = value; } } @@ -110,12 +110,12 @@ public bool SortDirectoriesAlongsideFiles get => _SortDirectoriesAlongsideFiles; set { - if (FolderSettings is FolderSettingsViewModel viewModel) + if (FolderSettings is LayoutPreferencesManager viewModel) viewModel.SortDirectoriesAlongsideFiles = value; } } - private FolderSettingsViewModel? FolderSettings => context.PaneOrColumn?.InstanceViewModel?.FolderSettings; + private LayoutPreferencesManager? FolderSettings => context.PaneOrColumn?.InstanceViewModel?.FolderSettings; public DisplayPageContext() { @@ -126,12 +126,12 @@ public DisplayPageContext() public void DecreaseLayoutSize() { - if (FolderSettings is FolderSettingsViewModel viewModel) + if (FolderSettings is LayoutPreferencesManager viewModel) viewModel.GridViewSize -= GridViewIncrement; } public void IncreaseLayoutSize() { - if (FolderSettings is FolderSettingsViewModel viewModel) + if (FolderSettings is LayoutPreferencesManager viewModel) viewModel.GridViewSize += GridViewIncrement; } @@ -158,27 +158,27 @@ private void FolderSettings_PropertyChanged(object? sender, PropertyChangedEvent switch (e.PropertyName) { - case nameof(FolderSettingsViewModel.LayoutMode): - case nameof(FolderSettingsViewModel.GridViewSize): - case nameof(FolderSettingsViewModel.IsAdaptiveLayoutEnabled): + case nameof(LayoutPreferencesManager.LayoutMode): + case nameof(LayoutPreferencesManager.GridViewSize): + case nameof(LayoutPreferencesManager.IsAdaptiveLayoutEnabled): SetProperty(ref _LayoutType, GetLayoutType(), nameof(LayoutType)); break; - case nameof(FolderSettingsViewModel.DirectorySortOption): + case nameof(LayoutPreferencesManager.DirectorySortOption): SetProperty(ref _SortOption, viewModel.DirectorySortOption, nameof(SortOption)); break; - case nameof(FolderSettingsViewModel.DirectorySortDirection): + case nameof(LayoutPreferencesManager.DirectorySortDirection): SetProperty(ref _SortDirection, viewModel.DirectorySortDirection, nameof(SortDirection)); break; - case nameof(FolderSettingsViewModel.DirectoryGroupOption): + case nameof(LayoutPreferencesManager.DirectoryGroupOption): SetProperty(ref _GroupOption, viewModel.DirectoryGroupOption, nameof(GroupOption)); break; - case nameof(FolderSettingsViewModel.DirectoryGroupDirection): + case nameof(LayoutPreferencesManager.DirectoryGroupDirection): SetProperty(ref _GroupDirection, viewModel.DirectoryGroupDirection, nameof(GroupDirection)); break; - case nameof(FolderSettingsViewModel.DirectoryGroupByDateUnit): + case nameof(LayoutPreferencesManager.DirectoryGroupByDateUnit): SetProperty(ref _GroupByDateUnit, viewModel.DirectoryGroupByDateUnit, nameof(GroupByDateUnit)); break; - case nameof(FolderSettingsViewModel.SortDirectoriesAlongsideFiles): + case nameof(LayoutPreferencesManager.SortDirectoriesAlongsideFiles): SetProperty(ref _SortDirectoriesAlongsideFiles, viewModel.SortDirectoriesAlongsideFiles, nameof(SortDirectoriesAlongsideFiles)); break; } diff --git a/src/Files.App/Data/EventArguments/LayoutPreferenceEventArgs.cs b/src/Files.App/Data/EventArguments/LayoutPreferenceEventArgs.cs index a5099f545052..263717da7d77 100644 --- a/src/Files.App/Data/EventArguments/LayoutPreferenceEventArgs.cs +++ b/src/Files.App/Data/EventArguments/LayoutPreferenceEventArgs.cs @@ -7,12 +7,12 @@ public class LayoutPreferenceEventArgs { public readonly bool IsAdaptiveLayoutUpdateRequired; - public readonly LayoutPreferences LayoutPreference; + public readonly LayoutPreferencesItem LayoutPreference; - internal LayoutPreferenceEventArgs(LayoutPreferences layoutPref) + internal LayoutPreferenceEventArgs(LayoutPreferencesItem layoutPref) => LayoutPreference = layoutPref; - internal LayoutPreferenceEventArgs(LayoutPreferences layoutPref, bool isAdaptiveLayoutUpdateRequired) + internal LayoutPreferenceEventArgs(LayoutPreferencesItem layoutPref, bool isAdaptiveLayoutUpdateRequired) => (LayoutPreference, IsAdaptiveLayoutUpdateRequired) = (layoutPref, isAdaptiveLayoutUpdateRequired); } } diff --git a/src/Files.App/Data/Models/ColumnViewModel.cs b/src/Files.App/Data/Items/DetailsLayoutColumnItem.cs similarity index 62% rename from src/Files.App/Data/Models/ColumnViewModel.cs rename to src/Files.App/Data/Items/DetailsLayoutColumnItem.cs index 25d9806b4e40..a3b4874595d5 100644 --- a/src/Files.App/Data/Models/ColumnViewModel.cs +++ b/src/Files.App/Data/Items/DetailsLayoutColumnItem.cs @@ -3,46 +3,42 @@ using Microsoft.UI.Xaml; -namespace Files.App.Data.Models +namespace Files.App.Data.Items { - public class ColumnViewModel : ObservableObject + /// + /// Represents item for a column shown in . + /// + public class DetailsLayoutColumnItem : ObservableObject { - private bool isHidden; + private const int GRID_SPLITTER_WIDTH = 12; - [LiteDB.BsonIgnore] - public bool IsHidden - { - get => isHidden; - set => SetProperty(ref isHidden, value); - } - - [LiteDB.BsonIgnore] - public double MaxLength + public double UserLengthPixels { - get => UserCollapsed || IsHidden ? 0 : NormalMaxLength; + get => UserLength.Value; + set => UserLength = new GridLength(value, GridUnitType.Pixel); } - private double normalMaxLength = 800; - + private double _NormalMaxLength = 800; public double NormalMaxLength { - get => normalMaxLength; - set => SetProperty(ref normalMaxLength, value); + get => _NormalMaxLength; + set => SetProperty(ref _NormalMaxLength, value); } - private double normalMinLength = 50; - - [LiteDB.BsonIgnore] - public double NormalMinLength + private bool _UserCollapsed; + public bool UserCollapsed { - get => normalMinLength; + get => _UserCollapsed; set { - if (SetProperty(ref normalMinLength, value)) - OnPropertyChanged(nameof(MinLength)); + if (SetProperty(ref _UserCollapsed, value)) + UpdateVisibility(); } } + [LiteDB.BsonIgnore] + public bool IsResizable { get; set; } = true; + [LiteDB.BsonIgnore] public double MinLength => UserCollapsed || IsHidden ? 0 : NormalMinLength; @@ -51,46 +47,48 @@ public double MinLength public Visibility Visibility => UserCollapsed || IsHidden ? Visibility.Collapsed : Visibility.Visible; - private bool userCollapsed; - - public bool UserCollapsed - { - get => userCollapsed; - set - { - if (SetProperty(ref userCollapsed, value)) - UpdateVisibility(); - } - } - [LiteDB.BsonIgnore] public GridLength Length - { - get => UserCollapsed || IsHidden ? new GridLength(0) : UserLength; - } + => UserCollapsed || IsHidden ? new GridLength(0) : UserLength; - private const int gridSplitterWidth = 12; + [LiteDB.BsonIgnore] + public GridLength LengthIncludingGridSplitter => + UserCollapsed || IsHidden + ? new(0) + : new(UserLength.Value + (IsResizable ? GRID_SPLITTER_WIDTH : 0)); + + [LiteDB.BsonIgnore] + public double MaxLength + => UserCollapsed || IsHidden ? 0 : NormalMaxLength; + private bool _IsHidden; [LiteDB.BsonIgnore] - public GridLength LengthIncludingGridSplitter + public bool IsHidden { - get => UserCollapsed || IsHidden - ? new(0) - : new(UserLength.Value + (IsResizeable ? gridSplitterWidth : 0)); + get => _IsHidden; + set => SetProperty(ref _IsHidden, value); } + private double _NormalMinLength = 50; [LiteDB.BsonIgnore] - public bool IsResizeable { get; set; } = true; - - private GridLength userLength = new(200, GridUnitType.Pixel); + public double NormalMinLength + { + get => _NormalMinLength; + set + { + if (SetProperty(ref _NormalMinLength, value)) + OnPropertyChanged(nameof(MinLength)); + } + } + private GridLength _UserLength = new(200, GridUnitType.Pixel); [LiteDB.BsonIgnore] public GridLength UserLength { - get => userLength; + get => _UserLength; set { - if (SetProperty(ref userLength, value)) + if (SetProperty(ref _UserLength, value)) { OnPropertyChanged(nameof(Length)); OnPropertyChanged(nameof(LengthIncludingGridSplitter)); @@ -98,12 +96,6 @@ public GridLength UserLength } } - public double UserLengthPixels - { - get => UserLength.Value; - set => UserLength = new GridLength(value, GridUnitType.Pixel); - } - public void Hide() { IsHidden = true; @@ -125,21 +117,6 @@ private void UpdateVisibility() OnPropertyChanged(nameof(MinLength)); } - public void TryMultiplySize(double factor) - { - var newSize = Length.Value * factor; - if (newSize == 0) - return; - - double setLength = newSize; - if (newSize < MinLength) - setLength = MinLength; - else if (newSize >= MaxLength) - setLength = MaxLength; - - UserLength = new GridLength(setLength); - } - public override bool Equals(object? obj) { if (obj is null) @@ -148,7 +125,7 @@ public override bool Equals(object? obj) if (obj == this) return true; - if (obj is ColumnViewModel model) + if (obj is DetailsLayoutColumnItem model) { return model.UserCollapsed == UserCollapsed && diff --git a/src/Files.App/Data/Models/ColumnsViewModel.cs b/src/Files.App/Data/Models/ColumnsViewModel.cs index d5f0b92a943c..e3957e38d361 100644 --- a/src/Files.App/Data/Models/ColumnsViewModel.cs +++ b/src/Files.App/Data/Models/ColumnsViewModel.cs @@ -7,135 +7,135 @@ namespace Files.App.Data.Models { public class ColumnsViewModel : ObservableObject { - private ColumnViewModel iconColumn = new() + private DetailsLayoutColumnItem iconColumn = new() { UserLength = new GridLength(24, GridUnitType.Pixel), - IsResizeable = false, + IsResizable = false, }; [LiteDB.BsonIgnore] - public ColumnViewModel IconColumn + public DetailsLayoutColumnItem IconColumn { get => iconColumn; set => SetProperty(ref iconColumn, value); } - private ColumnViewModel _GitStatusColumn = new(); - public ColumnViewModel GitStatusColumn + private DetailsLayoutColumnItem _GitStatusColumn = new(); + public DetailsLayoutColumnItem GitStatusColumn { get => _GitStatusColumn; set => SetProperty(ref _GitStatusColumn, value); } - private ColumnViewModel _GitLastCommitDateColumn = new(); - public ColumnViewModel GitLastCommitDateColumn + private DetailsLayoutColumnItem _GitLastCommitDateColumn = new(); + public DetailsLayoutColumnItem GitLastCommitDateColumn { get => _GitLastCommitDateColumn; set => SetProperty(ref _GitLastCommitDateColumn, value); } - private ColumnViewModel _GitLastCommitMessageColumn = new(); - public ColumnViewModel GitLastCommitMessageColumn + private DetailsLayoutColumnItem _GitLastCommitMessageColumn = new(); + public DetailsLayoutColumnItem GitLastCommitMessageColumn { get => _GitLastCommitMessageColumn; set => SetProperty(ref _GitLastCommitMessageColumn, value); } - private ColumnViewModel _GitCommitAuthorColumn = new(); - public ColumnViewModel GitCommitAuthorColumn + private DetailsLayoutColumnItem _GitCommitAuthorColumn = new(); + public DetailsLayoutColumnItem GitCommitAuthorColumn { get => _GitCommitAuthorColumn; set => SetProperty(ref _GitCommitAuthorColumn, value); } - private ColumnViewModel _GitLastCommitShaColumn = new(); - public ColumnViewModel GitLastCommitShaColumn + private DetailsLayoutColumnItem _GitLastCommitShaColumn = new(); + public DetailsLayoutColumnItem GitLastCommitShaColumn { get => _GitLastCommitShaColumn; set => SetProperty(ref _GitLastCommitShaColumn, value); } - private ColumnViewModel tagColumn = new(); - public ColumnViewModel TagColumn + private DetailsLayoutColumnItem tagColumn = new(); + public DetailsLayoutColumnItem TagColumn { get => tagColumn; set => SetProperty(ref tagColumn, value); } - private ColumnViewModel nameColumn = new() + private DetailsLayoutColumnItem nameColumn = new() { NormalMaxLength = 1000d }; - public ColumnViewModel NameColumn + public DetailsLayoutColumnItem NameColumn { get => nameColumn; set => SetProperty(ref nameColumn, value); } - private ColumnViewModel statusColumn = new() + private DetailsLayoutColumnItem statusColumn = new() { UserLength = new GridLength(50), NormalMaxLength = 80, }; - public ColumnViewModel StatusColumn + public DetailsLayoutColumnItem StatusColumn { get => statusColumn; set => SetProperty(ref statusColumn, value); } - private ColumnViewModel dateModifiedColumn = new(); - public ColumnViewModel DateModifiedColumn + private DetailsLayoutColumnItem dateModifiedColumn = new(); + public DetailsLayoutColumnItem DateModifiedColumn { get => dateModifiedColumn; set => SetProperty(ref dateModifiedColumn, value); } - private ColumnViewModel pathColumn = new() + private DetailsLayoutColumnItem pathColumn = new() { NormalMaxLength = 500, }; - public ColumnViewModel PathColumn + public DetailsLayoutColumnItem PathColumn { get => pathColumn; set => SetProperty(ref pathColumn, value); } - private ColumnViewModel originalPathColumn = new() + private DetailsLayoutColumnItem originalPathColumn = new() { NormalMaxLength = 500, }; - public ColumnViewModel OriginalPathColumn + public DetailsLayoutColumnItem OriginalPathColumn { get => originalPathColumn; set => SetProperty(ref originalPathColumn, value); } - private ColumnViewModel itemTypeColumn = new(); - public ColumnViewModel ItemTypeColumn + private DetailsLayoutColumnItem itemTypeColumn = new(); + public DetailsLayoutColumnItem ItemTypeColumn { get => itemTypeColumn; set => SetProperty(ref itemTypeColumn, value); } - private ColumnViewModel dateDeletedColumn = new(); - public ColumnViewModel DateDeletedColumn + private DetailsLayoutColumnItem dateDeletedColumn = new(); + public DetailsLayoutColumnItem DateDeletedColumn { get => dateDeletedColumn; set => SetProperty(ref dateDeletedColumn, value); } - private ColumnViewModel dateCreatedColumn = new() + private DetailsLayoutColumnItem dateCreatedColumn = new() { UserCollapsed = true }; - public ColumnViewModel DateCreatedColumn + public DetailsLayoutColumnItem DateCreatedColumn { get => dateCreatedColumn; set => SetProperty(ref dateCreatedColumn, value); } - private ColumnViewModel sizeColumn = new(); - public ColumnViewModel SizeColumn + private DetailsLayoutColumnItem sizeColumn = new(); + public DetailsLayoutColumnItem SizeColumn { get => sizeColumn; set => SetProperty(ref sizeColumn, value); @@ -160,39 +160,6 @@ public ColumnViewModel SizeColumn SizeColumn.Length.Value + StatusColumn.Length.Value; - public void SetDesiredSize(double width) - { - if (TotalWidth > width || TotalWidth < width) - { - var proportion = width / TotalWidth; - - //SetColumnSizeProportionally(proportion); - } - } - - /// - /// Multiplies every column's length by the given amount if it is within the size - /// - /// - private void SetColumnSizeProportionally(double factor) - { - NameColumn.TryMultiplySize(factor); - GitStatusColumn.TryMultiplySize(factor); - GitLastCommitDateColumn.TryMultiplySize(factor); - GitLastCommitMessageColumn.TryMultiplySize(factor); - GitCommitAuthorColumn.TryMultiplySize(factor); - GitLastCommitShaColumn.TryMultiplySize(factor); - TagColumn.TryMultiplySize(factor); - DateModifiedColumn.TryMultiplySize(factor); - PathColumn.TryMultiplySize(factor); - OriginalPathColumn.TryMultiplySize(factor); - ItemTypeColumn.TryMultiplySize(factor); - DateDeletedColumn.TryMultiplySize(factor); - DateCreatedColumn.TryMultiplySize(factor); - SizeColumn.TryMultiplySize(factor); - StatusColumn.TryMultiplySize(factor); - } - public override bool Equals(object? obj) { if (obj is null) diff --git a/src/Files.App/Data/Models/CurrentInstanceViewModel.cs b/src/Files.App/Data/Models/CurrentInstanceViewModel.cs index 1e4e5ed75ed5..1e883ab9ce90 100644 --- a/src/Files.App/Data/Models/CurrentInstanceViewModel.cs +++ b/src/Files.App/Data/Models/CurrentInstanceViewModel.cs @@ -10,16 +10,16 @@ public class CurrentInstanceViewModel : ObservableObject // a single enum property providing simplified customization of the // values being manipulated inside the setter blocks - public FolderSettingsViewModel FolderSettings { get; } + public LayoutPreferencesManager FolderSettings { get; } public CurrentInstanceViewModel() { - FolderSettings = new FolderSettingsViewModel(); + FolderSettings = new LayoutPreferencesManager(); } public CurrentInstanceViewModel(FolderLayoutModes rootLayoutMode) { - FolderSettings = new FolderSettingsViewModel(rootLayoutMode); + FolderSettings = new LayoutPreferencesManager(rootLayoutMode); } private bool isPageTypeSearchResults = false; diff --git a/src/Files.App/Data/Models/FolderSettingsViewModel.cs b/src/Files.App/Data/Models/FolderSettingsViewModel.cs deleted file mode 100644 index 70903651413e..000000000000 --- a/src/Files.App/Data/Models/FolderSettingsViewModel.cs +++ /dev/null @@ -1,659 +0,0 @@ -// Copyright (c) 2023 Files Community -// Licensed under the MIT License. See the LICENSE. - -using System.Text.Json; -using Windows.Storage; - -namespace Files.App.Data.Models -{ - public class FolderSettingsViewModel : ObservableObject - { - public static string LayoutSettingsDbPath - => SystemIO.Path.Combine(ApplicationData.Current.LocalFolder.Path, "user_settings.db"); - - private static readonly Lazy dbInstance = new(() => new LayoutPrefsDb(LayoutSettingsDbPath, true)); - - public static LayoutPrefsDb GetDbInstance() - => dbInstance.Value; - - public event EventHandler? LayoutPreferencesUpdateRequired; - - private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetRequiredService(); - - public FolderSettingsViewModel() - { - LayoutPreference = new LayoutPreferences(); - } - - public FolderSettingsViewModel(FolderLayoutModes modeOverride) : this() - => (rootLayoutMode, LayoutPreference.IsAdaptiveLayoutOverridden) = (modeOverride, true); - - private readonly FolderLayoutModes? rootLayoutMode; - - public bool IsLayoutModeFixed - => rootLayoutMode is not null; - - public bool IsAdaptiveLayoutEnabled - { - get => !LayoutPreference.IsAdaptiveLayoutOverridden; - set - { - if (SetProperty(ref LayoutPreference.IsAdaptiveLayoutOverridden, !value, nameof(IsAdaptiveLayoutEnabled))) - LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreference, true)); - } - } - - public FolderLayoutModes LayoutMode - { - get => rootLayoutMode ?? LayoutPreference.LayoutMode; - set - { - if (SetProperty(ref LayoutPreference.LayoutMode, value, nameof(LayoutMode))) - LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreference)); - } - } - - public uint GetIconSize() - { - // ListView thumbnail - if (LayoutMode == FolderLayoutModes.DetailsView) - return Constants.Browser.DetailsLayoutBrowser.DetailsViewSize; - // ListView thumbnail - else if (LayoutMode == FolderLayoutModes.ColumnView) - return Constants.Browser.ColumnViewBrowser.ColumnViewSize; - // Small thumbnail - else if (LayoutMode == FolderLayoutModes.TilesView) - return Constants.Browser.GridViewBrowser.GridViewSizeSmall; - // Small thumbnail - else if (GridViewSize <= Constants.Browser.GridViewBrowser.GridViewSizeSmall) - return Constants.Browser.GridViewBrowser.GridViewSizeSmall; - // Medium thumbnail - else if (GridViewSize <= Constants.Browser.GridViewBrowser.GridViewSizeMedium) - return Constants.Browser.GridViewBrowser.GridViewSizeMedium; - // Large thumbnail - else if (GridViewSize <= Constants.Browser.GridViewBrowser.GridViewSizeLarge) - return Constants.Browser.GridViewBrowser.GridViewSizeLarge; - // Extra large thumbnail - else - return Constants.Browser.GridViewBrowser.GridViewSizeMax; - } - - private bool isLayoutModeChanging; - public bool IsLayoutModeChanging - { - get => isLayoutModeChanging; - set => SetProperty(ref isLayoutModeChanging, value); - } - - public Type GetLayoutType(string folderPath, bool changeLayoutMode = true) - { - var prefsForPath = GetLayoutPreferencesForPath(folderPath); - if (changeLayoutMode) - { - IsLayoutModeChanging = LayoutPreference.LayoutMode != prefsForPath.LayoutMode; - LayoutPreference = prefsForPath; - } - - return (prefsForPath.LayoutMode) switch - { - FolderLayoutModes.DetailsView => typeof(DetailsLayoutPage), - FolderLayoutModes.TilesView => typeof(GridLayoutPage), - FolderLayoutModes.GridView => typeof(GridLayoutPage), - FolderLayoutModes.ColumnView => typeof(ColumnsLayoutPage), - _ => typeof(DetailsLayoutPage) - }; - } - - public event EventHandler? LayoutModeChangeRequested; - - public event EventHandler? GridViewSizeChangeRequested; - - public GridViewSizeKind GridViewSizeKind - { - get - { - if (GridViewSize < Constants.Browser.GridViewBrowser.GridViewSizeMedium) - return GridViewSizeKind.Small; - else if (GridViewSize >= Constants.Browser.GridViewBrowser.GridViewSizeMedium && GridViewSize < Constants.Browser.GridViewBrowser.GridViewSizeLarge) - return GridViewSizeKind.Medium; - else - return GridViewSizeKind.Large; - } - } - - public int GridViewSize - { - get => LayoutPreference.GridViewSize; - set - { - // Size down - if (value < LayoutPreference.GridViewSize) - { - // Size down from tiles to list - if (LayoutMode == FolderLayoutModes.TilesView) - { - LayoutPreference.IsAdaptiveLayoutOverridden = true; - LayoutMode = FolderLayoutModes.DetailsView; - LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(LayoutMode, GridViewSize)); - } - // Size down from grid to tiles - else if (LayoutMode == FolderLayoutModes.GridView && value < Constants.Browser.GridViewBrowser.GridViewSizeSmall) - { - LayoutPreference.IsAdaptiveLayoutOverridden = true; - LayoutMode = FolderLayoutModes.TilesView; - LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(LayoutMode, GridViewSize)); - } - // Resize grid view - else if (LayoutMode != FolderLayoutModes.DetailsView) - { - // Set grid size to allow immediate UI update - var newValue = (value >= Constants.Browser.GridViewBrowser.GridViewSizeSmall) ? value : Constants.Browser.GridViewBrowser.GridViewSizeSmall; - SetProperty(ref LayoutPreference.GridViewSize, newValue, nameof(GridViewSize)); - - // Only update layout mode if it isn't already in grid view - if (LayoutMode != FolderLayoutModes.GridView) - { - LayoutPreference.IsAdaptiveLayoutOverridden = true; - LayoutMode = FolderLayoutModes.GridView; - LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(LayoutMode, GridViewSize)); - } - else - { - LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreference)); - } - - GridViewSizeChangeRequested?.Invoke(this, EventArgs.Empty); - } - } - // Size up - else if (value > LayoutPreference.GridViewSize) - { - // Size up from list to tiles - if (LayoutMode == FolderLayoutModes.DetailsView) - { - LayoutPreference.IsAdaptiveLayoutOverridden = true; - LayoutMode = FolderLayoutModes.TilesView; - LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(LayoutMode, GridViewSize)); - } - else // Size up from tiles to grid - { - // Set grid size to allow immediate UI update - var newValue = (LayoutMode == FolderLayoutModes.TilesView) ? Constants.Browser.GridViewBrowser.GridViewSizeSmall : (value <= Constants.Browser.GridViewBrowser.GridViewSizeMax) ? value : Constants.Browser.GridViewBrowser.GridViewSizeMax; - SetProperty(ref LayoutPreference.GridViewSize, newValue, nameof(GridViewSize)); - - // Only update layout mode if it isn't already in grid view - if (LayoutMode != FolderLayoutModes.GridView) - { - LayoutPreference.IsAdaptiveLayoutOverridden = true; - LayoutMode = FolderLayoutModes.GridView; - LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(LayoutMode, GridViewSize)); - } - else - { - LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreference)); - } - - // Don't request a grid resize if it is already at the max size - if (value < Constants.Browser.GridViewBrowser.GridViewSizeMax) - GridViewSizeChangeRequested?.Invoke(this, EventArgs.Empty); - } - } - } - } - - public event EventHandler? SortOptionPreferenceUpdated; - - public event EventHandler? GroupOptionPreferenceUpdated; - - public event EventHandler? SortDirectionPreferenceUpdated; - - public event EventHandler? GroupDirectionPreferenceUpdated; - - public event EventHandler? GroupByDateUnitPreferenceUpdated; - - public event EventHandler? SortDirectoriesAlongsideFilesPreferenceUpdated; - - public SortOption DirectorySortOption - { - get => LayoutPreference.DirectorySortOption; - set - { - if (SetProperty(ref LayoutPreference.DirectorySortOption, value, nameof(DirectorySortOption))) - { - LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreference)); - SortOptionPreferenceUpdated?.Invoke(this, DirectorySortOption); - } - } - } - - public GroupOption DirectoryGroupOption - { - get => LayoutPreference.DirectoryGroupOption; - set - { - if (SetProperty(ref LayoutPreference.DirectoryGroupOption, value, nameof(DirectoryGroupOption))) - { - LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreference)); - GroupOptionPreferenceUpdated?.Invoke(this, DirectoryGroupOption); - } - } - } - - public SortDirection DirectorySortDirection - { - get => LayoutPreference.DirectorySortDirection; - set - { - if (SetProperty(ref LayoutPreference.DirectorySortDirection, value, nameof(DirectorySortDirection))) - { - LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreference)); - SortDirectionPreferenceUpdated?.Invoke(this, DirectorySortDirection); - } - } - } - - public SortDirection DirectoryGroupDirection - { - get => LayoutPreference.DirectoryGroupDirection; - set - { - if (SetProperty(ref LayoutPreference.DirectoryGroupDirection, value, nameof(DirectoryGroupDirection))) - { - LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreference)); - GroupDirectionPreferenceUpdated?.Invoke(this, DirectoryGroupDirection); - } - } - } - - public GroupByDateUnit DirectoryGroupByDateUnit - { - get => LayoutPreference.DirectoryGroupByDateUnit; - set - { - if (SetProperty(ref LayoutPreference.DirectoryGroupByDateUnit, value, nameof(DirectoryGroupByDateUnit))) - { - LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreference)); - GroupByDateUnitPreferenceUpdated?.Invoke(this, DirectoryGroupByDateUnit); - } - } - } - - public bool SortDirectoriesAlongsideFiles - { - get - { - return LayoutPreference.SortDirectoriesAlongsideFiles; - } - set - { - if (SetProperty(ref LayoutPreference.SortDirectoriesAlongsideFiles, value, nameof(SortDirectoriesAlongsideFiles))) - { - LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreference)); - SortDirectoriesAlongsideFilesPreferenceUpdated?.Invoke(this, SortDirectoriesAlongsideFiles); - } - } - } - - public ColumnsViewModel ColumnsViewModel - { - get => LayoutPreference.ColumnsViewModel; - set - { - SetProperty(ref LayoutPreference.ColumnsViewModel, value, nameof(ColumnsViewModel)); - LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreference)); - } - } - - private static LayoutPreferences GetLayoutPreferencesForPath(string folderPath) - { - IUserSettingsService userSettingsService = Ioc.Default.GetRequiredService(); - if (!userSettingsService.FoldersSettingsService.SyncFolderPreferencesAcrossDirectories) - { - folderPath = folderPath.TrimPath(); - var folderFRN = NativeFileOperationsHelper.GetFolderFRN(folderPath); - return ReadLayoutPreferencesFromDb(folderPath, folderFRN) - ?? ReadLayoutPreferencesFromAds(folderPath, folderFRN) - ?? GetDefaultLayoutPreferences(folderPath); - } - - return LayoutPreferences.DefaultLayoutPreferences; - } - - public static void SetLayoutPreferencesForPath(string folderPath, LayoutPreferences prefs) - { - IUserSettingsService userSettingsService = Ioc.Default.GetRequiredService(); - - if (!userSettingsService.FoldersSettingsService.SyncFolderPreferencesAcrossDirectories) - { - var folderFRN = NativeFileOperationsHelper.GetFolderFRN(folderPath); - var trimmedFolderPath = folderPath.TrimPath(); - if (trimmedFolderPath is not null) - WriteLayoutPreferencesToDb(trimmedFolderPath, folderFRN, prefs); - } - else - { - userSettingsService.FoldersSettingsService.DefaultLayoutMode = prefs.LayoutMode; - userSettingsService.LayoutSettingsService.DefaultGridViewSize = prefs.GridViewSize; - - // Do not save options which only work in recycle bin or cloud folders or search results as global - if (prefs.DirectorySortOption != SortOption.Path && - prefs.DirectorySortOption != SortOption.OriginalFolder && - prefs.DirectorySortOption != SortOption.DateDeleted && - prefs.DirectorySortOption != SortOption.SyncStatus) - { - userSettingsService.FoldersSettingsService.DefaultSortOption = prefs.DirectorySortOption; - } - - if (prefs.DirectoryGroupOption != GroupOption.OriginalFolder && - prefs.DirectoryGroupOption != GroupOption.DateDeleted && - prefs.DirectoryGroupOption != GroupOption.FolderPath && - prefs.DirectoryGroupOption != GroupOption.SyncStatus) - { - userSettingsService.FoldersSettingsService.DefaultGroupOption = prefs.DirectoryGroupOption; - } - - userSettingsService.FoldersSettingsService.DefaultDirectorySortDirection = prefs.DirectorySortDirection; - userSettingsService.FoldersSettingsService.DefaultDirectoryGroupDirection = prefs.DirectoryGroupDirection; - userSettingsService.FoldersSettingsService.DefaultGroupByDateUnit = prefs.DirectoryGroupByDateUnit; - userSettingsService.FoldersSettingsService.DefaultSortDirectoriesAlongsideFiles = prefs.SortDirectoriesAlongsideFiles; - - userSettingsService.FoldersSettingsService.NameColumnWidth = prefs.ColumnsViewModel.NameColumn.UserLengthPixels; - if (!prefs.ColumnsViewModel.DateModifiedColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowDateColumn = !prefs.ColumnsViewModel.DateModifiedColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.DateModifiedColumnWidth = prefs.ColumnsViewModel.DateModifiedColumn.UserLengthPixels; - } - if (!prefs.ColumnsViewModel.DateCreatedColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowDateCreatedColumn = !prefs.ColumnsViewModel.DateCreatedColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.DateCreatedColumnWidth = prefs.ColumnsViewModel.DateCreatedColumn.UserLengthPixels; - } - if (!prefs.ColumnsViewModel.ItemTypeColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowTypeColumn = !prefs.ColumnsViewModel.ItemTypeColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.TypeColumnWidth = prefs.ColumnsViewModel.ItemTypeColumn.UserLengthPixels; - } - if (!prefs.ColumnsViewModel.SizeColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowSizeColumn = !prefs.ColumnsViewModel.SizeColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.SizeColumnWidth = prefs.ColumnsViewModel.SizeColumn.UserLengthPixels; - } - if (!prefs.ColumnsViewModel.TagColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowFileTagColumn = !prefs.ColumnsViewModel.TagColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.TagColumnWidth = prefs.ColumnsViewModel.TagColumn.UserLengthPixels; - } - if (!prefs.ColumnsViewModel.GitStatusColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowGitStatusColumn = !prefs.ColumnsViewModel.GitStatusColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.GitStatusColumnWidth = prefs.ColumnsViewModel.GitStatusColumn.UserLengthPixels; - } - if (!prefs.ColumnsViewModel.GitLastCommitDateColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowGitLastCommitDateColumn = !prefs.ColumnsViewModel.GitLastCommitDateColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.GitLastCommitDateColumnWidth = prefs.ColumnsViewModel.GitLastCommitDateColumn.UserLengthPixels; - } - if (!prefs.ColumnsViewModel.GitLastCommitMessageColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowGitLastCommitMessageColumn = !prefs.ColumnsViewModel.GitLastCommitMessageColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.GitLastCommitMessageColumnWidth = prefs.ColumnsViewModel.GitLastCommitMessageColumn.UserLengthPixels; - } - if (!prefs.ColumnsViewModel.GitCommitAuthorColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowGitCommitAuthorColumn = !prefs.ColumnsViewModel.GitCommitAuthorColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.GitCommitAuthorColumnWidth = prefs.ColumnsViewModel.GitCommitAuthorColumn.UserLengthPixels; - } - if (!prefs.ColumnsViewModel.GitLastCommitShaColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowGitLastCommitShaColumn = !prefs.ColumnsViewModel.GitLastCommitShaColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.GitLastCommitShaColumnWidth = prefs.ColumnsViewModel.GitLastCommitShaColumn.UserLengthPixels; - } - if (!prefs.ColumnsViewModel.DateDeletedColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowDateDeletedColumn = !prefs.ColumnsViewModel.DateDeletedColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.DateDeletedColumnWidth = prefs.ColumnsViewModel.DateDeletedColumn.UserLengthPixels; - } - if (!prefs.ColumnsViewModel.PathColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowPathColumn = !prefs.ColumnsViewModel.PathColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.PathColumnWidth = prefs.ColumnsViewModel.PathColumn.UserLengthPixels; - } - if (!prefs.ColumnsViewModel.OriginalPathColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowOriginalPathColumn = !prefs.ColumnsViewModel.OriginalPathColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.OriginalPathColumnWidth = prefs.ColumnsViewModel.OriginalPathColumn.UserLengthPixels; - } - if (!prefs.ColumnsViewModel.StatusColumn.IsHidden) - { - userSettingsService.FoldersSettingsService.ShowSyncStatusColumn = !prefs.ColumnsViewModel.StatusColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.SyncStatusColumnWidth = prefs.ColumnsViewModel.StatusColumn.UserLengthPixels; - } - } - } - - private static LayoutPreferences ReadLayoutPreferencesFromAds(string folderPath, ulong? frn) - { - var str = NativeFileOperationsHelper.ReadStringFromFile($"{folderPath}:files_layoutmode"); - - var adsPrefs = SafetyExtensions.IgnoreExceptions(() => - string.IsNullOrEmpty(str) ? null : JsonSerializer.Deserialize(str)); - - // Port settings to DB, delete ADS - WriteLayoutPreferencesToDb(folderPath, frn, adsPrefs); - NativeFileOperationsHelper.DeleteFileFromApp($"{folderPath}:files_layoutmode"); - - return adsPrefs; - } - - private static LayoutPreferences? ReadLayoutPreferencesFromDb(string folderPath, ulong? frn) - { - if (string.IsNullOrEmpty(folderPath)) - return null; - - var dbInstance = GetDbInstance(); - - return dbInstance.GetPreferences(folderPath, frn); - } - - private static LayoutPreferences GetDefaultLayoutPreferences(string folderPath) - { - if (string.IsNullOrEmpty(folderPath)) - return LayoutPreferences.DefaultLayoutPreferences; - - if (folderPath == Constants.UserEnvironmentPaths.DownloadsPath) - // Default for downloads folder is to group by date created - return new LayoutPreferences() - { - DirectoryGroupOption = GroupOption.DateCreated, - DirectoryGroupDirection = SortDirection.Descending, - DirectoryGroupByDateUnit = GroupByDateUnit.Year - }; - else if (LibraryManager.IsLibraryPath(folderPath)) - // Default for libraries is to group by folder path - return new LayoutPreferences() { DirectoryGroupOption = GroupOption.FolderPath }; - else - // Either global setting or smart guess - return LayoutPreferences.DefaultLayoutPreferences; - } - - private static void WriteLayoutPreferencesToDb(string folderPath, ulong? frn, LayoutPreferences prefs) - { - if (string.IsNullOrEmpty(folderPath)) - return; - - var dbInstance = GetDbInstance(); - if (dbInstance.GetPreferences(folderPath, frn) is null && - LayoutPreferences.DefaultLayoutPreferences.Equals(prefs)) - { - // Do not create setting if it's default - return; - } - - dbInstance.SetPreferences(folderPath, frn, prefs); - } - - private LayoutPreferences layoutPreference; - - public LayoutPreferences LayoutPreference - { - get => layoutPreference; - private set - { - if (SetProperty(ref layoutPreference, value)) - { - OnPropertyChanged(nameof(LayoutMode)); - OnPropertyChanged(nameof(GridViewSize)); - OnPropertyChanged(nameof(GridViewSizeKind)); - OnPropertyChanged(nameof(IsAdaptiveLayoutEnabled)); - OnPropertyChanged(nameof(DirectoryGroupOption)); - OnPropertyChanged(nameof(DirectorySortOption)); - OnPropertyChanged(nameof(DirectorySortDirection)); - OnPropertyChanged(nameof(DirectoryGroupDirection)); - OnPropertyChanged(nameof(DirectoryGroupByDateUnit)); - OnPropertyChanged(nameof(SortDirectoriesAlongsideFiles)); - OnPropertyChanged(nameof(ColumnsViewModel)); - } - } - } - - public void ToggleLayoutModeGridViewLarge(bool manuallySet) - { - IsAdaptiveLayoutEnabled &= !manuallySet; - - // Grid View - LayoutMode = FolderLayoutModes.GridView; - - // Size - GridViewSize = Constants.Browser.GridViewBrowser.GridViewSizeLarge; - - LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.GridView, GridViewSize)); - } - - public void ToggleLayoutModeColumnView(bool manuallySet) - { - IsAdaptiveLayoutEnabled &= !manuallySet; - - // Column View - LayoutMode = FolderLayoutModes.ColumnView; - - LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.ColumnView, GridViewSize)); - } - - public void ToggleLayoutModeGridViewMedium(bool manuallySet) - { - IsAdaptiveLayoutEnabled &= !manuallySet; - - // Grid View - LayoutMode = FolderLayoutModes.GridView; - - // Size - GridViewSize = Constants.Browser.GridViewBrowser.GridViewSizeMedium; - - LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.GridView, GridViewSize)); - } - - public void ToggleLayoutModeGridViewSmall(bool manuallySet) - { - IsAdaptiveLayoutEnabled &= !manuallySet; - - // Grid View - LayoutMode = FolderLayoutModes.GridView; - - // Size - GridViewSize = Constants.Browser.GridViewBrowser.GridViewSizeSmall; - - LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.GridView, GridViewSize)); - } - - public void ToggleLayoutModeGridView(int size) - { - // Grid View - LayoutMode = FolderLayoutModes.GridView; - - // Size - GridViewSize = size; - - LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(LayoutMode, GridViewSize)); - } - - public void ToggleLayoutModeTiles(bool manuallySet) - { - IsAdaptiveLayoutEnabled &= !manuallySet; - - // Tiles View - LayoutMode = FolderLayoutModes.TilesView; - - LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.TilesView, GridViewSize)); - } - - public void ToggleLayoutModeDetailsView(bool manuallySet) - { - IsAdaptiveLayoutEnabled &= !manuallySet; - - // Details View - LayoutMode = FolderLayoutModes.DetailsView; - - LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.DetailsView, GridViewSize)); - } - - public void ToggleLayoutModeAdaptive() - { - // Adaptive - IsAdaptiveLayoutEnabled = true; - - LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.Adaptive, GridViewSize)); - } - - public void OnDefaultPreferencesChanged(string folderPath, string settingsName) - { - var prefs = GetLayoutPreferencesForPath(folderPath); - - switch (settingsName) - { - case nameof(UserSettingsService.FoldersSettingsService.DefaultSortDirectoriesAlongsideFiles): - SortDirectoriesAlongsideFiles = prefs.SortDirectoriesAlongsideFiles; - break; - case nameof(UserSettingsService.FoldersSettingsService.SyncFolderPreferencesAcrossDirectories): - LayoutPreference = prefs; - // TODO: Update layout - break; - } - } - - public void SetDefaultLayoutPreferences(ColumnsViewModel columns) - { - IUserSettingsService userSettingsService = Ioc.Default.GetRequiredService(); - - userSettingsService.FoldersSettingsService.ShowDateColumn = !columns.DateModifiedColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.ShowDateCreatedColumn = !columns.DateCreatedColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.ShowTypeColumn = !columns.ItemTypeColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.ShowSizeColumn = !columns.SizeColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.ShowFileTagColumn = !columns.TagColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.ShowGitStatusColumn = !columns.GitStatusColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.ShowGitLastCommitDateColumn = !columns.GitLastCommitDateColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.ShowGitLastCommitMessageColumn = !columns.GitLastCommitMessageColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.ShowGitCommitAuthorColumn = !columns.GitCommitAuthorColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.ShowGitLastCommitShaColumn = !columns.GitLastCommitShaColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.ShowDateDeletedColumn = !columns.DateDeletedColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.ShowPathColumn = !columns.PathColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.ShowOriginalPathColumn = !columns.OriginalPathColumn.UserCollapsed; - userSettingsService.FoldersSettingsService.ShowSyncStatusColumn = !columns.StatusColumn.UserCollapsed; - - userSettingsService.FoldersSettingsService.NameColumnWidth = columns.NameColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.DateModifiedColumnWidth = columns.DateModifiedColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.DateCreatedColumnWidth = columns.DateCreatedColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.TypeColumnWidth = columns.ItemTypeColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.SizeColumnWidth = columns.SizeColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.TagColumnWidth = columns.TagColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.GitStatusColumnWidth = columns.GitStatusColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.GitLastCommitDateColumnWidth = columns.GitLastCommitDateColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.GitLastCommitMessageColumnWidth = columns.GitLastCommitMessageColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.GitCommitAuthorColumnWidth = columns.GitCommitAuthorColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.GitLastCommitShaColumnWidth = columns.GitLastCommitShaColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.DateDeletedColumnWidth = columns.DateDeletedColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.PathColumnWidth = columns.PathColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.OriginalPathColumnWidth = columns.OriginalPathColumn.UserLengthPixels; - userSettingsService.FoldersSettingsService.SyncStatusColumnWidth = columns.StatusColumn.UserLengthPixels; - } - } -} diff --git a/src/Files.App/Data/Models/ItemViewModel.cs b/src/Files.App/Data/Models/ItemViewModel.cs index 41f50b6e107f..1b6b5fe6a0c9 100644 --- a/src/Files.App/Data/Models/ItemViewModel.cs +++ b/src/Files.App/Data/Models/ItemViewModel.cs @@ -53,7 +53,7 @@ public sealed class ItemViewModel : ObservableObject, IDisposable // Only used for Binding and ApplyFilesAndFoldersChangesAsync, don't manipulate on this! public BulkConcurrentObservableCollection FilesAndFolders { get; } - private FolderSettingsViewModel folderSettings = null; + private LayoutPreferencesManager folderSettings = null; private ListedItem? currentFolder; public ListedItem? CurrentFolder @@ -408,7 +408,7 @@ public bool AreDirectoriesSortedAlongsideFiles public bool HasNoWatcher { get; private set; } - public ItemViewModel(FolderSettingsViewModel folderSettingsViewModel) + public ItemViewModel(LayoutPreferencesManager folderSettingsViewModel) { folderSettings = folderSettingsViewModel; filesAndFolders = new ConcurrentCollection(); diff --git a/src/Files.App/Helpers/ContentLayout/LayoutPrefsDb.cs b/src/Files.App/Helpers/ContentLayout/LayoutPrefsDb.cs deleted file mode 100644 index cad8a8b1e045..000000000000 --- a/src/Files.App/Helpers/ContentLayout/LayoutPrefsDb.cs +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2023 Files Community -// Licensed under the MIT License. See the LICENSE. - -using Files.Shared.Extensions; -using LiteDB; -using System; -using System.Linq; -using System.Text; -using IO = System.IO; - -namespace Files.App.Helpers -{ - public class LayoutPrefsDb : IDisposable - { - private readonly LiteDatabase db; - - public LayoutPrefsDb(string connection, bool shared = false) - { - SafetyExtensions.IgnoreExceptions(() => CheckDbVersion(connection)); - db = new LiteDatabase(new ConnectionString(connection) - { - Mode = shared ? LiteDB.FileMode.Shared : LiteDB.FileMode.Exclusive - }, new BsonMapper() { IncludeFields = true }); - } - - public void SetPreferences(string filePath, ulong? frn, LayoutPreferences? prefs) - { - // Get a collection (or create, if doesn't exist) - var col = db.GetCollection("layoutprefs"); - - var tmp = _FindPreferences(filePath, frn); - if (tmp is null) - { - if (prefs is not null) - { - // Insert new tagged file (Id will be auto-incremented) - var newPref = new LayoutDbPrefs() - { - FilePath = filePath, - Frn = frn, - Prefs = prefs - }; - col.Insert(newPref); - col.EnsureIndex(x => x.Frn); - col.EnsureIndex(x => x.FilePath); - } - } - else - { - if (prefs is not null) - { - // Update file tag - tmp.Prefs = prefs; - col.Update(tmp); - } - else - { - // Remove file tag - col.Delete(tmp.Id); - } - } - } - - public LayoutPreferences? GetPreferences(string? filePath = null, ulong? frn = null) - { - return _FindPreferences(filePath, frn)?.Prefs; - } - - private LayoutDbPrefs? _FindPreferences(string? filePath = null, ulong? frn = null) - { - // Get a collection (or create, if doesn't exist) - var col = db.GetCollection("layoutprefs"); - - if (filePath is not null) - { - var tmp = col.FindOne(x => x.FilePath == filePath); - if (tmp is not null) - { - if (frn is not null) - { - // Keep entry updated - tmp.Frn = frn; - col.Update(tmp); - } - return tmp; - } - } - if (frn is not null) - { - var tmp = col.FindOne(x => x.Frn == frn); - if (tmp is not null) - { - if (filePath is not null) - { - // Keep entry updated - tmp.FilePath = filePath; - col.Update(tmp); - } - return tmp; - } - } - return null; - } - - public void ResetAll(Func? predicate = null) - { - var col = db.GetCollection("layoutprefs"); - if (predicate is null) - { - col.Delete(Query.All()); - } - else - { - col.Delete(x => predicate(x)); - } - } - - public void ApplyToAll(Action updateAction, Func? predicate = null) - { - var col = db.GetCollection("layoutprefs"); - var allDocs = predicate is null ? col.FindAll() : col.Find(x => predicate(x)); - allDocs.ForEach(x => updateAction(x)); - col.Update(allDocs); - } - - ~LayoutPrefsDb() - { - Dispose(); - } - - public void Dispose() - { - db.Dispose(); - } - - public void Import(string json) - { - var dataValues = JsonSerializer.DeserializeArray(json); - var col = db.GetCollection("layoutprefs"); - col.Delete(Query.All()); - col.InsertBulk(dataValues.Select(x => x.AsDocument)); - } - - public string Export() - { - return JsonSerializer.Serialize(new BsonArray(db.GetCollection("layoutprefs").FindAll())); - } - - // https://github.com/mbdavid/LiteDB/blob/master/LiteDB/Engine/Engine/Upgrade.cs - private void CheckDbVersion(string filename) - { - var buffer = new byte[8192 * 2]; - using (var stream = new IO.FileStream(filename, IO.FileMode.Open, IO.FileAccess.Read, IO.FileShare.ReadWrite)) - { - // read first 16k - stream.Read(buffer, 0, buffer.Length); - - // checks if v7 (plain or encrypted) - if (Encoding.UTF8.GetString(buffer, 25, "** This is a LiteDB file **".Length) == "** This is a LiteDB file **" && - buffer[52] == 7) - { - return; // version 4.1.4 - } - } - IO.File.Delete(filename); // recreate DB with correct version - } - - public class LayoutDbPrefs - { - [BsonId] - public int Id { get; set; } - public ulong? Frn { get; set; } - public string FilePath { get; set; } = string.Empty; - public LayoutPreferences Prefs { get; set; } = LayoutPreferences.DefaultLayoutPreferences; - } - } -} diff --git a/src/Files.App/Helpers/ContentLayout/AdaptiveLayoutHelpers.cs b/src/Files.App/Helpers/Layout/AdaptiveLayoutHelpers.cs similarity index 92% rename from src/Files.App/Helpers/ContentLayout/AdaptiveLayoutHelpers.cs rename to src/Files.App/Helpers/Layout/AdaptiveLayoutHelpers.cs index ab48e2df70e7..a3ccc154d496 100644 --- a/src/Files.App/Helpers/ContentLayout/AdaptiveLayoutHelpers.cs +++ b/src/Files.App/Helpers/Layout/AdaptiveLayoutHelpers.cs @@ -12,11 +12,11 @@ namespace Files.App.Helpers { public static class AdaptiveLayoutHelpers { - private static readonly IFoldersSettingsService foldersSettingsService = Ioc.Default.GetRequiredService(); + private static IFoldersSettingsService FoldersSettingsService { get; } = Ioc.Default.GetRequiredService(); - public static void ApplyAdaptativeLayout(FolderSettingsViewModel folderSettings, string path, IList filesAndFolders) + public static void ApplyAdaptativeLayout(LayoutPreferencesManager folderSettings, string path, IList filesAndFolders) { - if (foldersSettingsService.SyncFolderPreferencesAcrossDirectories) + if (FoldersSettingsService.SyncFolderPreferencesAcrossDirectories) return; if (string.IsNullOrWhiteSpace(path)) return; diff --git a/src/Files.App/Helpers/Layout/LayoutPreferencesDatabaseItem.cs b/src/Files.App/Helpers/Layout/LayoutPreferencesDatabaseItem.cs new file mode 100644 index 000000000000..202ff4304dea --- /dev/null +++ b/src/Files.App/Helpers/Layout/LayoutPreferencesDatabaseItem.cs @@ -0,0 +1,22 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +using LiteDB; + +namespace Files.App.Helpers +{ + /// + /// Represents item for the database of a folder's layout preferences. + /// + public class LayoutPreferencesDatabaseItem + { + [BsonId] + public int Id { get; set; } + + public ulong? Frn { get; set; } + + public string FilePath { get; set; } = string.Empty; + + public LayoutPreferencesItem LayoutPreferencesManager { get; set; } = new(); + } +} diff --git a/src/Files.App/Helpers/Layout/LayoutPreferencesDatabaseManager.cs b/src/Files.App/Helpers/Layout/LayoutPreferencesDatabaseManager.cs new file mode 100644 index 000000000000..7b2daa52f4e3 --- /dev/null +++ b/src/Files.App/Helpers/Layout/LayoutPreferencesDatabaseManager.cs @@ -0,0 +1,200 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +using LiteDB; +using System.Text; + +namespace Files.App.Helpers +{ + /// + /// Represents manager for the database of layout preferences. + /// + public class LayoutPreferencesDatabaseManager : IDisposable + { + // Fields + + private readonly LiteDatabase _database; + + // Constructor + + public LayoutPreferencesDatabaseManager(string connection, bool shared = false) + { + SafetyExtensions.IgnoreExceptions(() => EnsureDatabaseVersion(connection)); + + _database = new( + new ConnectionString(connection) + { + Mode = shared + ? FileMode.Shared + : FileMode.Exclusive + }, + new() + { + IncludeFields = true + }); + } + + // Methods + + public LayoutPreferencesItem? GetPreferences(string? filePath = null, ulong? frn = null) + { + return FindPreferences(filePath, frn)?.LayoutPreferencesManager; + } + + public void SetPreferences(string filePath, ulong? frn, LayoutPreferencesItem? preferencesItem) + { + // Get a collection (or create, if doesn't exist) + var col = _database.GetCollection("layoutprefs"); + + var tmp = FindPreferences(filePath, frn); + + if (tmp is null) + { + if (preferencesItem is not null) + { + // Insert new tagged file (Id will be auto-incremented) + var newPref = new LayoutPreferencesDatabaseItem() + { + FilePath = filePath, + Frn = frn, + LayoutPreferencesManager = preferencesItem + }; + + col.Insert(newPref); + col.EnsureIndex(x => x.Frn); + col.EnsureIndex(x => x.FilePath); + } + } + else + { + if (preferencesItem is not null) + { + // Update file tag + tmp.LayoutPreferencesManager = preferencesItem; + col.Update(tmp); + } + else + { + // Remove file tag + col.Delete(tmp.Id); + } + } + } + + public void ResetAll(Func? predicate = null) + { + var col = _database.GetCollection("layoutprefs"); + + if (predicate is null) + { + col.Delete(Query.All()); + } + else + { + col.Delete(x => predicate(x)); + } + } + + public void ApplyToAll(Action updateAction, Func? predicate = null) + { + var col = _database.GetCollection("layoutprefs"); + + var allDocs = predicate is null ? col.FindAll() : col.Find(x => predicate(x)); + + allDocs.ForEach(x => updateAction(x)); + col.Update(allDocs); + } + + public void Import(string json) + { + var dataValues = JsonSerializer.DeserializeArray(json); + + var col = _database.GetCollection("layoutprefs"); + + col.Delete(Query.All()); + col.InsertBulk(dataValues.Select(x => x.AsDocument)); + } + + public string Export() + { + return JsonSerializer.Serialize(new BsonArray(_database.GetCollection("layoutprefs").FindAll())); + } + + private LayoutPreferencesDatabaseItem? FindPreferences(string? filePath = null, ulong? frn = null) + { + // Get a collection (or create, if doesn't exist) + var col = _database.GetCollection("layoutprefs"); + + if (filePath is not null) + { + var tmp = col.FindOne(x => x.FilePath == filePath); + if (tmp is not null) + { + if (frn is not null) + { + // Keep entry updated + tmp.Frn = frn; + col.Update(tmp); + } + + return tmp; + } + } + + if (frn is not null) + { + var tmp = col.FindOne(x => x.Frn == frn); + if (tmp is not null) + { + if (filePath is not null) + { + // Keep entry updated + tmp.FilePath = filePath; + col.Update(tmp); + } + + return tmp; + } + } + + return null; + } + + private void EnsureDatabaseVersion(string filename) + { + // NOTE: + // For more information, visit + // https://github.com/mbdavid/LiteDB/blob/master/LiteDB/Engine/Engine/Upgrade.cs + + var buffer = new byte[8192 * 2]; + + using var stream = new SystemIO.FileStream(filename, SystemIO.FileMode.Open, SystemIO.FileAccess.Read, SystemIO.FileShare.ReadWrite); + + // Read first 16k + stream.Read(buffer, 0, buffer.Length); + + // Check if v7 (plain or encrypted) + if (Encoding.UTF8.GetString(buffer, 25, "** This is a LiteDB file **".Length) == "** This is a LiteDB file **" && + buffer[52] == 7) + { + // version 4.1.4 + return; + } + + // Re-create database with correct version + SystemIO.File.Delete(filename); + } + + // De-constructor & Disposer + + ~LayoutPreferencesDatabaseManager() + { + Dispose(); + } + + public void Dispose() + { + _database.Dispose(); + } + } +} diff --git a/src/Files.App/Helpers/ContentLayout/LayoutPreferences.cs b/src/Files.App/Helpers/Layout/LayoutPreferencesItem.cs similarity index 78% rename from src/Files.App/Helpers/ContentLayout/LayoutPreferences.cs rename to src/Files.App/Helpers/Layout/LayoutPreferencesItem.cs index ebadec0e993f..4bc07f010907 100644 --- a/src/Files.App/Helpers/ContentLayout/LayoutPreferences.cs +++ b/src/Files.App/Helpers/Layout/LayoutPreferencesItem.cs @@ -3,26 +3,35 @@ namespace Files.App.Helpers { - public class LayoutPreferences + /// + /// Represents item for a folder's layout preferences. + /// + public class LayoutPreferencesItem { + // Dependency injections + private IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetRequiredService(); + // Fields + + public ColumnsViewModel ColumnsViewModel; + + public bool SortDirectoriesAlongsideFiles; + public bool IsAdaptiveLayoutOverridden; + public int GridViewSize; + + public FolderLayoutModes LayoutMode; + public SortOption DirectorySortOption; public SortDirection DirectorySortDirection; - public bool SortDirectoriesAlongsideFiles; - public GroupOption DirectoryGroupOption; public SortDirection DirectoryGroupDirection; - public GroupByDateUnit DirectoryGroupByDateUnit; - public FolderLayoutModes LayoutMode; - public int GridViewSize; - public bool IsAdaptiveLayoutOverridden; - public ColumnsViewModel ColumnsViewModel; + public GroupOption DirectoryGroupOption; + public GroupByDateUnit DirectoryGroupByDateUnit; - [LiteDB.BsonIgnore] - public static LayoutPreferences DefaultLayoutPreferences => new LayoutPreferences(); + // Constructor - public LayoutPreferences() + public LayoutPreferencesItem() { var defaultLayout = UserSettingsService.FoldersSettingsService.DefaultLayoutMode; @@ -69,6 +78,8 @@ public LayoutPreferences() ColumnsViewModel.StatusColumn.UserLengthPixels = UserSettingsService.FoldersSettingsService.SyncStatusColumnWidth; } + // Overridden methods + public override bool Equals(object? obj) { if (obj is null) @@ -77,36 +88,39 @@ public override bool Equals(object? obj) if (obj == this) return true; - if (obj is LayoutPreferences prefs) + if (obj is LayoutPreferencesItem item) { return ( - prefs.LayoutMode == LayoutMode && - prefs.GridViewSize == GridViewSize && - prefs.DirectoryGroupOption == DirectoryGroupOption && - prefs.DirectorySortOption == DirectorySortOption && - prefs.DirectorySortDirection == DirectorySortDirection && - prefs.DirectoryGroupDirection == DirectoryGroupDirection && - prefs.DirectoryGroupByDateUnit == DirectoryGroupByDateUnit && - prefs.SortDirectoriesAlongsideFiles == SortDirectoriesAlongsideFiles && - prefs.IsAdaptiveLayoutOverridden == IsAdaptiveLayoutOverridden && - prefs.ColumnsViewModel.Equals(ColumnsViewModel)); + item.LayoutMode == LayoutMode && + item.GridViewSize == GridViewSize && + item.DirectoryGroupOption == DirectoryGroupOption && + item.DirectorySortOption == DirectorySortOption && + item.DirectorySortDirection == DirectorySortDirection && + item.DirectoryGroupDirection == DirectoryGroupDirection && + item.DirectoryGroupByDateUnit == DirectoryGroupByDateUnit && + item.SortDirectoriesAlongsideFiles == SortDirectoriesAlongsideFiles && + item.IsAdaptiveLayoutOverridden == IsAdaptiveLayoutOverridden && + item.ColumnsViewModel.Equals(ColumnsViewModel)); } return base.Equals(obj); } public override int GetHashCode() { - var hashCode = LayoutMode.GetHashCode(); - hashCode = (hashCode * 397) ^ GridViewSize.GetHashCode(); - hashCode = (hashCode * 397) ^ DirectoryGroupOption.GetHashCode(); - hashCode = (hashCode * 397) ^ DirectorySortOption.GetHashCode(); - hashCode = (hashCode * 397) ^ DirectorySortDirection.GetHashCode(); - hashCode = (hashCode * 397) ^ DirectoryGroupDirection.GetHashCode(); - hashCode = (hashCode * 397) ^ DirectoryGroupByDateUnit.GetHashCode(); - hashCode = (hashCode * 397) ^ SortDirectoriesAlongsideFiles.GetHashCode(); - hashCode = (hashCode * 397) ^ IsAdaptiveLayoutOverridden.GetHashCode(); - hashCode = (hashCode * 397) ^ ColumnsViewModel.GetHashCode(); - return hashCode; + HashCode hash = new(); + + hash.Add(LayoutMode); + hash.Add(GridViewSize); + hash.Add(DirectoryGroupOption); + hash.Add(DirectorySortOption); + hash.Add(DirectorySortDirection); + hash.Add(DirectoryGroupDirection); + hash.Add(DirectoryGroupByDateUnit); + hash.Add(SortDirectoriesAlongsideFiles); + hash.Add(IsAdaptiveLayoutOverridden); + hash.Add(ColumnsViewModel); + + return hash.ToHashCode(); } } } diff --git a/src/Files.App/Helpers/Layout/LayoutPreferencesManager.cs b/src/Files.App/Helpers/Layout/LayoutPreferencesManager.cs new file mode 100644 index 000000000000..dfd685ca398f --- /dev/null +++ b/src/Files.App/Helpers/Layout/LayoutPreferencesManager.cs @@ -0,0 +1,680 @@ +// Copyright (c) 2023 Files Community +// Licensed under the MIT License. See the LICENSE. + +using System.Text.Json; +using Windows.Storage; + +namespace Files.App.Data.Models +{ + /// + /// Represents manager for layout preferences settings. + /// + public class LayoutPreferencesManager : ObservableObject + { + // Dependency injections + + private static IUserSettingsService UserSettingsService { get; } = Ioc.Default.GetRequiredService(); + + // Fields + + private static readonly Lazy _databaseInstance = + new(() => new LayoutPreferencesDatabaseManager(LayoutSettingsDbPath, true)); + + private readonly FolderLayoutModes? _rootLayoutMode; + + // Properties + + public static string LayoutSettingsDbPath + => SystemIO.Path.Combine(ApplicationData.Current.LocalFolder.Path, "user_settings.db"); + + public bool IsLayoutModeFixed + => _rootLayoutMode is not null; + + public bool IsAdaptiveLayoutEnabled + { + get => !LayoutPreferencesItem.IsAdaptiveLayoutOverridden; + set + { + if (SetProperty(ref LayoutPreferencesItem.IsAdaptiveLayoutOverridden, !value, nameof(IsAdaptiveLayoutEnabled))) + LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreferencesItem, true)); + } + } + + public int GridViewSize + { + get => LayoutPreferencesItem.GridViewSize; + set + { + // Size down + if (value < LayoutPreferencesItem.GridViewSize) + { + // Size down from tiles to list + if (LayoutMode == FolderLayoutModes.TilesView) + { + LayoutPreferencesItem.IsAdaptiveLayoutOverridden = true; + LayoutMode = FolderLayoutModes.DetailsView; + LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(LayoutMode, GridViewSize)); + } + // Size down from grid to tiles + else if (LayoutMode == FolderLayoutModes.GridView && value < Constants.Browser.GridViewBrowser.GridViewSizeSmall) + { + LayoutPreferencesItem.IsAdaptiveLayoutOverridden = true; + LayoutMode = FolderLayoutModes.TilesView; + LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(LayoutMode, GridViewSize)); + } + // Resize grid view + else if (LayoutMode != FolderLayoutModes.DetailsView) + { + // Set grid size to allow immediate UI update + var newValue = (value >= Constants.Browser.GridViewBrowser.GridViewSizeSmall) ? value : Constants.Browser.GridViewBrowser.GridViewSizeSmall; + SetProperty(ref LayoutPreferencesItem.GridViewSize, newValue, nameof(GridViewSize)); + + // Only update layout mode if it isn't already in grid view + if (LayoutMode != FolderLayoutModes.GridView) + { + LayoutPreferencesItem.IsAdaptiveLayoutOverridden = true; + LayoutMode = FolderLayoutModes.GridView; + LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(LayoutMode, GridViewSize)); + } + else + { + LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreferencesItem)); + } + + GridViewSizeChangeRequested?.Invoke(this, EventArgs.Empty); + } + } + // Size up + else if (value > LayoutPreferencesItem.GridViewSize) + { + // Size up from list to tiles + if (LayoutMode == FolderLayoutModes.DetailsView) + { + LayoutPreferencesItem.IsAdaptiveLayoutOverridden = true; + LayoutMode = FolderLayoutModes.TilesView; + LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(LayoutMode, GridViewSize)); + } + else // Size up from tiles to grid + { + // Set grid size to allow immediate UI update + var newValue = (LayoutMode == FolderLayoutModes.TilesView) ? Constants.Browser.GridViewBrowser.GridViewSizeSmall : (value <= Constants.Browser.GridViewBrowser.GridViewSizeMax) ? value : Constants.Browser.GridViewBrowser.GridViewSizeMax; + SetProperty(ref LayoutPreferencesItem.GridViewSize, newValue, nameof(GridViewSize)); + + // Only update layout mode if it isn't already in grid view + if (LayoutMode != FolderLayoutModes.GridView) + { + LayoutPreferencesItem.IsAdaptiveLayoutOverridden = true; + LayoutMode = FolderLayoutModes.GridView; + LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(LayoutMode, GridViewSize)); + } + else + { + LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreferencesItem)); + } + + // Don't request a grid resize if it is already at the max size + if (value < Constants.Browser.GridViewBrowser.GridViewSizeMax) + GridViewSizeChangeRequested?.Invoke(this, EventArgs.Empty); + } + } + } + } + + public FolderLayoutModes LayoutMode + { + get => _rootLayoutMode ?? LayoutPreferencesItem.LayoutMode; + set + { + if (SetProperty(ref LayoutPreferencesItem.LayoutMode, value, nameof(LayoutMode))) + LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreferencesItem)); + } + } + + public GridViewSizeKind GridViewSizeKind + { + get + { + if (GridViewSize < Constants.Browser.GridViewBrowser.GridViewSizeMedium) + return GridViewSizeKind.Small; + else if (GridViewSize >= Constants.Browser.GridViewBrowser.GridViewSizeMedium && GridViewSize < Constants.Browser.GridViewBrowser.GridViewSizeLarge) + return GridViewSizeKind.Medium; + else + return GridViewSizeKind.Large; + } + } + + public SortOption DirectorySortOption + { + get => LayoutPreferencesItem.DirectorySortOption; + set + { + if (SetProperty(ref LayoutPreferencesItem.DirectorySortOption, value, nameof(DirectorySortOption))) + { + LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreferencesItem)); + SortOptionPreferenceUpdated?.Invoke(this, DirectorySortOption); + } + } + } + + public GroupOption DirectoryGroupOption + { + get => LayoutPreferencesItem.DirectoryGroupOption; + set + { + if (SetProperty(ref LayoutPreferencesItem.DirectoryGroupOption, value, nameof(DirectoryGroupOption))) + { + LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreferencesItem)); + GroupOptionPreferenceUpdated?.Invoke(this, DirectoryGroupOption); + } + } + } + + public SortDirection DirectorySortDirection + { + get => LayoutPreferencesItem.DirectorySortDirection; + set + { + if (SetProperty(ref LayoutPreferencesItem.DirectorySortDirection, value, nameof(DirectorySortDirection))) + { + LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreferencesItem)); + SortDirectionPreferenceUpdated?.Invoke(this, DirectorySortDirection); + } + } + } + + public SortDirection DirectoryGroupDirection + { + get => LayoutPreferencesItem.DirectoryGroupDirection; + set + { + if (SetProperty(ref LayoutPreferencesItem.DirectoryGroupDirection, value, nameof(DirectoryGroupDirection))) + { + LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreferencesItem)); + GroupDirectionPreferenceUpdated?.Invoke(this, DirectoryGroupDirection); + } + } + } + + public GroupByDateUnit DirectoryGroupByDateUnit + { + get => LayoutPreferencesItem.DirectoryGroupByDateUnit; + set + { + if (SetProperty(ref LayoutPreferencesItem.DirectoryGroupByDateUnit, value, nameof(DirectoryGroupByDateUnit))) + { + LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreferencesItem)); + GroupByDateUnitPreferenceUpdated?.Invoke(this, DirectoryGroupByDateUnit); + } + } + } + + public bool SortDirectoriesAlongsideFiles + { + get => LayoutPreferencesItem.SortDirectoriesAlongsideFiles; + set + { + if (SetProperty(ref LayoutPreferencesItem.SortDirectoriesAlongsideFiles, value, nameof(SortDirectoriesAlongsideFiles))) + { + LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreferencesItem)); + SortDirectoriesAlongsideFilesPreferenceUpdated?.Invoke(this, SortDirectoriesAlongsideFiles); + } + } + } + + public ColumnsViewModel ColumnsViewModel + { + get => LayoutPreferencesItem.ColumnsViewModel; + set + { + SetProperty(ref LayoutPreferencesItem.ColumnsViewModel, value, nameof(ColumnsViewModel)); + LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreferencesItem)); + } + } + + private bool _IsLayoutModeChanging; + public bool IsLayoutModeChanging + { + get => _IsLayoutModeChanging; + set => SetProperty(ref _IsLayoutModeChanging, value); + } + + private LayoutPreferencesItem? _LayoutPreferencesItem; + public LayoutPreferencesItem LayoutPreferencesItem + { + get => _LayoutPreferencesItem!; + private set + { + if (SetProperty(ref _LayoutPreferencesItem, value)) + { + OnPropertyChanged(nameof(LayoutMode)); + OnPropertyChanged(nameof(GridViewSize)); + OnPropertyChanged(nameof(GridViewSizeKind)); + OnPropertyChanged(nameof(IsAdaptiveLayoutEnabled)); + OnPropertyChanged(nameof(DirectoryGroupOption)); + OnPropertyChanged(nameof(DirectorySortOption)); + OnPropertyChanged(nameof(DirectorySortDirection)); + OnPropertyChanged(nameof(DirectoryGroupDirection)); + OnPropertyChanged(nameof(DirectoryGroupByDateUnit)); + OnPropertyChanged(nameof(SortDirectoriesAlongsideFiles)); + OnPropertyChanged(nameof(ColumnsViewModel)); + } + } + } + + // Events + + public event EventHandler? LayoutPreferencesUpdateRequired; + public event EventHandler? SortOptionPreferenceUpdated; + public event EventHandler? GroupOptionPreferenceUpdated; + public event EventHandler? SortDirectionPreferenceUpdated; + public event EventHandler? GroupDirectionPreferenceUpdated; + public event EventHandler? GroupByDateUnitPreferenceUpdated; + public event EventHandler? SortDirectoriesAlongsideFilesPreferenceUpdated; + public event EventHandler? LayoutModeChangeRequested; + public event EventHandler? GridViewSizeChangeRequested; + + // Constructors + + public LayoutPreferencesManager() + { + LayoutPreferencesItem = new LayoutPreferencesItem(); + } + + public LayoutPreferencesManager(FolderLayoutModes modeOverride) : this() + { + _rootLayoutMode = modeOverride; + LayoutPreferencesItem.IsAdaptiveLayoutOverridden = true; + } + + // Methods + + public uint GetIconSize() + { + return LayoutMode switch + { + FolderLayoutModes.DetailsView + => Constants.Browser.DetailsLayoutBrowser.DetailsViewSize, + FolderLayoutModes.ColumnView + => Constants.Browser.ColumnViewBrowser.ColumnViewSize, + FolderLayoutModes.TilesView + => Constants.Browser.GridViewBrowser.GridViewSizeSmall, + _ when GridViewSize <= Constants.Browser.GridViewBrowser.GridViewSizeSmall + => Constants.Browser.GridViewBrowser.GridViewSizeSmall, + _ when GridViewSize <= Constants.Browser.GridViewBrowser.GridViewSizeMedium + => Constants.Browser.GridViewBrowser.GridViewSizeMedium, + _ when GridViewSize <= Constants.Browser.GridViewBrowser.GridViewSizeLarge + => Constants.Browser.GridViewBrowser.GridViewSizeLarge, + _ => Constants.Browser.GridViewBrowser.GridViewSizeMax, + }; + } + + public Type GetLayoutType(string path, bool changeLayoutMode = true) + { + var preferencesItem = GetLayoutPreferencesForPath(path); + if (preferencesItem is null) + return typeof(DetailsLayoutPage); + + if (changeLayoutMode) + { + IsLayoutModeChanging = LayoutPreferencesItem.LayoutMode != preferencesItem.LayoutMode; + LayoutPreferencesItem = preferencesItem; + } + + return (preferencesItem.LayoutMode) switch + { + FolderLayoutModes.DetailsView => typeof(DetailsLayoutPage), + FolderLayoutModes.TilesView => typeof(GridLayoutPage), + FolderLayoutModes.GridView => typeof(GridLayoutPage), + FolderLayoutModes.ColumnView => typeof(ColumnsLayoutPage), + _ => typeof(DetailsLayoutPage) + }; + } + + public void ToggleLayoutModeGridViewLarge(bool manuallySet) + { + IsAdaptiveLayoutEnabled &= !manuallySet; + + // Grid View + LayoutMode = FolderLayoutModes.GridView; + + // Size + GridViewSize = Constants.Browser.GridViewBrowser.GridViewSizeLarge; + + LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.GridView, GridViewSize)); + } + + public void ToggleLayoutModeColumnView(bool manuallySet) + { + IsAdaptiveLayoutEnabled &= !manuallySet; + + // Column View + LayoutMode = FolderLayoutModes.ColumnView; + + LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.ColumnView, GridViewSize)); + } + + public void ToggleLayoutModeGridViewMedium(bool manuallySet) + { + IsAdaptiveLayoutEnabled &= !manuallySet; + + // Grid View + LayoutMode = FolderLayoutModes.GridView; + + // Size + GridViewSize = Constants.Browser.GridViewBrowser.GridViewSizeMedium; + + LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.GridView, GridViewSize)); + } + + public void ToggleLayoutModeGridViewSmall(bool manuallySet) + { + IsAdaptiveLayoutEnabled &= !manuallySet; + + // Grid View + LayoutMode = FolderLayoutModes.GridView; + + // Size + GridViewSize = Constants.Browser.GridViewBrowser.GridViewSizeSmall; + + LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.GridView, GridViewSize)); + } + + public void ToggleLayoutModeGridView(int size) + { + // Grid View + LayoutMode = FolderLayoutModes.GridView; + + // Size + GridViewSize = size; + + LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(LayoutMode, GridViewSize)); + } + + public void ToggleLayoutModeTiles(bool manuallySet) + { + IsAdaptiveLayoutEnabled &= !manuallySet; + + // Tiles View + LayoutMode = FolderLayoutModes.TilesView; + + LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.TilesView, GridViewSize)); + } + + public void ToggleLayoutModeDetailsView(bool manuallySet) + { + IsAdaptiveLayoutEnabled &= !manuallySet; + + // Details View + LayoutMode = FolderLayoutModes.DetailsView; + + LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.DetailsView, GridViewSize)); + } + + public void ToggleLayoutModeAdaptive() + { + // Adaptive + IsAdaptiveLayoutEnabled = true; + + LayoutModeChangeRequested?.Invoke(this, new LayoutModeEventArgs(FolderLayoutModes.Adaptive, GridViewSize)); + } + + public void OnDefaultPreferencesChanged(string path, string settingsName) + { + var preferencesItem = GetLayoutPreferencesForPath(path); + if (preferencesItem is null) + return; + + switch (settingsName) + { + case nameof(UserSettingsService.FoldersSettingsService.DefaultSortDirectoriesAlongsideFiles): + SortDirectoriesAlongsideFiles = preferencesItem.SortDirectoriesAlongsideFiles; + break; + case nameof(UserSettingsService.FoldersSettingsService.SyncFolderPreferencesAcrossDirectories): + LayoutPreferencesItem = preferencesItem; + // TODO: Update layout + break; + } + } + + // Static methods + + public static LayoutPreferencesDatabaseManager GetDatabaseManagerInstance() + { + return _databaseInstance.Value; + } + + public static void SetDefaultLayoutPreferences(ColumnsViewModel columns) + { + UserSettingsService.FoldersSettingsService.ShowDateColumn = !columns.DateModifiedColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.ShowDateCreatedColumn = !columns.DateCreatedColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.ShowTypeColumn = !columns.ItemTypeColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.ShowSizeColumn = !columns.SizeColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.ShowFileTagColumn = !columns.TagColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.ShowGitStatusColumn = !columns.GitStatusColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.ShowGitLastCommitDateColumn = !columns.GitLastCommitDateColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.ShowGitLastCommitMessageColumn = !columns.GitLastCommitMessageColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.ShowGitCommitAuthorColumn = !columns.GitCommitAuthorColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.ShowGitLastCommitShaColumn = !columns.GitLastCommitShaColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.ShowDateDeletedColumn = !columns.DateDeletedColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.ShowPathColumn = !columns.PathColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.ShowOriginalPathColumn = !columns.OriginalPathColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.ShowSyncStatusColumn = !columns.StatusColumn.UserCollapsed; + + UserSettingsService.FoldersSettingsService.NameColumnWidth = columns.NameColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.DateModifiedColumnWidth = columns.DateModifiedColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.DateCreatedColumnWidth = columns.DateCreatedColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.TypeColumnWidth = columns.ItemTypeColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.SizeColumnWidth = columns.SizeColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.TagColumnWidth = columns.TagColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.GitStatusColumnWidth = columns.GitStatusColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.GitLastCommitDateColumnWidth = columns.GitLastCommitDateColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.GitLastCommitMessageColumnWidth = columns.GitLastCommitMessageColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.GitCommitAuthorColumnWidth = columns.GitCommitAuthorColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.GitLastCommitShaColumnWidth = columns.GitLastCommitShaColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.DateDeletedColumnWidth = columns.DateDeletedColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.PathColumnWidth = columns.PathColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.OriginalPathColumnWidth = columns.OriginalPathColumn.UserLengthPixels; + UserSettingsService.FoldersSettingsService.SyncStatusColumnWidth = columns.StatusColumn.UserLengthPixels; + } + + public static void SetLayoutPreferencesForPath(string path, LayoutPreferencesItem preferencesItem) + { + if (!UserSettingsService.FoldersSettingsService.SyncFolderPreferencesAcrossDirectories) + { + var folderFRN = NativeFileOperationsHelper.GetFolderFRN(path); + var trimmedFolderPath = path.TrimPath(); + if (trimmedFolderPath is not null) + SetLayoutPreferencesToDatabase(trimmedFolderPath, folderFRN, preferencesItem); + } + else + { + UserSettingsService.FoldersSettingsService.DefaultLayoutMode = preferencesItem.LayoutMode; + UserSettingsService.LayoutSettingsService.DefaultGridViewSize = preferencesItem.GridViewSize; + + // Do not save options which only work in recycle bin or cloud folders or search results as global + if (preferencesItem.DirectorySortOption != SortOption.Path && + preferencesItem.DirectorySortOption != SortOption.OriginalFolder && + preferencesItem.DirectorySortOption != SortOption.DateDeleted && + preferencesItem.DirectorySortOption != SortOption.SyncStatus) + { + UserSettingsService.FoldersSettingsService.DefaultSortOption = preferencesItem.DirectorySortOption; + } + + if (preferencesItem.DirectoryGroupOption != GroupOption.OriginalFolder && + preferencesItem.DirectoryGroupOption != GroupOption.DateDeleted && + preferencesItem.DirectoryGroupOption != GroupOption.FolderPath && + preferencesItem.DirectoryGroupOption != GroupOption.SyncStatus) + { + UserSettingsService.FoldersSettingsService.DefaultGroupOption = preferencesItem.DirectoryGroupOption; + } + + UserSettingsService.FoldersSettingsService.DefaultDirectorySortDirection = preferencesItem.DirectorySortDirection; + UserSettingsService.FoldersSettingsService.DefaultDirectoryGroupDirection = preferencesItem.DirectoryGroupDirection; + UserSettingsService.FoldersSettingsService.DefaultGroupByDateUnit = preferencesItem.DirectoryGroupByDateUnit; + UserSettingsService.FoldersSettingsService.DefaultSortDirectoriesAlongsideFiles = preferencesItem.SortDirectoriesAlongsideFiles; + + UserSettingsService.FoldersSettingsService.NameColumnWidth = preferencesItem.ColumnsViewModel.NameColumn.UserLengthPixels; + + if (!preferencesItem.ColumnsViewModel.DateModifiedColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowDateColumn = !preferencesItem.ColumnsViewModel.DateModifiedColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.DateModifiedColumnWidth = preferencesItem.ColumnsViewModel.DateModifiedColumn.UserLengthPixels; + } + if (!preferencesItem.ColumnsViewModel.DateCreatedColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowDateCreatedColumn = !preferencesItem.ColumnsViewModel.DateCreatedColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.DateCreatedColumnWidth = preferencesItem.ColumnsViewModel.DateCreatedColumn.UserLengthPixels; + } + if (!preferencesItem.ColumnsViewModel.ItemTypeColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowTypeColumn = !preferencesItem.ColumnsViewModel.ItemTypeColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.TypeColumnWidth = preferencesItem.ColumnsViewModel.ItemTypeColumn.UserLengthPixels; + } + if (!preferencesItem.ColumnsViewModel.SizeColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowSizeColumn = !preferencesItem.ColumnsViewModel.SizeColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.SizeColumnWidth = preferencesItem.ColumnsViewModel.SizeColumn.UserLengthPixels; + } + if (!preferencesItem.ColumnsViewModel.TagColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowFileTagColumn = !preferencesItem.ColumnsViewModel.TagColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.TagColumnWidth = preferencesItem.ColumnsViewModel.TagColumn.UserLengthPixels; + } + if (!preferencesItem.ColumnsViewModel.GitStatusColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowGitStatusColumn = !preferencesItem.ColumnsViewModel.GitStatusColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.GitStatusColumnWidth = preferencesItem.ColumnsViewModel.GitStatusColumn.UserLengthPixels; + } + if (!preferencesItem.ColumnsViewModel.GitLastCommitDateColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowGitLastCommitDateColumn = !preferencesItem.ColumnsViewModel.GitLastCommitDateColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.GitLastCommitDateColumnWidth = preferencesItem.ColumnsViewModel.GitLastCommitDateColumn.UserLengthPixels; + } + if (!preferencesItem.ColumnsViewModel.GitLastCommitMessageColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowGitLastCommitMessageColumn = !preferencesItem.ColumnsViewModel.GitLastCommitMessageColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.GitLastCommitMessageColumnWidth = preferencesItem.ColumnsViewModel.GitLastCommitMessageColumn.UserLengthPixels; + } + if (!preferencesItem.ColumnsViewModel.GitCommitAuthorColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowGitCommitAuthorColumn = !preferencesItem.ColumnsViewModel.GitCommitAuthorColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.GitCommitAuthorColumnWidth = preferencesItem.ColumnsViewModel.GitCommitAuthorColumn.UserLengthPixels; + } + if (!preferencesItem.ColumnsViewModel.GitLastCommitShaColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowGitLastCommitShaColumn = !preferencesItem.ColumnsViewModel.GitLastCommitShaColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.GitLastCommitShaColumnWidth = preferencesItem.ColumnsViewModel.GitLastCommitShaColumn.UserLengthPixels; + } + if (!preferencesItem.ColumnsViewModel.DateDeletedColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowDateDeletedColumn = !preferencesItem.ColumnsViewModel.DateDeletedColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.DateDeletedColumnWidth = preferencesItem.ColumnsViewModel.DateDeletedColumn.UserLengthPixels; + } + if (!preferencesItem.ColumnsViewModel.PathColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowPathColumn = !preferencesItem.ColumnsViewModel.PathColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.PathColumnWidth = preferencesItem.ColumnsViewModel.PathColumn.UserLengthPixels; + } + if (!preferencesItem.ColumnsViewModel.OriginalPathColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowOriginalPathColumn = !preferencesItem.ColumnsViewModel.OriginalPathColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.OriginalPathColumnWidth = preferencesItem.ColumnsViewModel.OriginalPathColumn.UserLengthPixels; + } + if (!preferencesItem.ColumnsViewModel.StatusColumn.IsHidden) + { + UserSettingsService.FoldersSettingsService.ShowSyncStatusColumn = !preferencesItem.ColumnsViewModel.StatusColumn.UserCollapsed; + UserSettingsService.FoldersSettingsService.SyncStatusColumnWidth = preferencesItem.ColumnsViewModel.StatusColumn.UserLengthPixels; + } + } + } + + private static LayoutPreferencesItem? GetLayoutPreferencesForPath(string path) + { + if (!UserSettingsService.FoldersSettingsService.SyncFolderPreferencesAcrossDirectories) + { + path = path.TrimPath() ?? string.Empty; + + var folderFRN = NativeFileOperationsHelper.GetFolderFRN(path); + + return GetLayoutPreferencesFromDatabase(path, folderFRN) + ?? GetLayoutPreferencesFromAds(path, folderFRN) + ?? GetDefaultLayoutPreferences(path); + } + + return new LayoutPreferencesItem(); + } + + private static LayoutPreferencesItem? GetLayoutPreferencesFromAds(string path, ulong? frn) + { + var str = NativeFileOperationsHelper.ReadStringFromFile($"{path}:files_layoutmode"); + + var layoutPreferences = SafetyExtensions.IgnoreExceptions(() => + string.IsNullOrEmpty(str) ? null : JsonSerializer.Deserialize(str)); + + if (layoutPreferences is null) + return null; + + // Port settings to the database, delete the ADS + SetLayoutPreferencesToDatabase(path, frn, layoutPreferences); + NativeFileOperationsHelper.DeleteFileFromApp($"{path}:files_layoutmode"); + + return layoutPreferences; + } + + private static LayoutPreferencesItem? GetLayoutPreferencesFromDatabase(string path, ulong? frn) + { + if (string.IsNullOrEmpty(path)) + return null; + + var databaseManager = GetDatabaseManagerInstance(); + + return databaseManager.GetPreferences(path, frn); + } + + private static LayoutPreferencesItem? GetDefaultLayoutPreferences(string path) + { + if (string.IsNullOrEmpty(path)) + return new(); + + if (path == Constants.UserEnvironmentPaths.DownloadsPath) + { + // Default for downloads folder is to group by date created + return new() + { + DirectoryGroupOption = GroupOption.DateCreated, + DirectoryGroupDirection = SortDirection.Descending, + DirectoryGroupByDateUnit = GroupByDateUnit.Year + }; + } + else if (LibraryManager.IsLibraryPath(path)) + { + // Default for libraries is to group by folder path + return new() + { + DirectoryGroupOption = GroupOption.FolderPath + }; + } + else + { + // Either global setting or smart guess + return new(); + } + } + + private static void SetLayoutPreferencesToDatabase(string path, ulong? frn, LayoutPreferencesItem preferencesItem) + { + if (string.IsNullOrEmpty(path)) + return; + + var dbInstance = GetDatabaseManagerInstance(); + if (dbInstance.GetPreferences(path, frn) is null && + new LayoutPreferencesItem().Equals(preferencesItem)) + { + // Do not create setting if it's default + return; + } + + dbInstance.SetPreferences(path, frn, preferencesItem); + } + } +} diff --git a/src/Files.App/ViewModels/Settings/AdvancedViewModel.cs b/src/Files.App/ViewModels/Settings/AdvancedViewModel.cs index 6401e9317674..5f9117c5466a 100644 --- a/src/Files.App/ViewModels/Settings/AdvancedViewModel.cs +++ b/src/Files.App/ViewModels/Settings/AdvancedViewModel.cs @@ -182,9 +182,9 @@ private async Task ImportSettingsAsync() tagDbInstance.Import(importTagsDB); // Import layout preferences and DB - var layoutPrefsDB = await zipFolder.GetFileAsync(Path.GetFileName(FolderSettingsViewModel.LayoutSettingsDbPath)); + var layoutPrefsDB = await zipFolder.GetFileAsync(Path.GetFileName(LayoutPreferencesManager.LayoutSettingsDbPath)); string importPrefsDB = await layoutPrefsDB.ReadTextAsync(); - var layoutDbInstance = FolderSettingsViewModel.GetDbInstance(); + var layoutDbInstance = LayoutPreferencesManager.GetDatabaseManagerInstance(); layoutDbInstance.Import(importPrefsDB); } catch (Exception ex) @@ -229,9 +229,9 @@ private async Task ExportSettingsAsync() await zipFolder.CreateFileAsync(new MemoryStream(exportTagsDB), Path.GetFileName(FileTagsHelper.FileTagsDbPath), CreationCollisionOption.ReplaceExisting); // Export layout preferences DB - var layoutDbInstance = FolderSettingsViewModel.GetDbInstance(); + var layoutDbInstance = LayoutPreferencesManager.GetDatabaseManagerInstance(); byte[] exportPrefsDB = UTF8Encoding.UTF8.GetBytes(layoutDbInstance.Export()); - await zipFolder.CreateFileAsync(new MemoryStream(exportPrefsDB), Path.GetFileName(FolderSettingsViewModel.LayoutSettingsDbPath), CreationCollisionOption.ReplaceExisting); + await zipFolder.CreateFileAsync(new MemoryStream(exportPrefsDB), Path.GetFileName(LayoutPreferencesManager.LayoutSettingsDbPath), CreationCollisionOption.ReplaceExisting); } catch (Exception ex) { diff --git a/src/Files.App/ViewModels/Settings/FoldersViewModel.cs b/src/Files.App/ViewModels/Settings/FoldersViewModel.cs index 66f42a70ddce..dff294ab5e05 100644 --- a/src/Files.App/ViewModels/Settings/FoldersViewModel.cs +++ b/src/Files.App/ViewModels/Settings/FoldersViewModel.cs @@ -454,7 +454,7 @@ public bool ShowCheckboxesWhenSelectingItems public void ResetLayoutPreferences() { // Is this proper practice? - var dbInstance = FolderSettingsViewModel.GetDbInstance(); + var dbInstance = LayoutPreferencesManager.GetDatabaseManagerInstance(); dbInstance.ResetAll(); } diff --git a/src/Files.App/ViewModels/UserControls/ToolbarViewModel.cs b/src/Files.App/ViewModels/UserControls/ToolbarViewModel.cs index 7592b2bf1377..5b14ef081e20 100644 --- a/src/Files.App/ViewModels/UserControls/ToolbarViewModel.cs +++ b/src/Files.App/ViewModels/UserControls/ToolbarViewModel.cs @@ -179,7 +179,7 @@ public CurrentInstanceViewModel InstanceViewModel if (SetProperty(ref instanceViewModel, value) && instanceViewModel?.FolderSettings is not null) { - FolderSettings_PropertyChanged(this, new PropertyChangedEventArgs(nameof(FolderSettingsViewModel.LayoutMode))); + FolderSettings_PropertyChanged(this, new PropertyChangedEventArgs(nameof(LayoutPreferencesManager.LayoutMode))); instanceViewModel.FolderSettings.PropertyChanged += FolderSettings_PropertyChanged; } } @@ -906,8 +906,8 @@ private void FolderSettings_PropertyChanged(object? sender, PropertyChangedEvent { switch (e.PropertyName) { - case nameof(FolderSettingsViewModel.GridViewSize): - case nameof(FolderSettingsViewModel.LayoutMode): + case nameof(LayoutPreferencesManager.GridViewSize): + case nameof(LayoutPreferencesManager.LayoutMode): LayoutOpacityIcon = instanceViewModel.FolderSettings.LayoutMode switch { FolderLayoutModes.TilesView => Commands.LayoutTiles.OpacityStyle!, diff --git a/src/Files.App/Views/HomePage.xaml.cs b/src/Files.App/Views/HomePage.xaml.cs index b3081593aebf..9016d366b9ae 100644 --- a/src/Files.App/Views/HomePage.xaml.cs +++ b/src/Files.App/Views/HomePage.xaml.cs @@ -22,7 +22,7 @@ public sealed partial class HomePage : Page, IDisposable private IShellPage AppInstance { get; set; } = null!; - public FolderSettingsViewModel FolderSettings + public LayoutPreferencesManager FolderSettings => AppInstance?.InstanceViewModel.FolderSettings!; private QuickAccessWidget? quickAccessWidget; diff --git a/src/Files.App/Views/Layouts/BaseLayoutPage.cs b/src/Files.App/Views/Layouts/BaseLayoutPage.cs index ff1315ff446a..51b4e23a591b 100644 --- a/src/Files.App/Views/Layouts/BaseLayoutPage.cs +++ b/src/Files.App/Views/Layouts/BaseLayoutPage.cs @@ -73,7 +73,7 @@ public abstract class BaseLayoutPage : Page, IBaseLayoutPage, INotifyPropertyCha protected AddressToolbar? NavToolbar => (MainWindow.Instance.Content as Frame)?.FindDescendant(); - public FolderSettingsViewModel? FolderSettings + public LayoutPreferencesManager? FolderSettings => ParentShellPageInstance?.InstanceViewModel.FolderSettings; public CurrentInstanceViewModel? InstanceViewModel diff --git a/src/Files.App/Views/Layouts/DetailsLayoutPage.xaml.cs b/src/Files.App/Views/Layouts/DetailsLayoutPage.xaml.cs index 7e7873cd207d..eceeb3b7b852 100644 --- a/src/Files.App/Views/Layouts/DetailsLayoutPage.xaml.cs +++ b/src/Files.App/Views/Layouts/DetailsLayoutPage.xaml.cs @@ -579,7 +579,6 @@ private void UpdateColumnLayout() private void RootGrid_SizeChanged(object? sender, SizeChangedEventArgs? e) { - ColumnsViewModel.SetDesiredSize(Math.Max(0, RootGrid.ActualWidth - 80)); MaxWidthForRenameTextbox = Math.Max(0, RootGrid.ActualWidth - 80); } @@ -620,7 +619,7 @@ private void SizeAllColumnsToFit_Click(object sender, RoutedEventArgs e) return; // For scalability, just count the # of public `ColumnViewModel` properties in ColumnsViewModel - int totalColumnCount = ColumnsViewModel.GetType().GetProperties().Count(prop => prop.PropertyType == typeof(ColumnViewModel)); + int totalColumnCount = ColumnsViewModel.GetType().GetProperties().Count(prop => prop.PropertyType == typeof(DetailsLayoutColumnItem)); for (int columnIndex = 1; columnIndex <= totalColumnCount; columnIndex++) ResizeColumnToFit(columnIndex); } @@ -786,7 +785,7 @@ private void FileList_Loaded(object sender, RoutedEventArgs e) private void SetDetailsColumnsAsDefault_Click(object sender, RoutedEventArgs e) { - FolderSettings.SetDefaultLayoutPreferences(ColumnsViewModel); + LayoutPreferencesManager.SetDefaultLayoutPreferences(ColumnsViewModel); } private void ItemSelected_Checked(object sender, RoutedEventArgs e) diff --git a/src/Files.App/Views/Shells/BaseShellPage.cs b/src/Files.App/Views/Shells/BaseShellPage.cs index e12f37b78dc6..7e263cfe3dd9 100644 --- a/src/Files.App/Views/Shells/BaseShellPage.cs +++ b/src/Files.App/Views/Shells/BaseShellPage.cs @@ -56,7 +56,7 @@ public abstract class BaseShellPage : Page, IShellPage, INotifyPropertyChanged public Type CurrentPageType => ItemDisplay.SourcePageType; - public FolderSettingsViewModel FolderSettings => InstanceViewModel.FolderSettings; + public LayoutPreferencesManager FolderSettings => InstanceViewModel.FolderSettings; public AppModel AppModel => App.AppModel; diff --git a/src/Files.App/Views/Shells/ModernShellPage.xaml.cs b/src/Files.App/Views/Shells/ModernShellPage.xaml.cs index caf9a36112b3..2c77cd2c448e 100644 --- a/src/Files.App/Views/Shells/ModernShellPage.xaml.cs +++ b/src/Files.App/Views/Shells/ModernShellPage.xaml.cs @@ -83,7 +83,7 @@ protected override void FolderSettings_LayoutPreferencesUpdateRequired(object se if (FilesystemViewModel is null) return; - FolderSettingsViewModel.SetLayoutPreferencesForPath(FilesystemViewModel.WorkingDirectory, e.LayoutPreference); + LayoutPreferencesManager.SetLayoutPreferencesForPath(FilesystemViewModel.WorkingDirectory, e.LayoutPreference); if (e.IsAdaptiveLayoutUpdateRequired) AdaptiveLayoutHelpers.ApplyAdaptativeLayout(InstanceViewModel.FolderSettings, FilesystemViewModel.WorkingDirectory, FilesystemViewModel.FilesAndFolders); } @@ -321,7 +321,7 @@ public override void NavigateToPath(string? navigationPath, Type? sourcePageType string.IsNullOrEmpty(navArg) || !navArg.StartsWith("tag:"))) // Return if already selected { - if (InstanceViewModel?.FolderSettings is FolderSettingsViewModel fsModel) + if (InstanceViewModel?.FolderSettings is LayoutPreferencesManager fsModel) fsModel.IsLayoutModeChanging = false; return;