Skip to content

Commit 50e8524

Browse files
authored
Feature: Added support for changing groups direction (#11154)
1 parent bc3eff5 commit 50e8524

File tree

11 files changed

+143
-17
lines changed

11 files changed

+143
-17
lines changed

src/Files.App/BaseLayout.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
using Windows.System;
3939
using static Files.App.Helpers.PathNormalization;
4040
using DispatcherQueueTimer = Microsoft.UI.Dispatching.DispatcherQueueTimer;
41+
using SortDirection = Files.Shared.Enums.SortDirection;
4142

4243
namespace Files.App
4344
{
@@ -377,6 +378,7 @@ protected override async void OnNavigatedTo(NavigationEventArgs eventArgs)
377378
IsItemSelected = false;
378379
FolderSettings!.LayoutModeChangeRequested += BaseFolderSettings_LayoutModeChangeRequested;
379380
FolderSettings.GroupOptionPreferenceUpdated += FolderSettings_GroupOptionPreferenceUpdated;
381+
FolderSettings.GroupDirectionPreferenceUpdated += FolderSettings_GroupDirectionPreferenceUpdated;
380382
ParentShellPageInstance.FilesystemViewModel.EmptyTextType = EmptyTextType.None;
381383
ParentShellPageInstance.ToolbarViewModel.UpdateSortAndGroupOptions();
382384
ParentShellPageInstance.ToolbarViewModel.CanRefresh = true;
@@ -474,7 +476,13 @@ public void SetSelectedItemsOnNavigation()
474476

475477
private CancellationTokenSource? groupingCancellationToken;
476478

477-
private async void FolderSettings_GroupOptionPreferenceUpdated(object? sender, GroupOption e)
479+
private void FolderSettings_GroupOptionPreferenceUpdated(object? sender, GroupOption e)
480+
=> GroupPreferenceUpdated();
481+
482+
private void FolderSettings_GroupDirectionPreferenceUpdated(object? sender, SortDirection e)
483+
=> GroupPreferenceUpdated();
484+
485+
private async void GroupPreferenceUpdated()
478486
{
479487
// Two or more of these running at the same time will cause a crash, so cancel the previous one before beginning
480488
groupingCancellationToken?.Cancel();
@@ -492,6 +500,7 @@ protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
492500
CharacterReceived -= Page_CharacterReceived;
493501
FolderSettings!.LayoutModeChangeRequested -= BaseFolderSettings_LayoutModeChangeRequested;
494502
FolderSettings.GroupOptionPreferenceUpdated -= FolderSettings_GroupOptionPreferenceUpdated;
503+
FolderSettings.GroupDirectionPreferenceUpdated -= FolderSettings_GroupDirectionPreferenceUpdated;
495504
ItemContextMenuFlyout.Opening -= ItemContextFlyout_Opening;
496505
BaseContextMenuFlyout.Opening -= BaseContextFlyout_Opening;
497506

src/Files.App/Helpers/ContextFlyoutItemHelper.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,40 @@ public static List<ContextMenuFlyoutItemViewModel> GetBaseLayoutMenuItems(Curren
469469
ItemType = ItemType.Toggle,
470470
ShowItem = currentInstanceViewModel.IsPageTypeLibrary,
471471
},
472+
new ContextMenuFlyoutItemViewModel()
473+
{
474+
ItemType = ItemType.Separator,
475+
ShowInRecycleBin = true,
476+
ShowInSearchPage = true,
477+
ShowInFtpPage = true,
478+
ShowInZipPage = true,
479+
},
480+
new ContextMenuFlyoutItemViewModel()
481+
{
482+
Text = "Ascending".GetLocalizedResource(),
483+
IsChecked = currentInstanceViewModel.FolderSettings.DirectoryGroupDirection == SortDirection.Ascending,
484+
IsEnabled = currentInstanceViewModel.FolderSettings.DirectoryGroupOption != GroupOption.None,
485+
ShowInRecycleBin = true,
486+
ShowInSearchPage = true,
487+
ShowInFtpPage = true,
488+
ShowInZipPage = true,
489+
Command = currentInstanceViewModel.FolderSettings.ChangeGroupDirectionCommand,
490+
CommandParameter = SortDirection.Ascending,
491+
ItemType = ItemType.Toggle,
492+
},
493+
new ContextMenuFlyoutItemViewModel()
494+
{
495+
Text = "Descending".GetLocalizedResource(),
496+
IsChecked = currentInstanceViewModel.FolderSettings.DirectoryGroupDirection == SortDirection.Descending,
497+
IsEnabled = currentInstanceViewModel.FolderSettings.DirectoryGroupOption != GroupOption.None,
498+
ShowInRecycleBin = true,
499+
ShowInSearchPage = true,
500+
ShowInFtpPage = true,
501+
ShowInZipPage = true,
502+
Command = currentInstanceViewModel.FolderSettings.ChangeGroupDirectionCommand,
503+
CommandParameter = SortDirection.Descending,
504+
ItemType = ItemType.Toggle,
505+
},
472506
}
473507
},
474508
new ContextMenuFlyoutItemViewModel()

src/Files.App/Helpers/ItemListDisplayHelpers/GroupingHelper.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,12 +140,12 @@ public static (string key, string text, string range, int index) GetGroupSizeInf
140140
if (size > sizeGp.size)
141141
{
142142
var rangeStr = i > 0 ? $"{sizeGp.sizeText} - {sizeGroups[i - 1].sizeText}" : $"{sizeGp.sizeText} +";
143-
return (sizeGp.size.ToString(), sizeGp.text, rangeStr, i + 1); //i +1 is so that other groups always show below "unspecified"
143+
return (sizeGp.size.ToString(), sizeGp.text, rangeStr, sizeGroups.Length - i);
144144
}
145145
lastSizeStr = sizeGp.sizeText;
146146
}
147147

148-
return ("0", "ItemSizeText_Tiny".GetLocalizedResource(), $"{"0 B".ConvertSizeAbbreviation()} - {lastSizeStr}", sizeGroups.Length + 1);
148+
return ("0", "ItemSizeText_Tiny".GetLocalizedResource(), $"{"0 B".ConvertSizeAbbreviation()} - {lastSizeStr}", 0);
149149
}
150150

151151
public static string GetGroupSizeKey(long size)
@@ -175,4 +175,4 @@ public interface IGroupableItem
175175
{
176176
public string Key { get; set; }
177177
}
178-
}
178+
}

src/Files.App/Helpers/LayoutPreferences/LayoutPreferences.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public class LayoutPreferences
1313
public SortDirection DirectorySortDirection;
1414
public bool SortDirectoriesAlongsideFiles;
1515
public GroupOption DirectoryGroupOption;
16+
public SortDirection DirectoryGroupDirection;
1617
public FolderLayoutModes LayoutMode;
1718
public int GridViewSize;
1819
public bool IsAdaptiveLayoutOverridden;
@@ -31,6 +32,7 @@ public LayoutPreferences()
3132
DirectorySortOption = UserSettingsService.FoldersSettingsService.DefaultSortOption;
3233
DirectoryGroupOption = UserSettingsService.FoldersSettingsService.DefaultGroupOption;
3334
DirectorySortDirection = UserSettingsService.LayoutSettingsService.DefaultDirectorySortDirection;
35+
DirectoryGroupDirection = UserSettingsService.LayoutSettingsService.DefaultDirectoryGroupDirection;
3436
SortDirectoriesAlongsideFiles = UserSettingsService.LayoutSettingsService.DefaultSortDirectoriesAlongsideFiles;
3537
IsAdaptiveLayoutOverridden = defaultLayout is not FolderLayoutModes.Adaptive;
3638

@@ -71,6 +73,7 @@ public override bool Equals(object? obj)
7173
prefs.DirectoryGroupOption == DirectoryGroupOption &&
7274
prefs.DirectorySortOption == DirectorySortOption &&
7375
prefs.DirectorySortDirection == DirectorySortDirection &&
76+
prefs.DirectoryGroupDirection == DirectoryGroupDirection &&
7477
prefs.SortDirectoriesAlongsideFiles == SortDirectoriesAlongsideFiles &&
7578
prefs.IsAdaptiveLayoutOverridden == IsAdaptiveLayoutOverridden &&
7679
prefs.ColumnsViewModel.Equals(ColumnsViewModel));
@@ -85,6 +88,7 @@ public override int GetHashCode()
8588
hashCode = (hashCode * 397) ^ DirectoryGroupOption.GetHashCode();
8689
hashCode = (hashCode * 397) ^ DirectorySortOption.GetHashCode();
8790
hashCode = (hashCode * 397) ^ DirectorySortDirection.GetHashCode();
91+
hashCode = (hashCode * 397) ^ DirectoryGroupDirection.GetHashCode();
8892
hashCode = (hashCode * 397) ^ SortDirectoriesAlongsideFiles.GetHashCode();
8993
hashCode = (hashCode * 397) ^ IsAdaptiveLayoutOverridden.GetHashCode();
9094
hashCode = (hashCode * 397) ^ ColumnsViewModel.GetHashCode();

src/Files.App/ServicesImplementation/DateTimeFormatter/AbstractDateTimeFormatter.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,14 @@ public ITimeSpanLabel ToTimeSpanLabel(DateTimeOffset offset)
2626

2727
return 0 switch
2828
{
29-
_ when now.Date == time.Date => new Label("Today", "\ue184", 0),
30-
_ when y.Date == time.Date => new Label("ItemTimeText_Yesterday", "\ue161", 1),
31-
_ when diff.Days < 7 && w.Year == time.Year && GetWeekOfYear(w) == GetWeekOfYear(time) => new Label("ItemTimeText_ThisWeek", "\uE162", 2),
32-
_ when diff.Days < 14 && w.Year == time.Year && GetWeekOfYear(w) == GetWeekOfYear(time) => new Label("ItemTimeText_LastWeek", "\uE162", 3),
33-
_ when now.Year == time.Year && now.Month == time.Month => new Label("ItemTimeText_ThisMonth", "\ue163", 4),
34-
_ when now.AddMonths(-1).Year == time.Year && now.AddMonths(-1).Month == time.Month => new Label("ItemTimeText_LastMonth", "\ue163", 5),
35-
_ when now.Year == time.Year => new Label("ItemTimeText_ThisYear", "\ue163", 5),
36-
_ => new Label("ItemTimeText_Older", "\uEC92", 6),
29+
_ when now.Date == time.Date => new Label("Today", "\ue184", 7),
30+
_ when y.Date == time.Date => new Label("ItemTimeText_Yesterday", "\ue161", 6),
31+
_ when diff.Days < 7 && w.Year == time.Year && GetWeekOfYear(w) == GetWeekOfYear(time) => new Label("ItemTimeText_ThisWeek", "\uE162", 5),
32+
_ when diff.Days < 14 && w.Year == time.Year && GetWeekOfYear(w) == GetWeekOfYear(time) => new Label("ItemTimeText_LastWeek", "\uE162", 4),
33+
_ when now.Year == time.Year && now.Month == time.Month => new Label("ItemTimeText_ThisMonth", "\ue163", 3),
34+
_ when now.AddMonths(-1).Year == time.Year && now.AddMonths(-1).Month == time.Month => new Label("ItemTimeText_LastMonth", "\ue163", 2),
35+
_ when now.Year == time.Year => new Label("ItemTimeText_ThisYear", "\ue163", 1),
36+
_ => new Label("ItemTimeText_Older", "\uEC92", 0),
3737
};
3838
}
3939

src/Files.App/ServicesImplementation/Settings/LayoutSettingsService.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ public SortDirection DefaultDirectorySortDirection
2424
set => Set((long)value);
2525
}
2626

27+
public SortDirection DefaultDirectoryGroupDirection
28+
{
29+
get => (SortDirection)Get((long)SortDirection.Ascending);
30+
set => Set((long)value);
31+
}
32+
2733
public bool DefaultSortDirectoriesAlongsideFiles
2834
{
2935
get => Get(false);

src/Files.App/UserControls/InnerNavigationToolbar.xaml

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,9 @@
493493
IsChecked="{x:Bind ViewModel.IsSortedByDateDeleted, Mode=TwoWay}"
494494
IsEnabled="{x:Bind ViewModel.InstanceViewModel.IsPageTypeRecycleBin, Mode=OneWay}"
495495
Text="{helpers:ResourceString Name=DateDeleted}" />
496+
<MenuFlyoutSeparator />
497+
<ToggleMenuFlyoutItem IsChecked="{x:Bind ViewModel.IsSortedAscending, Mode=TwoWay}" Text="{helpers:ResourceString Name=Ascending}" />
498+
<ToggleMenuFlyoutItem IsChecked="{x:Bind ViewModel.IsSortedDescending, Mode=TwoWay}" Text="{helpers:ResourceString Name=Descending}" />
496499
</MenuFlyoutSubItem>
497500
<MenuFlyoutSubItem Text="{helpers:ResourceString Name=NavToolbarGroupByRadioButtons/Text}">
498501
<ToggleMenuFlyoutItem IsChecked="{x:Bind ViewModel.IsGroupedByNone, Mode=TwoWay}" Text="{helpers:ResourceString Name=None}" />
@@ -518,11 +521,17 @@
518521
IsChecked="{x:Bind ViewModel.IsGroupedByFolderPath, Mode=TwoWay}"
519522
IsEnabled="{x:Bind ViewModel.InstanceViewModel.IsPageTypeLibrary, Mode=OneWay}"
520523
Text="{helpers:ResourceString Name=NavToolbarArrangementOptionFolderPath/Text}" />
524+
<MenuFlyoutSeparator />
525+
<ToggleMenuFlyoutItem
526+
IsChecked="{x:Bind ViewModel.IsGroupedAscending, Mode=TwoWay}"
527+
IsEnabled="{x:Bind ViewModel.IsGroupedByNone, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
528+
Text="{helpers:ResourceString Name=Ascending}" />
529+
<ToggleMenuFlyoutItem
530+
IsChecked="{x:Bind ViewModel.IsGroupedDescending, Mode=TwoWay}"
531+
IsEnabled="{x:Bind ViewModel.IsGroupedByNone, Mode=OneWay, Converter={StaticResource BoolNegationConverter}}"
532+
Text="{helpers:ResourceString Name=Descending}" />
521533
</MenuFlyoutSubItem>
522534
<MenuFlyoutSeparator />
523-
<ToggleMenuFlyoutItem IsChecked="{x:Bind ViewModel.IsSortedAscending, Mode=TwoWay}" Text="{helpers:ResourceString Name=Ascending}" />
524-
<ToggleMenuFlyoutItem IsChecked="{x:Bind ViewModel.IsSortedDescending, Mode=TwoWay}" Text="{helpers:ResourceString Name=Descending}" />
525-
<MenuFlyoutSeparator />
526535
<ToggleMenuFlyoutItem IsChecked="{x:Bind ViewModel.AreDirectoriesSortedAlongsideFiles, Mode=TwoWay}" Text="{helpers:ResourceString Name=SettingsListAndSortDirectoriesAlongsideFiles}" />
527536
</MenuFlyout>
528537
</AppBarButton.Flyout>

src/Files.App/ViewModels/FolderSettingsViewModel.cs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ public FolderSettingsViewModel()
4343
ToggleLayoutModeAdaptiveCommand = new RelayCommand(ToggleLayoutModeAdaptive);
4444

4545
ChangeGroupOptionCommand = new RelayCommand<GroupOption>(ChangeGroupOption);
46+
ChangeGroupDirectionCommand = new RelayCommand<SortDirection>(ChangeGroupDirection);
4647
}
4748
public FolderSettingsViewModel(FolderLayoutModes modeOverride) : this()
4849
=> (rootLayoutMode, LayoutPreference.IsAdaptiveLayoutOverridden) = (modeOverride, true);
@@ -215,6 +216,8 @@ public int GridViewSize
215216

216217
public event EventHandler<SortDirection>? SortDirectionPreferenceUpdated;
217218

219+
public event EventHandler<SortDirection>? GroupDirectionPreferenceUpdated;
220+
218221
public event EventHandler<bool>? SortDirectoriesAlongsideFilesPreferenceUpdated;
219222

220223
public SortOption DirectorySortOption
@@ -258,6 +261,21 @@ public SortDirection DirectorySortDirection
258261
}
259262
}
260263

264+
public ICommand ChangeGroupDirectionCommand { get; }
265+
266+
public SortDirection DirectoryGroupDirection
267+
{
268+
get => LayoutPreference.DirectoryGroupDirection;
269+
set
270+
{
271+
if (SetProperty(ref LayoutPreference.DirectoryGroupDirection, value, nameof(DirectoryGroupDirection)))
272+
{
273+
LayoutPreferencesUpdateRequired?.Invoke(this, new LayoutPreferenceEventArgs(LayoutPreference));
274+
GroupDirectionPreferenceUpdated?.Invoke(this, DirectoryGroupDirection);
275+
}
276+
}
277+
}
278+
261279
public bool SortDirectoriesAlongsideFiles
262280
{
263281
get
@@ -327,6 +345,7 @@ public static void SetLayoutPreferencesForPath(string folderPath, LayoutPreferen
327345
userSettingsService.FoldersSettingsService.DefaultGroupOption = prefs.DirectoryGroupOption;
328346
}
329347
userSettingsService.LayoutSettingsService.DefaultDirectorySortDirection = prefs.DirectorySortDirection;
348+
userSettingsService.LayoutSettingsService.DefaultDirectoryGroupDirection = prefs.DirectoryGroupDirection;
330349
userSettingsService.LayoutSettingsService.DefaultSortDirectoriesAlongsideFiles = prefs.SortDirectoriesAlongsideFiles;
331350

332351
userSettingsService.FoldersSettingsService.ShowDateColumn = !prefs.ColumnsViewModel.DateModifiedColumn.UserCollapsed;
@@ -376,7 +395,10 @@ private static LayoutPreferences GetDefaultLayoutPreferences(string folderPath)
376395

377396
if (folderPath == CommonPaths.DownloadsPath)
378397
// Default for downloads folder is to group by date created
379-
return new LayoutPreferences() { DirectoryGroupOption = GroupOption.DateCreated };
398+
return new LayoutPreferences() {
399+
DirectoryGroupOption = GroupOption.DateCreated,
400+
DirectoryGroupDirection = SortDirection.Descending
401+
};
380402
else if (LibraryManager.IsLibraryPath(folderPath))
381403
// Default for libraries is to group by folder path
382404
return new LayoutPreferences() { DirectoryGroupOption = GroupOption.FolderPath };
@@ -414,6 +436,7 @@ private set
414436
OnPropertyChanged(nameof(DirectoryGroupOption));
415437
OnPropertyChanged(nameof(DirectorySortOption));
416438
OnPropertyChanged(nameof(DirectorySortDirection));
439+
OnPropertyChanged(nameof(DirectoryGroupDirection));
417440
OnPropertyChanged(nameof(SortDirectoriesAlongsideFiles));
418441
OnPropertyChanged(nameof(ColumnsViewModel));
419442
}
@@ -498,6 +521,8 @@ public void ToggleLayoutModeAdaptive()
498521

499522
private void ChangeGroupOption(GroupOption option) => DirectoryGroupOption = option;
500523

524+
private void ChangeGroupDirection(SortDirection option) => DirectoryGroupDirection = option;
525+
501526
public void OnDefaultPreferencesChanged(string folderPath, string settingsName)
502527
{
503528
var prefs = GetLayoutPreferencesForPath(folderPath);

src/Files.App/ViewModels/ItemViewModel.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,22 @@ private void OrderGroups(CancellationToken token = default)
706706

707707
if (FilesAndFolders.GroupedCollection is null || FilesAndFolders.GroupedCollection.IsSorted)
708708
return;
709-
FilesAndFolders.GroupedCollection.Order(x => x.OrderBy(y => y.Model.SortIndexOverride).ThenBy(y => y.Model.Text));
709+
if (folderSettings.DirectoryGroupDirection == SortDirection.Ascending)
710+
{
711+
if (folderSettings.DirectoryGroupOption == GroupOption.Size)
712+
// Always show file sections below folders
713+
FilesAndFolders.GroupedCollection.Order(x => x.OrderBy(y => y.First().PrimaryItemAttribute != StorageItemTypes.Folder).ThenBy(y => y.Model.SortIndexOverride).ThenBy(y => y.Model.Text));
714+
else
715+
FilesAndFolders.GroupedCollection.Order(x => x.OrderBy(y => y.Model.SortIndexOverride).ThenBy(y => y.Model.Text));
716+
}
717+
else
718+
{
719+
if (folderSettings.DirectoryGroupOption == GroupOption.Size)
720+
// Always show file sections below folders
721+
FilesAndFolders.GroupedCollection.Order(x => x.OrderBy(y => y.First().PrimaryItemAttribute != StorageItemTypes.Folder).ThenByDescending(y => y.Model.SortIndexOverride).ThenByDescending(y => y.Model.Text));
722+
else
723+
FilesAndFolders.GroupedCollection.Order(x => x.OrderByDescending(y => y.Model.SortIndexOverride).ThenByDescending(y => y.Model.Text));
724+
}
710725
FilesAndFolders.GroupedCollection.IsSorted = true;
711726
}
712727

0 commit comments

Comments
 (0)