Skip to content

Feature: Translate shell folders names & avoid possible bugs #11890

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

Merged
merged 12 commits into from
Apr 2, 2023
Merged
9 changes: 0 additions & 9 deletions src/Files.App/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,6 @@ public static class AdaptiveLayout
public const float ExtraSmallThreshold = 15.0f;
}

public static class CommonPaths
{
public const string RecycleBinPath = @"Shell:RecycleBinFolder";

public const string NetworkFolderPath = @"Shell:NetworkPlacesFolder";

public const string MyComputerPath = @"Shell:MyComputerFolder";
}

public static class KnownImageFormats
{
public const string BITMAP_IMAGE_FORMAT = "bitmapimage";
Expand Down
10 changes: 9 additions & 1 deletion src/Files.App/DataModels/SidebarPinnedModel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.WinUI;
using Files.App.DataModels.NavigationControlItems;
using Files.App.Extensions;
using Files.App.Filesystem;
using Files.App.Helpers;
using Files.App.ServicesImplementation;
Expand Down Expand Up @@ -85,8 +86,15 @@ public async Task<LocationItem> CreateLocationItemFromPathAsync(string path)
if (string.Equals(path, CommonPaths.RecycleBinPath, StringComparison.OrdinalIgnoreCase))
locationItem = LocationItem.Create<RecycleBinLocationItem>();
else
{
locationItem = LocationItem.Create<LocationItem>();

if (path.Equals(CommonPaths.MyComputerPath, StringComparison.OrdinalIgnoreCase))
locationItem.Text = "ThisPC".GetLocalizedResource();
else if (path.Equals(CommonPaths.NetworkFolderPath, StringComparison.OrdinalIgnoreCase))
locationItem.Text = "Network".GetLocalizedResource();
}

locationItem.Path = path;
locationItem.Section = SectionType.Favorites;
locationItem.MenuOptions = new ContextMenuOptions
Expand Down Expand Up @@ -136,7 +144,7 @@ public async Task<LocationItem> CreateLocationItemFromPathAsync(string path)
public async Task AddItemToSidebarAsync(string path)
{
var locationItem = await CreateLocationItemFromPathAsync(path);

AddLocationItemToSidebar(locationItem);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Files.App/Filesystem/QuickAccessManager.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
using CommunityToolkit.Mvvm.DependencyInjection;
using CommunityToolkit.WinUI.Helpers;
using Files.App.DataModels;
using Files.App.Helpers;
using Files.App.ServicesImplementation;
using Files.App.UserControls.Widgets;
using System;
using System.IO;
using System.Threading.Tasks;
using static Files.App.Constants;

namespace Files.App.Filesystem
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,36 +270,39 @@ public async static Task<IList<StorageFolderWithPath>> GetFoldersWithPathAsync

private static PathBoxItem GetPathItem(string component, string path)
{
var title = string.Empty;
if (component.StartsWith(CommonPaths.RecycleBinPath, StringComparison.Ordinal))
{
// Handle the recycle bin: use the localized folder name
return new PathBoxItem()
{
Title = ApplicationData.Current.LocalSettings.Values.Get("RecycleBin_Title", "Recycle Bin"),
Path = path,
};
title = "RecycleBin".GetLocalizedResource();
}
else if (component.StartsWith(CommonPaths.MyComputerPath, StringComparison.Ordinal))
{
title = "ThisPC".GetLocalizedResource();
}
else if (component.StartsWith(CommonPaths.NetworkFolderPath, StringComparison.Ordinal))
{
title = "SidebarNetworkDrives".GetLocalizedResource();
}
else if (component.Contains(':', StringComparison.Ordinal))
{
var drives = App.DrivesManager.Drives.Concat(App.NetworkDrivesManager.Drives).Concat(App.CloudDrivesManager.Drives);
var drive = drives.FirstOrDefault(y => y.ItemType is NavigationControlItemType.Drive && y.Path.Contains(component, StringComparison.OrdinalIgnoreCase));
return new PathBoxItem()
{
Title = drive is not null ? drive.Text : $@"Drive ({component})",
Path = path,
};
title = drive is not null ? drive.Text : $@"Drive ({component})";
}
else
{
if (path.EndsWith('\\') || path.EndsWith('/'))
path = path.Remove(path.Length - 1);

return new PathBoxItem
{
Title = component,
Path = path
};
title = component;
}

return new PathBoxItem()
{
Title = title,
Path = path
};
}

private static string GetPathWithoutEnvironmentVariable(string path)
Expand All @@ -323,6 +326,9 @@ private static string ResolvePath(string path, bool isFtp)
if (path.StartsWith("Home"))
return "Home";

if (ShellStorageFolder.IsShellPath(path))
return ShellHelpers.ResolveShellPath(path);

var pathBuilder = new StringBuilder(path);
var lastPathIndex = path.Length - 1;
var separatorChar = isFtp || path.Contains('/', StringComparison.Ordinal) ? '/' : '\\';
Expand All @@ -333,7 +339,7 @@ private static string ResolvePath(string path, bool isFtp)
if (pathBuilder[i] is not '?' &&
pathBuilder[i] != Path.DirectorySeparatorChar &&
pathBuilder[i] != Path.AltDirectorySeparatorChar &&
i != lastIndex)
i != lastPathIndex)
continue;

if (lastIndex == i)
Expand Down
10 changes: 5 additions & 5 deletions src/Files.App/Helpers/CommonPaths.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ public static class CommonPaths
public static readonly string LocalAppDataPath = UserDataPaths.GetDefault().LocalAppData;

// Currently is the command to open the folder from cmd ("cmd /c start Shell:RecycleBinFolder")
public static readonly string RecycleBinPath = Constants.CommonPaths.RecycleBinPath;
public const string RecycleBinPath = @"Shell:RecycleBinFolder";

public static readonly string NetworkFolderPath = Constants.CommonPaths.NetworkFolderPath;
public const string NetworkFolderPath = @"Shell:NetworkPlacesFolder";

public static string MyComputerPath = Constants.CommonPaths.MyComputerPath;
public const string MyComputerPath = @"Shell:MyComputerFolder";

public static readonly string TempPath = ApplicationData.Current.LocalSettings.Values.Get("TEMP", "");

Expand All @@ -31,11 +31,11 @@ public static class CommonPaths
public static Dictionary<string, string> ShellPlaces = new Dictionary<string, string>() {
{ "::{645FF040-5081-101B-9F08-00AA002F954E}", RecycleBinPath },
{ "::{5E5F29CE-E0A8-49D3-AF32-7A7BDC173478}", "Home" /*MyComputerPath*/ },
{ "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", "Home" /*MyComputerPath*/ },
{ "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}", MyComputerPath },
{ "::{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}", NetworkFolderPath },
{ "::{208D2C60-3AEA-1069-A2D7-08002B30309D}", NetworkFolderPath },
{ RecycleBinPath.ToUpperInvariant(), RecycleBinPath },
{ MyComputerPath.ToUpperInvariant(), "Home" /*MyComputerPath*/ },
{ MyComputerPath.ToUpperInvariant(), MyComputerPath },
{ NetworkFolderPath.ToUpperInvariant(), NetworkFolderPath },
};
}
Expand Down
42 changes: 42 additions & 0 deletions src/Files.App/Helpers/ShellHelpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
using Files.App.Extensions;
using Files.Shared;
using System;
using System.IO;

namespace Files.App.Helpers
{
public static class ShellHelpers
{
public static string ResolveShellPath(string shPath)
{
if (shPath.StartsWith(CommonPaths.RecycleBinPath, StringComparison.OrdinalIgnoreCase))
return CommonPaths.RecycleBinPath;

if (shPath.StartsWith(CommonPaths.MyComputerPath, StringComparison.OrdinalIgnoreCase))
return CommonPaths.MyComputerPath;

if (shPath.StartsWith(CommonPaths.NetworkFolderPath, StringComparison.OrdinalIgnoreCase))
return CommonPaths.NetworkFolderPath;

return shPath;
}

public static string GetShellNameFromPath(string shPath)
{
return shPath switch
{
"Home" => "Home".GetLocalizedResource(),
CommonPaths.RecycleBinPath => "RecycleBin".GetLocalizedResource(),
CommonPaths.NetworkFolderPath => "SidebarNetworkDrives".GetLocalizedResource(),
CommonPaths.MyComputerPath => "ThisPC".GetLocalizedResource(),
_ => shPath
};
}

public static string GetLibraryFullPathFromShell(string shPath)
{
var partialPath = shPath.Substring(shPath.IndexOf('\\') + 1);
return Path.Combine(ShellLibraryItem.LibrariesPath, partialPath);
}
}
}
13 changes: 8 additions & 5 deletions src/Files.App/ServicesImplementation/JumpListService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Files.App.Filesystem;
using Files.App.Extensions;
using Files.App.Filesystem;
using Files.App.Helpers;
using Files.Shared.Extensions;
using Files.Shared.Services;
Expand Down Expand Up @@ -122,15 +123,17 @@ private void AddFolder(string path, string group, JumpList instance)

if (displayName is null)
{
var localSettings = ApplicationData.Current.LocalSettings;
if (path.Equals(CommonPaths.DesktopPath, StringComparison.OrdinalIgnoreCase))
displayName = "ms-resource:///Resources/Desktop";
else if (path.Equals(CommonPaths.DownloadsPath, StringComparison.OrdinalIgnoreCase))
displayName = "ms-resource:///Resources/Downloads";
else if (path.Equals(CommonPaths.RecycleBinPath, StringComparison.OrdinalIgnoreCase))
{
var localSettings = ApplicationData.Current.LocalSettings;
displayName = localSettings.Values.Get("RecycleBin_Title", "Recycle Bin");
}
displayName = "RecycleBin".GetLocalizedResource();
else if (path.Equals(CommonPaths.MyComputerPath, StringComparison.OrdinalIgnoreCase))
displayName = "ThisPC".GetLocalizedResource();
else if (path.Equals(CommonPaths.NetworkFolderPath, StringComparison.OrdinalIgnoreCase))
displayName = "SidebarNetworkDrives".GetLocalizedResource();
else if (App.LibraryManager.TryGetLibrary(path, out LibraryLocationItem library))
{
var libName = Path.GetFileNameWithoutExtension(library.Path);
Expand Down
5 changes: 3 additions & 2 deletions src/Files.App/ServicesImplementation/QuickAccessService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Files.App.Shell;
using Files.App.Helpers;
using Files.App.Shell;
using Files.App.UserControls.Widgets;
using Files.Shared;
using Files.Shared.Extensions;
Expand Down Expand Up @@ -53,7 +54,7 @@ public async Task UnpinFromSidebar(string[] folderPaths)
foreach (dynamic? fi in f2.Items())
{
if (folderPaths.Contains((string)fi.Path)
|| (string.Equals(fi.Path, "::{645FF040-5081-101B-9F08-00AA002F954E}") && folderPaths.Contains(Constants.CommonPaths.RecycleBinPath)))
|| (string.Equals(fi.Path, "::{645FF040-5081-101B-9F08-00AA002F954E}") && folderPaths.Contains(CommonPaths.RecycleBinPath)))
{
await SafetyExtensions.IgnoreExceptions(async () =>
{
Expand Down
3 changes: 0 additions & 3 deletions src/Files.App/Shell/RecycleBinManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,6 @@ private RecycleBinManager()
private void Initialize()
{
// Create shell COM object and get recycle bin folder
using var recycler = new ShellFolder(Shell32.KNOWNFOLDERID.FOLDERID_RecycleBinFolder);
ApplicationData.Current.LocalSettings.Values["RecycleBin_Title"] = recycler.Name;

StartRecycleBinWatcher();
}

Expand Down
14 changes: 10 additions & 4 deletions src/Files.App/Shell/ShellFolderExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Files.Shared;
using Files.App.Helpers;
using Files.Shared;
using Files.Shared.Extensions;
using System;
using System.IO;
Expand Down Expand Up @@ -57,9 +58,14 @@ public static ShellFileItem GetShellFileItem(ShellItem folderItem)
{
parsingPath = parsingPath switch
{
"::{645FF040-5081-101B-9F08-00AA002F954E}" => "Shell:RecycleBinFolder",
"::{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}" => "Shell:NetworkPlacesFolder",
"::{208D2C60-3AEA-1069-A2D7-08002B30309D}" => "Shell:NetworkPlacesFolder",
"::{645FF040-5081-101B-9F08-00AA002F954E}" => CommonPaths.RecycleBinPath,
"::{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}" => CommonPaths.NetworkFolderPath,
"::{208D2C60-3AEA-1069-A2D7-08002B30309D}" => CommonPaths.NetworkFolderPath,
"::{20D04FE0-3AEA-1069-A2D8-08002B30309D}" => CommonPaths.MyComputerPath,
"::{031E4825-7B94-4DC3-B131-E946B44C8DD5}\\Documents.library-ms" => ShellHelpers.GetLibraryFullPathFromShell(parsingPath),
"::{031E4825-7B94-4DC3-B131-E946B44C8DD5}\\Pictures.library-ms" => ShellHelpers.GetLibraryFullPathFromShell(parsingPath),
"::{031E4825-7B94-4DC3-B131-E946B44C8DD5}\\Music.library-ms" => ShellHelpers.GetLibraryFullPathFromShell(parsingPath),
"::{031E4825-7B94-4DC3-B131-E946B44C8DD5}\\Videos.library-ms" => ShellHelpers.GetLibraryFullPathFromShell(parsingPath),
// Use PIDL as path
// Replace "/" with "_" to avoid confusion with path separator
_ => $@"\\SHELL\{string.Join("\\", folderItem.PIDL.Select(x => x.GetBytes()).Select(x => Convert.ToBase64String(x, 0, x.Length).Replace("/", "_")))}"
Expand Down
6 changes: 6 additions & 0 deletions src/Files.App/Strings/en-US/Resources.resw
Original file line number Diff line number Diff line change
Expand Up @@ -2857,6 +2857,12 @@
<data name="ShowFileExtensionWarning" xml:space="preserve">
<value>Show warning when changing file extensions</value>
</data>
<data name="ThisPC" xml:space="preserve">
<value>This PC</value>
</data>
<data name="RecycleBin" xml:space="preserve">
<value>Recycle Bin</value>
</data>
<data name="Untagged" xml:space="preserve">
<value>Untagged</value>
</data>
Expand Down
9 changes: 6 additions & 3 deletions src/Files.App/ViewModels/ItemViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ private async void RecycleBinItemCreated(object sender, FileSystemEventArgs e)
return;

using var folderItem = SafetyExtensions.IgnoreExceptions(() => new ShellItem(e.FullPath));
if (folderItem is null)
if (folderItem is null)
return;

var shellFileItem = ShellFolderExtensions.GetShellFileItem(folderItem);
Expand Down Expand Up @@ -1389,8 +1389,11 @@ public async Task EnumerateItemsFromSpecialFolderAsync(string path)
{
PrimaryItemAttribute = StorageItemTypes.Folder,
ItemPropertiesInitialized = true,
ItemNameRaw = path.StartsWith(CommonPaths.RecycleBinPath, StringComparison.Ordinal) ? ApplicationData.Current.LocalSettings.Values.Get("RecycleBin_Title", "Recycle Bin") :
path.StartsWith(CommonPaths.NetworkFolderPath, StringComparison.Ordinal) ? "Network".GetLocalizedResource() : isFtp ? "FTP" : "Unknown",
ItemNameRaw =
path.StartsWith(CommonPaths.RecycleBinPath, StringComparison.OrdinalIgnoreCase) ? "RecycleBin".GetLocalizedResource() :
path.StartsWith(CommonPaths.NetworkFolderPath, StringComparison.OrdinalIgnoreCase) ? "Network".GetLocalizedResource() :
path.StartsWith(CommonPaths.MyComputerPath, StringComparison.OrdinalIgnoreCase) ? "ThisPC".GetLocalizedResource() :
isFtp ? "FTP" : "Unknown",
ItemDateModifiedReal = DateTimeOffset.Now, // Fake for now
ItemDateCreatedReal = DateTimeOffset.Now, // Fake for now
ItemType = "Folder".GetLocalizedResource(),
Expand Down
7 changes: 5 additions & 2 deletions src/Files.App/ViewModels/MainPageViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,11 @@ public static async Task UpdateTabInfo(TabItem tabItem, object navigationArg)
}
else if (currentPath.Equals(CommonPaths.RecycleBinPath, StringComparison.OrdinalIgnoreCase))
{
var localSettings = ApplicationData.Current.LocalSettings;
tabLocationHeader = localSettings.Values.Get("RecycleBin_Title", "Recycle Bin");
tabLocationHeader = "RecycleBin".GetLocalizedResource();
}
else if (currentPath.Equals(CommonPaths.MyComputerPath, StringComparison.OrdinalIgnoreCase))
{
tabLocationHeader = "ThisPC".GetLocalizedResource();
}
else if (currentPath.Equals(CommonPaths.NetworkFolderPath, StringComparison.OrdinalIgnoreCase))
{
Expand Down
11 changes: 1 addition & 10 deletions src/Files.App/ViewModels/Settings/PreferencesViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Files.App.Helpers;
using Files.Backend.Services.Settings;
using Files.Shared.Enums;
using Files.Shared.Extensions;
using Files.Shared.Services.DateTimeFormatter;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -600,15 +599,7 @@ public class PageOnStartupViewModel
{
public string Text
{
get
{
if (Path == "Home")
return "Home".GetLocalizedResource();

return (Path == CommonPaths.RecycleBinPath)
? ApplicationData.Current.LocalSettings.Values.Get("RecycleBin_Title", "Recycle Bin")
: Path;
}
get => ShellHelpers.GetShellNameFromPath(Path);
}

public string Path { get; }
Expand Down