Skip to content
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
14 changes: 0 additions & 14 deletions docs/linux-port/compat-off-baseline.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,4 @@
# One "file: error CODE: message" per line. Regenerate with scripts/linux/compat-off-check.sh --update.
src/Files.App/Data/Items/ContextMenu.cs: error CS0246: The type or namespace name 'MENU_ITEM_TYPE' could not be found (are you missing a using directive or an assembly reference?)
src/Files.App/Data/Items/WidgetRecentItem.cs: error CS0246: The type or namespace name 'IShellItem' could not be found (are you missing a using directive or an assembly reference?)
src/Files.App/Utils/Storage/Enumerators/Win32StorageEnumerator.cs: error CS0246: The type or namespace name 'Win32PInvoke' could not be found (are you missing a using directive or an assembly reference?)
src/Files.App/Utils/Storage/Helpers/FileTypesHelper.cs: error CS0234: The type or namespace name 'FileSystem' does not exist in the namespace 'Windows.Win32.Storage' (are you missing an assembly reference?)
src/Files.App/Utils/Storage/Helpers/FilesystemResult.cs: error CS0122: 'BOOL' is inaccessible due to its protection level
src/Files.App/Utils/Storage/Helpers/FolderHelpers.cs: error CS0234: The type or namespace name 'FileSystem' does not exist in the namespace 'Windows.Win32.Storage' (are you missing an assembly reference?)
src/Files.App/Utils/Storage/Helpers/StorageHelpers.cs: error CS0234: The type or namespace name 'FileSystem' does not exist in the namespace 'Windows.Win32.Storage' (are you missing an assembly reference?)
src/Files.App/Utils/Storage/Search/FolderSearch.cs: error CS0234: The type or namespace name 'FileSystem' does not exist in the namespace 'Windows.Win32.Storage' (are you missing an assembly reference?)
src/Files.App/Utils/Storage/Search/FolderSearch.cs: error CS0246: The type or namespace name 'FindCloseSafeHandle' could not be found (are you missing a using directive or an assembly reference?)
src/Files.App/Utils/Storage/Search/FolderSearch.cs: error CS0246: The type or namespace name 'WIN32_FIND_DATAW' could not be found (are you missing a using directive or an assembly reference?)
src/Files.App/Utils/Storage/StorageItems/ShellStorageFile.cs: error CS0246: The type or namespace name 'SHOW_WINDOW_CMD' could not be found (are you missing a using directive or an assembly reference?)
src/Files.App/Utils/Storage/StorageItems/ShellStorageFolder.cs: error CS0246: The type or namespace name 'SHOW_WINDOW_CMD' could not be found (are you missing a using directive or an assembly reference?)
src/Files.App/Utils/Storage/StorageItems/StreamWithContentType.cs: error CS0122: 'IStream' is inaccessible due to its protection level
src/Files.App/Utils/Storage/StorageItems/StreamWithContentType.cs: error CS0122: 'STATSTG' is inaccessible due to its protection level
src/Files.App/Utils/Storage/StorageItems/StreamWithContentType.cs: error CS0122: 'STGMEDIUM' is inaccessible due to its protection level
src/Files.App/Utils/Storage/StorageItems/VirtualStorageItem.cs: error CS0234: The type or namespace name 'FileSystem' does not exist in the namespace 'Windows.Win32.Storage' (are you missing an assembly reference?)
src/Files.App/ViewModels/ShellViewModel.cs: error CS0234: The type or namespace name 'Win32PInvoke' does not exist in the namespace 'Files.App.Helpers' (are you missing an assembly reference?)
2 changes: 2 additions & 0 deletions src/Files.App/Actions/FileSystem/CopyItemFromHomeAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ public async Task ExecuteAsync(object? parameter = null)
return;
}

#if WINDOWS
if (storageItem is SystemStorageFolder or SystemStorageFile)
{
var standardItems = await new[] { storageItem }.ToStandardStorageItemsAsync();
if (standardItems.Any())
storageItem = standardItems.First();
}

#endif
dataPackage.Properties.PackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;
dataPackage.SetStorageItems(new[] { storageItem }, false);

Expand Down
2 changes: 2 additions & 0 deletions src/Files.App/Actions/Sidebar/CopyItemFromSidebarAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,13 +63,15 @@ public async Task ExecuteAsync(object? parameter = null)
return;
}

#if WINDOWS
if (storageItem is SystemStorageFolder or SystemStorageFile)
{
var standardItems = await new[] { storageItem }.ToStandardStorageItemsAsync();
if (standardItems.Any())
storageItem = standardItems.First();
}

#endif
dataPackage.Properties.PackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName;
dataPackage.SetStorageItems(new[] { storageItem }, false);

Expand Down
2 changes: 2 additions & 0 deletions src/Files.App/Services/Windows/WindowsQuickAccessService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ private async Task<bool> UnpinFromSidebarAsync(string[] folderPaths, bool doUpda
?? throw new InvalidOperationException("The Windows Shell Home namespace returned an item without a path.");
bool shouldUnpin = folderPaths.Contains(pathStr);

#if WINDOWS
if (ShellStorageFolder.IsShellPath(pathStr))
{
var folder = await ShellStorageFolder.FromPathAsync(pathStr);
Expand All @@ -64,6 +65,7 @@ private async Task<bool> UnpinFromSidebarAsync(string[] folderPaths, bool doUpda
(path.StartsWith(@"\\SHELL\\") && folderPaths.Any(x => x.StartsWith(@"\\SHELL\\"))));
}

#endif
if (!shouldUnpin)
continue;

Expand Down
8 changes: 8 additions & 0 deletions src/Files.App/Utils/Shell/ShellHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public static class ShellHelpers
{
public static string ResolveShellPath(string shPath)
{
#if WINDOWS
if (!ShellStorageFolder.IsShellPath(shPath))
return shPath;

Expand All @@ -26,12 +27,19 @@ public static string ResolveShellPath(string shPath)
return Constants.UserEnvironmentPaths.NetworkFolderPath;

return shPath;
#else
return shPath;
#endif
}

public static bool IsSupportedShellPath(string shPath)
{
#if WINDOWS
return ShellStorageFolder.IsShellPath(shPath) &&
Constants.UserEnvironmentPaths.ShellPlaces.ContainsKey(GetShellPathLookupKey(shPath));
#else
return false;
#endif
}

private static string GetShellPathLookupKey(string shPath)
Expand Down
11 changes: 11 additions & 0 deletions src/Files.App/Utils/Storage/Helpers/ErrorCodeConverter.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,21 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

using Files.Core.Storage.Enums;

namespace Files.App.Utils.Storage
{
public static class ErrorCodeConverter
{
public static FileSystemStatusCode ToFileSystemStatusCode(this StorableStatus status) => status switch
{
StorableStatus.Success => FileSystemStatusCode.Success,
StorableStatus.NotFound => FileSystemStatusCode.NotFound,
StorableStatus.AccessDenied => FileSystemStatusCode.Unauthorized,
StorableStatus.NotMine or StorableStatus.Error => FileSystemStatusCode.Generic,
_ => FileSystemStatusCode.Generic,
};

public static ReturnResult ToStatus(this FileSystemStatusCode errorCode)
{
switch (errorCode)
Expand Down
4 changes: 4 additions & 0 deletions src/Files.App/Utils/Storage/Helpers/FilePropertiesHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
using Microsoft.UI.Xaml.Media.Animation;
using System.Collections.Concurrent;
using Windows.Graphics;
#if WINDOWS
using Windows.Win32;
#endif

namespace Files.App.Utils.Storage
{
Expand Down Expand Up @@ -135,8 +137,10 @@ public static void OpenPropertiesWindow(object item, IShellPage associatedInstan

// WINUI3: Move window to cursor position (the window manager places the window on Linux)
var pointerPosition = default(System.Drawing.Point);
#if WINDOWS
if (!OperatingSystem.IsLinux())
PInvoke.GetCursorPos(out pointerPosition);
#endif

// Null when no display is available, e.g. while monitors are detached
var displayArea = OperatingSystem.IsLinux()
Expand Down
6 changes: 6 additions & 0 deletions src/Files.App/Utils/Storage/Helpers/FileTypesHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@
// SPDX-License-Identifier: MPL-2.0

using System.Collections.Concurrent;
#if WINDOWS
using Windows.Win32;
using Windows.Win32.Storage.FileSystem;
using Windows.Win32.UI.Shell;
#endif

namespace Files.App.Utils.Storage
{
Expand All @@ -25,6 +27,7 @@ public static unsafe string GetLocalizedTypeName(string? extension)
if (!OperatingSystem.IsWindows())
return string.Empty;

#if WINDOWS
if (typeNameCache.TryGetValue(extension, out var cached))
return cached;

Expand All @@ -47,6 +50,9 @@ public static unsafe string GetLocalizedTypeName(string? extension)

typeNameCache[extension] = typeName;
return typeName;
#else
return string.Empty;
#endif
}
}
}
4 changes: 4 additions & 0 deletions src/Files.App/Utils/Storage/Helpers/FilesystemResult.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

#if WINDOWS
using Windows.Win32.Foundation;
#endif

namespace Files.App.Utils.Storage
{
Expand All @@ -18,8 +20,10 @@ public class FilesystemResult
public static explicit operator FilesystemResult(bool res) => new(res ? FileSystemStatusCode.Success : FileSystemStatusCode.Generic);


#if WINDOWS
public static implicit operator BOOL(FilesystemResult? res) => res?.ErrorCode is FileSystemStatusCode.Success;
public static explicit operator FilesystemResult(BOOL res) => new(res ? FileSystemStatusCode.Success : FileSystemStatusCode.Generic);
#endif
}

public sealed class FilesystemResult<T> : FilesystemResult
Expand Down
4 changes: 4 additions & 0 deletions src/Files.App/Utils/Storage/Helpers/FolderHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
// Licensed under the MIT License.

using System.IO;
#if WINDOWS
using Windows.Win32;
#endif
#if WINDOWS
using Windows.Win32.Storage.FileSystem;
#endif

namespace Files.App.Utils.Storage
{
Expand Down
94 changes: 94 additions & 0 deletions src/Files.App/Utils/Storage/Helpers/StorageFileExtensions.Linux.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

#if !WINDOWS
using System.IO;
using Windows.Storage;

namespace Files.App.Utils.Storage
{
public static partial class StorageFileExtensions
{
// LINUX-TODO(storage): retain legacy signatures until P4-B/E/G/H migrate to the resolver.
public static BaseStorageFile? AsBaseStorageFile(this IStorageItem? item) => item as BaseStorageFile;
public static BaseStorageFolder? AsBaseStorageFolder(this IStorageItem? item) => item as BaseStorageFolder;

public static Task<List<IStorageItem>> ToStandardStorageItemsAsync(this IEnumerable<IStorageItem> items)
=> Task.FromResult(items.ToList());

public static async Task<BaseStorageFile?> DangerousGetFileFromPathAsync(string value, StorageFolderWithPath? rootFolder = null, StorageFolderWithPath? parentFolder = null)
{
var path = ResolveLegacyPath(value, parentFolder);
var result = await StorageHelpers.GetFileAsync(path);
ThrowLegacyResolutionError(result.ErrorCode, path);
return await OpenLegacyFileAsync(path);
}

public static async Task<StorageFileWithPath> DangerousGetFileWithPathFromPathAsync(string value, StorageFolderWithPath? rootFolder = null, StorageFolderWithPath? parentFolder = null)
{
var path = ResolveLegacyPath(value, parentFolder);
ThrowLegacyResolutionError((await StorageHelpers.GetFileAsync(path)).ErrorCode, path);
return new(await OpenLegacyFileAsync(path), path);
}

public static async Task<BaseStorageFolder?> DangerousGetFolderFromPathAsync(string value, StorageFolderWithPath? rootFolder = null, StorageFolderWithPath? parentFolder = null)
{
var path = ResolveLegacyPath(value, parentFolder);
var result = await StorageHelpers.GetFolderAsync(path);
ThrowLegacyResolutionError(result.ErrorCode, path);
return await OpenLegacyFolderAsync(path);
}

public static async Task<StorageFolderWithPath> DangerousGetFolderWithPathFromPathAsync(string value, StorageFolderWithPath? rootFolder = null, StorageFolderWithPath? parentFolder = null)
{
var path = ResolveLegacyPath(value, parentFolder);
ThrowLegacyResolutionError((await StorageHelpers.GetFolderAsync(path)).ErrorCode, path);
return new(await OpenLegacyFolderAsync(path), path);
}

/// <summary>Opens a path the resolver already accepted as a legacy item; null when no legacy type can represent it (e.g. archive members).</summary>
internal static async Task<BaseStorageFile?> OpenLegacyFileAsync(string path)
{
// Uno does not check existence or type, so only local regular files qualify
if (!Path.IsPathRooted(path) || !File.Exists(path))
return null;
try { return await BaseStorageFile.GetFileFromPathAsync(path); }
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException or ArgumentException or NotSupportedException) { return null; }
}

internal static async Task<BaseStorageFolder?> OpenLegacyFolderAsync(string path)
{
if (!Path.IsPathRooted(path) || !Directory.Exists(path))
return null;
try { return await BaseStorageFolder.GetFolderFromPathAsync(path); }
catch (Exception ex) when (ex is IOException or UnauthorizedAccessException or ArgumentException or NotSupportedException) { return null; }
}

private static string ResolveLegacyPath(string path, StorageFolderWithPath? parentFolder)
=> parentFolder is not null && !Path.IsPathRooted(path) && !FtpHelpers.IsFtpPath(path)
? Path.GetFullPath(Path.Combine(parentFolder.Path, path)) : path;

private static void ThrowLegacyResolutionError(FileSystemStatusCode status, string path)
{
if (status is FileSystemStatusCode.Success)
return;
if (status is FileSystemStatusCode.NotFound)
throw new FileNotFoundException("The storage item was not found.", path);
if (status is FileSystemStatusCode.Unauthorized)
throw new UnauthorizedAccessException("The storage item cannot be accessed.");
if (status is FileSystemStatusCode.NotAFile or FileSystemStatusCode.NotAFolder)
throw new ArgumentException("The storage item has a different kind.", nameof(path));
throw new NotSupportedException("Use IStorableResolver instead of the legacy WinRT storage layer.");
}

public static Task<IList<StorageFileWithPath>> GetFilesWithPathAsync(this StorageFolderWithPath parentFolder, uint maxNumberOfItems = uint.MaxValue)
=> throw new NotSupportedException("Use IFolder.GetItemsAsync instead of the legacy WinRT storage layer.");

public static Task<IList<StorageFolderWithPath>> GetFoldersWithPathAsync(this StorageFolderWithPath parentFolder, uint maxNumberOfItems = uint.MaxValue)
=> throw new NotSupportedException("Use IFolder.GetItemsAsync instead of the legacy WinRT storage layer.");

public static Task<IList<StorageFolderWithPath>?> GetFoldersWithPathAsync(this StorageFolderWithPath parentFolder, string nameFilter, uint maxNumberOfItems = uint.MaxValue)
=> throw new NotSupportedException("Use IFolder.GetItemsAsync instead of the legacy WinRT storage layer.");
}
}
#endif
Loading
Loading