Skip to content
Open
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
<WindowsSdkPackageVersion>10.0.26100.67-preview</WindowsSdkPackageVersion>
<WindowsTargetFramework>$(TargetFrameworkVersion)-windows$(TargetWindowsVersion)</WindowsTargetFramework>
<LangVersion>preview</LangVersion>
<WarningsAsErrors>nullable</WarningsAsErrors>

<!-- Use Microsoft.Testing.Platform -->
<EnableMSTestRunner>true</EnableMSTestRunner>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public interface IOmnibarTextMemberPathProvider
/// Retrieves the path of the text member as a string. This path can be used to identify the location of the text member.
/// </summary>
/// <returns>Returns a string representing the path of the text member.</returns>
string GetTextMemberPath(string textMemberPath);
string? GetTextMemberPath(string textMemberPath);
}
}
2 changes: 1 addition & 1 deletion src/Files.App.Controls/Omnibar/Omnibar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ private string GetObjectText(object obj)
return obj is string text
? text
: obj is IOmnibarTextMemberPathProvider textMemberPathProvider
? textMemberPathProvider.GetTextMemberPath(CurrentSelectedMode.TextMemberPath ?? string.Empty)
? textMemberPathProvider.GetTextMemberPath(CurrentSelectedMode.TextMemberPath ?? string.Empty) ?? string.Empty
: obj.ToString() ?? string.Empty;
}

Expand Down
14 changes: 14 additions & 0 deletions src/Files.App.Controls/Sidebar/ISidebarItemModel.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,24 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

using Microsoft.UI.Xaml;

namespace Files.App.Controls
{
public interface ISidebarItemPresentationModel
{
string? Text { get; }

object? ToolTip { get; }

FrameworkElement? IconElement { get; }

FrameworkElement? ItemDecorator { get; }
}

public interface ISidebarItemModel : INotifyPropertyChanged
{

/// <summary>
/// The children of this item that will be rendered as child elements of the SidebarItem
/// </summary>
Expand Down
16 changes: 15 additions & 1 deletion src/Files.App.Controls/Sidebar/SidebarItem.Properties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,15 @@ public ISidebarItemModel? Item
set { SetValue(ItemProperty, value); }
}
public static readonly DependencyProperty ItemProperty =
DependencyProperty.Register(nameof(Item), typeof(ISidebarItemModel), typeof(SidebarItem), new PropertyMetadata(null));
DependencyProperty.Register(nameof(Item), typeof(ISidebarItemModel), typeof(SidebarItem), new PropertyMetadata(null, OnPropertyChanged));

public bool UseItemPresentation
{
get { return (bool)GetValue(UseItemPresentationProperty); }
set { SetValue(UseItemPresentationProperty, value); }
}
public static readonly DependencyProperty UseItemPresentationProperty =
DependencyProperty.Register(nameof(UseItemPresentation), typeof(bool), typeof(SidebarItem), new PropertyMetadata(false, OnPropertyChanged));

public bool UseReorderDrop
{
Expand Down Expand Up @@ -136,12 +144,18 @@ public static void OnPropertyChanged(DependencyObject sender, DependencyProperty
}
else if (e.Property == IsExpandedProperty)
{
if (item.UseItemPresentation && item.Item is { } model && model.IsExpanded != item.IsExpanded)
model.IsExpanded = item.IsExpanded;
item.UpdateExpansionState();
}
else if (e.Property == ItemProperty)
{
item.HandleItemChange();
}
else if (e.Property == UseItemPresentationProperty && item.UseItemPresentation)
{
item.UpdateItemPresentation();
}
else
{
Debug.Write(e.Property.ToString());
Expand Down
60 changes: 60 additions & 0 deletions src/Files.App.Controls/Sidebar/SidebarItem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,10 @@ protected override void OnApplyTemplate()
if (GetTemplateChild("ChevronContainer") is Border chevronContainer)
chevronContainer.PointerPressed += ChevronContainer_PointerPressed;
if (GetTemplateChild("FlyoutChildrenPresenter") is ItemsRepeater flyoutRepeater)
{
flyoutRepeater.ElementPrepared += FlyoutChildrenPresenter_ElementPrepared;
flyoutRepeater.ItemsSource = Item?.Children;
}
}

if (Owner is null)
Expand Down Expand Up @@ -124,11 +127,31 @@ private void SidebarItem_Loaded(object sender, RoutedEventArgs e)
public void HandleItemChange()
{
HookupItemChangeListener(null, Item);
if (UseItemPresentation)
UpdateItemPresentation();
UpdateFlyoutChildrenSource();
UpdateExpansionState();
ReevaluateSelection();
CanDrag = Item?.Path is string path && Path.IsPathRooted(path);
}

private void UpdateItemPresentation()
{
var presentation = Item as ISidebarItemPresentationModel;
AutomationProperties.SetAutomationId(this, presentation?.Text ?? string.Empty);
Text = presentation?.Text;
ToolTip = presentation?.ToolTip;
Icon = presentation?.IconElement;
Decorator = presentation?.ItemDecorator;
IsExpanded = Item?.IsExpanded ?? true;
}

private void UpdateFlyoutChildrenSource()
{
if (GetTemplateChild("FlyoutChildrenPresenter") is ItemsRepeater flyoutRepeater)
flyoutRepeater.ItemsSource = Item?.Children;
}

private void HookupOwners()
{
// Owner is pushed in by the hosting SidebarView's MenuItemsHost_ElementPrepared (top-level rows) or the parent SidebarItem's FlyoutChildrenPresenter_ElementPrepared (flyout children) before Loaded fires. Static SidebarItems declared directly in XAML (MainPage's SettingsButton in SidebarView.Footer) aren't realized through either path, so resolve Owner via a visual-tree walk for them. OwnerExpansionSupport state is applied by OnOwnerChanged.
Expand Down Expand Up @@ -181,9 +204,46 @@ private void Item_PropertyChanged(object? sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case null:
case "":
if (UseItemPresentation)
UpdateItemPresentation();
UpdateFlyoutChildrenSource();
UpdateExpansionState();
ReevaluateSelection();
break;
case nameof(ISidebarItemPresentationModel.Text):
if (UseItemPresentation)
{
var presentation = Item as ISidebarItemPresentationModel;
Text = presentation?.Text;
AutomationProperties.SetAutomationId(this, presentation?.Text ?? string.Empty);
}
break;
case nameof(ISidebarItemPresentationModel.ToolTip):
if (UseItemPresentation)
ToolTip = (Item as ISidebarItemPresentationModel)?.ToolTip;
break;
case nameof(ISidebarItemPresentationModel.IconElement):
if (UseItemPresentation)
Icon = (Item as ISidebarItemPresentationModel)?.IconElement;
break;
case nameof(ISidebarItemPresentationModel.ItemDecorator):
if (UseItemPresentation)
Decorator = (Item as ISidebarItemPresentationModel)?.ItemDecorator;
break;
case nameof(ISidebarItemModel.IsExpanded):
if (UseItemPresentation)
IsExpanded = Item?.IsExpanded ?? true;
UpdateExpansionState();
break;
case nameof(ISidebarItemModel.HasUnrealizedChildren):
case nameof(ISidebarItemModel.IsLeafWithChildren):
UpdateExpansionState();
ReevaluateSelection();
break;
case nameof(ISidebarItemModel.Children):
UpdateFlyoutChildrenSource();
UpdateExpansionState();
ReevaluateSelection();
break;
Expand Down
22 changes: 1 addition & 21 deletions src/Files.App.Controls/Sidebar/SidebarStyles.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -36,20 +36,6 @@
<Setter Target="Padding" Value="0" />
</Style>

<DataTemplate x:Key="DefaultSidebarItemTemplate">
<local:SidebarItem
AutomationProperties.AutomationId="{Binding Item.Text}"
ContentOpacity="{Binding RowOpacity}"
Decorator="{Binding Item.ItemDecorator}"
Icon="{Binding Item.IconElement}"
IsExpanded="{Binding Item.IsExpanded, Mode=TwoWay}"
Item="{Binding Item}"
Margin="{Binding SectionGapMargin}"
NestingLevel="{Binding Depth}"
Text="{Binding Item.Text}"
ToolTip="{Binding Item.ToolTip}" />
</DataTemplate>

<Style TargetType="local:SidebarItem">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
Expand Down Expand Up @@ -211,19 +197,13 @@
x:Name="FlyoutChildrenPresenter"
HorizontalAlignment="Stretch"
AutomationProperties.AccessibilityView="Content"
ItemsSource="{Binding Item.Children, Mode=OneWay}"
XYFocusKeyboardNavigation="Enabled">
<ItemsRepeater.ItemTemplate>
<DataTemplate>
<local:SidebarItem
AutomationProperties.AutomationId="{Binding Text}"
Decorator="{Binding ItemDecorator}"
Icon="{Binding IconElement}"
IsExpanded="{Binding IsExpanded, Mode=TwoWay}"
IsInFlyout="True"
Item="{Binding}"
Text="{Binding Text}"
ToolTip="{Binding ToolTip}" />
UseItemPresentation="True" />
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
Expand Down
15 changes: 15 additions & 0 deletions src/Files.App.Controls/Sidebar/SidebarView.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,27 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Files.App.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
HorizontalAlignment="Stretch"
Loaded="SidebarView_Loaded"
TabFocusNavigation="Local"
mc:Ignorable="d">

<UserControl.Resources>
<DataTemplate
x:Key="DefaultSidebarItemTemplate"
x:DataType="local:FlatSidebarItem">
<local:SidebarItem
ContentOpacity="{x:Bind RowOpacity}"
DataContext="{x:Bind}"
Item="{x:Bind Item}"
Margin="{x:Bind SectionGapMargin, Mode=OneWay}"
NestingLevel="{x:Bind Depth}"
UseItemPresentation="True" />
</DataTemplate>
</UserControl.Resources>

<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition
Expand Down
2 changes: 1 addition & 1 deletion src/Files.App.Launcher/Files.App.Launcher.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
<PropertyGroup Condition="'$(Configuration)'!='Debug'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<PlatformToolset>v145</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<LinkIncremental>false</LinkIncremental>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,29 @@ public BaseCompressArchiveAction()

protected void GetDestination(out string[] sources, out string directory, out string fileName)
{
sources = context.SelectedItems.Select(item => item.ItemPath).ToArray();
sources = context.SelectedItems
.Select(item => item.GetRequiredPath())
.ToArray();
directory = string.Empty;
fileName = string.Empty;

if (sources.Length is not 0)
{
// Get the current directory path
directory = context.ShellPage.ShellViewModel.WorkingDirectory.Normalize();
var shellPage = context.ShellPage ?? throw new InvalidOperationException("An active shell page is required to compress items.");
var shellViewModel = shellPage.GetRequiredShellViewModel();
var workingDirectory = shellViewModel.WorkingDirectory
?? throw new InvalidOperationException("The active shell page does not have a working directory.");
directory = workingDirectory.Normalize();

// Get the library save folder if the folder is library item
if (App.LibraryManager.TryGetLibrary(directory, out var library) && !library.IsEmpty)
directory = library.DefaultSaveFolder;
directory = library.DefaultSaveFolder
?? throw new InvalidOperationException("The library does not have a default save folder.");

// Gets the file name from the directory path
fileName = SystemIO.Path.GetFileName(sources.Length is 1 ? sources[0] : directory);
fileName = SystemIO.Path.GetFileName(sources.Length is 1 ? sources[0] : directory)
?? throw new InvalidOperationException("The archive destination does not have a file name.");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ protected async Task DecompressArchiveHereAsync(bool smart = false)
return;

var selectedItems = context.SelectedItems.ToList();
var currentFolderPath = context.ShellPage?.ShellViewModel.CurrentFolder?.ItemPath ?? string.Empty;
BaseStorageFolder currentFolder = await StorageHelpers.ToStorageItem<BaseStorageFolder>(currentFolderPath);
var currentFolderPath = context.ShellPage?.ShellViewModel!.CurrentFolder?.ItemPath ?? string.Empty;
BaseStorageFolder? currentFolder = await StorageHelpers.ToStorageItem<BaseStorageFolder>(currentFolderPath);

foreach (var selectedItem in selectedItems)
{
var password = string.Empty;
BaseStorageFile archive = await StorageHelpers.ToStorageItem<BaseStorageFile>(selectedItem.ItemPath);
BaseStorageFile? archive = await StorageHelpers.ToStorageItem<BaseStorageFile>(selectedItem.ItemPath!);

if (archive?.Path is null)
return;
Expand Down Expand Up @@ -140,7 +140,7 @@ static ReadOnlySpan<char> GetFirstMeaningfulSegment(ReadOnlySpan<char> path)
if (smart && currentFolder is not null && isMultipleItems)
{
destinationFolder =
await FilesystemTasks.Wrap(() =>
await FilesystemTasks.WrapNullable(() =>
currentFolder.CreateFolderAsync(
SystemIO.Path.GetFileNameWithoutExtension(archive.Path),
CreationCollisionOption.GenerateUniqueName).AsTask());
Expand All @@ -152,7 +152,7 @@ await FilesystemTasks.Wrap(() =>

// Operate decompress
var result = await FilesystemTasks.Wrap(() =>
StorageArchiveService.DecompressAsync(selectedItem.ItemPath, destinationFolder?.Path ?? string.Empty, password));
StorageArchiveService.DecompressAsync(selectedItem.ItemPath!, destinationFolder?.Path ?? string.Empty, password));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public override async Task ExecuteAsync(object? parameter = null)
if (string.IsNullOrEmpty(archivePath))
return;

BaseStorageFile archive = await StorageHelpers.ToStorageItem<BaseStorageFile>(archivePath);
BaseStorageFile? archive = await StorageHelpers.ToStorageItem<BaseStorageFile>(archivePath);

if (archive?.Path is null)
return;
Expand Down Expand Up @@ -83,21 +83,24 @@ public override async Task ExecuteAsync(object? parameter = null)
if (!StorageHelpers.Exists(archive.Path))
return;

BaseStorageFolder destinationFolder = decompressArchiveViewModel.DestinationFolder;
BaseStorageFolder? destinationFolder = decompressArchiveViewModel.DestinationFolder;
string destinationFolderPath = decompressArchiveViewModel.DestinationFolderPath;

// Save extraction location for future use
SaveExtractionLocation(destinationFolderPath);

if (destinationFolder is null)
{
BaseStorageFolder parentFolder = await StorageHelpers.ToStorageItem<BaseStorageFolder>(Path.GetDirectoryName(archive.Path) ?? string.Empty);
destinationFolder = await FilesystemTasks.Wrap(() => parentFolder.CreateFolderAsync(Path.GetFileName(destinationFolderPath), CreationCollisionOption.GenerateUniqueName).AsTask());
BaseStorageFolder? parentFolder = await StorageHelpers.ToStorageItem<BaseStorageFolder>(Path.GetDirectoryName(archive.Path) ?? string.Empty);
if (parentFolder is null)
throw new InvalidOperationException("The archive's parent folder could not be resolved.");

destinationFolder = await FilesystemTasks.WrapNullable(() => parentFolder.CreateFolderAsync(Path.GetFileName(destinationFolderPath), CreationCollisionOption.GenerateUniqueName).AsTask());
}

// Operate decompress
var result = await FilesystemTasks.Wrap(() =>
StorageArchiveService.DecompressAsync(archive?.Path ?? string.Empty, destinationFolder?.Path ?? string.Empty, password, encoding));
StorageArchiveService.DecompressAsync(archive.Path, destinationFolder?.Path ?? string.Empty, password, encoding));

if (decompressArchiveViewModel.OpenDestinationFolderOnCompletion)
await NavigationHelpers.OpenPath(destinationFolderPath, context.ShellPage, FilesystemItemType.Directory);
Expand Down
Loading