Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Code Quality: Refactored AdaptiveLayoutHelpers #10782

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 107 additions & 105 deletions src/Files.App/Helpers/AdaptiveLayoutHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,124 +3,126 @@
using Files.App.ViewModels;
using Files.App.ViewModels.Previews;
using Files.Backend.Services.Settings;
using IniParser.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using Windows.Storage;
using static Files.App.Constants.AdaptiveLayout;
using IO = System.IO;

namespace Files.App.Helpers
{
public static class AdaptiveLayoutHelpers
{
public static bool PredictLayoutMode(FolderSettingsViewModel folderSettings, string path, IList<ListedItem> filesAndFolders)
private static readonly IFoldersSettingsService foldersSettingsService = Ioc.Default.GetRequiredService<IFoldersSettingsService>();

public static void ApplyAdaptativeLayout(FolderSettingsViewModel folderSettings, string path, IList<ListedItem> filesAndFolders)
{
IUserSettingsService userSettingsService = Ioc.Default.GetRequiredService<IUserSettingsService>();
if (foldersSettingsService.SyncFolderPreferencesAcrossDirectories)
return;
if (string.IsNullOrWhiteSpace(path))
return;
if (folderSettings.IsLayoutModeFixed || !folderSettings.IsAdaptiveLayoutEnabled)
return;

if (!userSettingsService.FoldersSettingsService.SyncFolderPreferencesAcrossDirectories
&& folderSettings.IsAdaptiveLayoutEnabled
&& !folderSettings.IsLayoutModeFixed)
var layout = GetAdaptiveLayout(path, filesAndFolders);
switch (layout)
{
Action layoutDetails = () => folderSettings.ToggleLayoutModeDetailsView(false);
Action layoutGridView = () => folderSettings.ToggleLayoutModeGridView(folderSettings.GridViewSize);

bool desktopIniFound = false;

if (string.IsNullOrWhiteSpace(path))
{
return false;
}

var iniPath = System.IO.Path.Combine(path, "desktop.ini");
var iniContents = NativeFileOperationsHelper.ReadStringFromFile(iniPath)?.Trim();
if (!string.IsNullOrEmpty(iniContents))
{
var parser = new IniParser.Parser.IniDataParser();
parser.Configuration.ThrowExceptionsOnError = false;
var data = parser.Parse(iniContents);
if (data is not null)
{
var viewModeSection = data.Sections.FirstOrDefault(x => "ViewState".Equals(x.SectionName, StringComparison.OrdinalIgnoreCase));
if (viewModeSection is not null)
{
var folderTypeKey = viewModeSection.Keys.FirstOrDefault(s => "FolderType".Equals(s.KeyName, StringComparison.OrdinalIgnoreCase));
if (folderTypeKey is not null)
{
var setLayout = (folderTypeKey.Value) switch
{
"Documents" => layoutDetails,
"Pictures" => layoutGridView,
"Music" => layoutDetails,
"Videos" => layoutGridView,
_ => layoutDetails
};
setLayout();
desktopIniFound = true;
}
}
}
}

if (desktopIniFound)
{
return true;
}
if (filesAndFolders.Count == 0)
{
return false;
}

int allItemsCount = filesAndFolders.Count;

int mediaCount;
int imagesCount;
int foldersCount;
int miscFilesCount;

float mediaPercentage;
float imagesPercentage;
float foldersPercentage;
float miscFilesPercentage;

mediaCount = filesAndFolders.Where((item) =>
{
return !string.IsNullOrEmpty(item.FileExtension) && MediaPreviewViewModel.ContainsExtension(item.FileExtension.ToLowerInvariant());
}).Count();
imagesCount = filesAndFolders.Where((item) =>
{
return !string.IsNullOrEmpty(item.FileExtension) && ImagePreviewViewModel.ContainsExtension(item.FileExtension.ToLowerInvariant());
}).Count();
foldersCount = filesAndFolders.Where((item) => item.PrimaryItemAttribute == StorageItemTypes.Folder).Count();
miscFilesCount = allItemsCount - (mediaCount + imagesCount + foldersCount);

mediaPercentage = mediaCount * 100.0f / allItemsCount;
imagesPercentage = imagesCount * 100.0f / allItemsCount;
foldersPercentage = foldersCount * 100.0f / allItemsCount;
miscFilesPercentage = miscFilesCount * 100.0f / allItemsCount;

// Decide layout mode

// Mostly files + folders, lesser media and image files | Mostly folders
if ((foldersPercentage + miscFilesPercentage) > Constants.AdaptiveLayout.LargeThreshold)
{
layoutDetails();
}
// Mostly images, probably an images folder
else if (imagesPercentage > Constants.AdaptiveLayout.ExtraLargeThreshold
|| (imagesPercentage > Constants.AdaptiveLayout.MediumThreshold
&& (mediaPercentage + miscFilesPercentage + foldersPercentage) > Constants.AdaptiveLayout.SmallThreshold
&& (miscFilesPercentage + foldersPercentage) < Constants.AdaptiveLayout.ExtraSmallThreshold))
{
layoutGridView();
}
else
{
layoutDetails();
}

return true;
case Layouts.Detail:
folderSettings.ToggleLayoutModeDetailsView(false);
break;
case Layouts.Grid:
folderSettings.ToggleLayoutModeGridView(folderSettings.GridViewSize);
break;
}
}

private static Layouts GetAdaptiveLayout(string path, IList<ListedItem> filesAndFolders)
{
var pathLayout = GetPathLayout(path);
if (pathLayout is not Layouts.None)
return pathLayout;

return GetContentLayout(filesAndFolders);
}

private static Layouts GetPathLayout(string path)
{
var iniPath = IO.Path.Combine(path, "desktop.ini");

var iniContents = NativeFileOperationsHelper.ReadStringFromFile(iniPath)?.Trim();
if (string.IsNullOrEmpty(iniContents))
return Layouts.None;

var parser = new IniParser.Parser.IniDataParser();
parser.Configuration.ThrowExceptionsOnError = false;
var data = parser.Parse(iniContents);
if (data is null)
return Layouts.None;

var viewModeSection = data.Sections.FirstOrDefault(IsViewState);
if (viewModeSection is null)
return Layouts.None;

var folderTypeKey = viewModeSection.Keys.FirstOrDefault(IsFolderType);
if (folderTypeKey is null)
return Layouts.None;

return folderTypeKey.Value switch
{
"Pictures" => Layouts.Grid,
"Videos" => Layouts.Grid,
_ => Layouts.Detail,
};

static bool IsViewState(SectionData data)
=> "ViewState".Equals(data.SectionName, StringComparison.OrdinalIgnoreCase);

static bool IsFolderType(KeyData data)
=> "FolderType".Equals(data.KeyName, StringComparison.OrdinalIgnoreCase);
}

private static Layouts GetContentLayout(IList<ListedItem> filesAndFolders)
{
int itemCount = filesAndFolders.Count;
if (filesAndFolders.Count is 0)
return Layouts.None;

float folderPercentage = 100f * filesAndFolders.Count(IsFolder) / itemCount;
float imagePercentage = 100f * filesAndFolders.Count(IsImage) / itemCount;
float mediaPercentage = 100f * filesAndFolders.Count(IsMedia) / itemCount;
float miscPercentage = 100f - (folderPercentage + imagePercentage + mediaPercentage);

return false;
if (folderPercentage + miscPercentage > LargeThreshold)
return Layouts.Detail;
if (imagePercentage > ExtraLargeThreshold)
return Layouts.Grid;
if (imagePercentage <= MediumThreshold)
return Layouts.Detail;
if (100f - imagePercentage <= SmallThreshold)
return Layouts.Detail;
if (folderPercentage + miscPercentage <= ExtraSmallThreshold)
return Layouts.Detail;
return Layouts.Grid;

static bool IsFolder(ListedItem item)
=> item.PrimaryItemAttribute is StorageItemTypes.Folder;

static bool IsImage(ListedItem item)
=> !string.IsNullOrEmpty(item.FileExtension)
&& ImagePreviewViewModel.ContainsExtension(item.FileExtension.ToLowerInvariant());

static bool IsMedia(ListedItem item)
=> !string.IsNullOrEmpty(item.FileExtension)
&& MediaPreviewViewModel.ContainsExtension(item.FileExtension.ToLowerInvariant());
QuaintMako marked this conversation as resolved.
Show resolved Hide resolved
}

private enum Layouts
{
None, // Don't decide. Another function to decide can be called afterwards if available.
Detail, // Apply the layout Detail.
Grid, // Apply the layout Grid.
}
}
}
}
2 changes: 1 addition & 1 deletion src/Files.App/ViewModels/ItemViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1272,7 +1272,7 @@ private async void RapidAddItemsToCollectionAsync(string path, string? previousD
ItemLoadStatusChanged?.Invoke(this, new ItemLoadStatusChangedEventArgs() { Status = ItemLoadStatusChangedEventArgs.ItemLoadStatus.Complete, PreviousDirectory = previousDir, Path = path });
IsLoadingItems = false;

AdaptiveLayoutHelpers.PredictLayoutMode(folderSettings, WorkingDirectory, filesAndFolders);
AdaptiveLayoutHelpers.ApplyAdaptativeLayout(folderSettings, WorkingDirectory, filesAndFolders);

if (App.PreviewPaneViewModel.IsEnabled)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Files.App/Views/ModernShellPage.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ private void FolderSettings_LayoutPreferencesUpdateRequired(object sender, Layou

FolderSettingsViewModel.SetLayoutPreferencesForPath(FilesystemViewModel.WorkingDirectory, e.LayoutPreference);
if (e.IsAdaptiveLayoutUpdateRequired)
AdaptiveLayoutHelpers.PredictLayoutMode(InstanceViewModel.FolderSettings, FilesystemViewModel.WorkingDirectory, FilesystemViewModel.FilesAndFolders);
AdaptiveLayoutHelpers.ApplyAdaptativeLayout(InstanceViewModel.FolderSettings, FilesystemViewModel.WorkingDirectory, FilesystemViewModel.FilesAndFolders);
}

/*
Expand Down