/
AdaptiveLayoutHelpers.cs
127 lines (106 loc) · 4.14 KB
/
AdaptiveLayoutHelpers.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.
using Files.App.ViewModels.Previews;
using Files.Shared.Helpers;
using IniParser.Model;
using Windows.Storage;
using static Files.App.Constants.AdaptiveLayout;
using IO = System.IO;
namespace Files.App.Helpers
{
public static class AdaptiveLayoutHelpers
{
private static IFoldersSettingsService FoldersSettingsService { get; } = Ioc.Default.GetRequiredService<IFoldersSettingsService>();
private static ILayoutSettingsService LayoutSettingsService { get; } = Ioc.Default.GetRequiredService<ILayoutSettingsService>();
public static void ApplyAdaptativeLayout(LayoutPreferencesManager folderSettings, string path, IList<ListedItem> filesAndFolders)
{
if (LayoutSettingsService.SyncFolderPreferencesAcrossDirectories)
return;
if (string.IsNullOrWhiteSpace(path))
return;
if (folderSettings.IsLayoutModeFixed || !folderSettings.IsAdaptiveLayoutEnabled)
return;
var layout = GetAdaptiveLayout(path, filesAndFolders);
switch (layout)
{
case Layouts.Detail:
folderSettings.ToggleLayoutModeDetailsView(false);
break;
case Layouts.Grid:
folderSettings.ToggleLayoutModeGridView(false);
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);
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)
&& (FileExtensionHelpers.IsAudioFile(item.FileExtension)
|| FileExtensionHelpers.IsVideoFile(item.FileExtension));
}
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.
}
}
}