Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
4 changes: 2 additions & 2 deletions Files.Launcher/MessageHandlers/Win32MessageHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public async Task ParseArgumentsAsync(PipeStream connection, Dictionary<string,
var fileIconPath = (string)message["filePath"];
var thumbnailSize = (int)(long)message["thumbnailSize"];
var isOverlayOnly = (bool)message["isOverlayOnly"];
var iconOverlay = Win32API.StartSTATask(() => Win32API.GetFileIconAndOverlay(fileIconPath, thumbnailSize, true, isOverlayOnly)).Result;
var iconOverlay = await Win32API.StartSTATask(() => Win32API.GetFileIconAndOverlay(fileIconPath, thumbnailSize, true, isOverlayOnly));
await Win32API.SendMessageAsync(connection, new ValueSet()
{
{ "Icon", iconOverlay.icon },
Expand All @@ -73,7 +73,7 @@ public async Task ParseArgumentsAsync(PipeStream connection, Dictionary<string,
case "GetIconWithoutOverlay":
var fileIconPath2 = (string)message["filePath"];
var thumbnailSize2 = (int)(long)message["thumbnailSize"];
var icon2 = Win32API.StartSTATask(() => Win32API.GetFileIconAndOverlay(fileIconPath2, thumbnailSize2, false)).Result;
var icon2 = await Win32API.StartSTATask(() => Win32API.GetFileIconAndOverlay(fileIconPath2, thumbnailSize2, false));
await Win32API.SendMessageAsync(connection, new ValueSet()
{
{ "Icon", icon2.icon },
Expand Down
6 changes: 3 additions & 3 deletions Files.Launcher/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ private static void EndReadCallBack(IAsyncResult result)
{
var message = info.Message.ToString().TrimEnd('\0');

Connection_RequestReceived(connection, JsonConvert.DeserializeObject<Dictionary<string, object>>(message));
_ = Task.Run(() => Connection_RequestReceived(connection, JsonConvert.DeserializeObject<Dictionary<string, object>>(message)));

// Begin a new reading operation
var nextInfo = (Buffer: new byte[connection.InBufferSize], Message: new StringBuilder());
Expand All @@ -170,7 +170,7 @@ private static void EndReadCallBack(IAsyncResult result)
}
}

private static async void Connection_RequestReceived(PipeStream conn, Dictionary<string, object> message)
private static async Task Connection_RequestReceived(PipeStream conn, Dictionary<string, object> message)
{
// Get a deferral because we use an awaitable API below to respond to the message
// and we don't want this call to get cancelled while we are waiting.
Expand All @@ -187,7 +187,7 @@ private static async void Connection_RequestReceived(PipeStream conn, Dictionary
var arguments = (string)message["Arguments"];
Logger.Info($"Argument: {arguments}");

await ParseArgumentsAsync(message, arguments);
await Extensions.IgnoreExceptions(() => ParseArgumentsAsync(message, arguments), Logger);
}
}

Expand Down
37 changes: 23 additions & 14 deletions Files.Launcher/Win32API.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@ public static string[] CommandLineToArgs(string commandLine)
}
}

private static object lockObject = new object();

public static (string icon, string overlay) GetFileIconAndOverlay(string path, int thumbnailSize, bool getOverlay = true, bool onlyGetOverlay = false)
{
string iconStr = null, overlayStr = null;
Expand Down Expand Up @@ -197,24 +199,31 @@ public static (string icon, string overlay) GetFileIconAndOverlay(string path, i
}

User32.DestroyIcon(shfi.hIcon);
Shell32.SHGetImageList(Shell32.SHIL.SHIL_LARGE, typeof(ComCtl32.IImageList).GUID, out var tmp);
using var imageList = ComCtl32.SafeHIMAGELIST.FromIImageList(tmp);
if (imageList.IsNull || imageList.IsInvalid)
{
return (iconStr, null);
}

var overlayIdx = shfi.iIcon >> 24;
if (overlayIdx != 0)
lock (lockObject)
{
var overlayImage = imageList.Interface.GetOverlayImage(overlayIdx);
using var hOverlay = imageList.Interface.GetIcon(overlayImage, ComCtl32.IMAGELISTDRAWFLAGS.ILD_TRANSPARENT);
if (!hOverlay.IsNull && !hOverlay.IsInvalid)
if (!Shell32.SHGetImageList(Shell32.SHIL.SHIL_LARGE, typeof(ComCtl32.IImageList).GUID, out var imageList).Succeeded)
{
using var image = hOverlay.ToIcon().ToBitmap();
byte[] bitmapData = (byte[])new ImageConverter().ConvertTo(image, typeof(byte[]));
overlayStr = Convert.ToBase64String(bitmapData, 0, bitmapData.Length);
return (iconStr, null);
}

var overlayIdx = shfi.iIcon >> 24;
if (overlayIdx != 0)
{
var overlayImage = imageList.GetOverlayImage(overlayIdx);
using var hOverlay = imageList.GetIcon(overlayImage, ComCtl32.IMAGELISTDRAWFLAGS.ILD_TRANSPARENT);
if (!hOverlay.IsNull && !hOverlay.IsInvalid)
{
using (var icon = hOverlay.ToIcon())
using (var image = icon.ToBitmap())
{
byte[] bitmapData = (byte[])new ImageConverter().ConvertTo(image, typeof(byte[]));
overlayStr = Convert.ToBase64String(bitmapData, 0, bitmapData.Length);
}
}
}

Marshal.ReleaseComObject(imageList);
}

return (iconStr, overlayStr);
Expand Down
3 changes: 2 additions & 1 deletion Files/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ await Task.WhenAll(
AppSettings.DetectQuickLook(),
TerminalController.InitializeAsync(),
JumpList.InitializeAsync(),
ExternalResourcesHelper.LoadOtherThemesAsync()
ExternalResourcesHelper.LoadOtherThemesAsync(),
ContextFlyoutItemHelper.CachedNewContextMenuEntries
);
});

Expand Down
29 changes: 7 additions & 22 deletions Files/Helpers/ContextFlyoutItemHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,7 @@ namespace Files.Helpers
{
public static class ContextFlyoutItemHelper
{
private static List<ShellNewEntry> cachedNewContextMenuEntries;

public static List<ShellNewEntry> CachedNewContextMenuEntries
{
get
{
cachedNewContextMenuEntries ??= Task.Run(() => ShellNewEntryExtensions.GetNewContextMenuEntries()).Result;
return cachedNewContextMenuEntries;
}
}

private static List<ContextMenuFlyoutItemViewModel> cachedNewItemItems;
public static Task<List<ShellNewEntry>> CachedNewContextMenuEntries = ShellNewEntryExtensions.GetNewContextMenuEntries();

public static List<ContextMenuFlyoutItemViewModel> GetItemContextCommandsWithoutShellItems(CurrentInstanceViewModel currentInstanceViewModel, string workingDir, List<ListedItem> selectedItems, BaseLayoutCommandsViewModel commandsViewModel, bool shiftPressed, bool showOpenMenu, SelectedItemsPropertiesViewModel selectedItemsPropertiesViewModel)
{
Expand Down Expand Up @@ -1053,19 +1042,16 @@ public static List<ContextMenuFlyoutItemViewModel> GetNewItemItems(BaseLayoutCom
}
};

CachedNewContextMenuEntries?.ForEach(i =>
var cachedNewContextMenuEntries = CachedNewContextMenuEntries.IsCompletedSuccessfully ? CachedNewContextMenuEntries.Result : null;
cachedNewContextMenuEntries?.ForEach(i =>
{
if (!string.IsNullOrEmpty(i.IconBase64))
{
// loading the bitmaps takes a while, so this caches them
var bitmap = cachedNewItemItems?.Where(x => x.Text == i.Name).FirstOrDefault()?.BitmapIcon;
if (bitmap == null)
{
byte[] bitmapData = Convert.FromBase64String(i.IconBase64);
using var ms = new MemoryStream(bitmapData);
bitmap = new BitmapImage();
_ = bitmap.SetSourceAsync(ms.AsRandomAccessStream());
}
byte[] bitmapData = Convert.FromBase64String(i.IconBase64);
using var ms = new MemoryStream(bitmapData);
var bitmap = new BitmapImage();
_ = bitmap.SetSourceAsync(ms.AsRandomAccessStream());
list.Add(new ContextMenuFlyoutItemViewModel()
{
Text = i.Name,
Expand All @@ -1086,7 +1072,6 @@ public static List<ContextMenuFlyoutItemViewModel> GetNewItemItems(BaseLayoutCom
}
});

cachedNewItemItems = list;
return list;
}
}
Expand Down
26 changes: 12 additions & 14 deletions Files/Helpers/UIFilesystemHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ public static async void CutItem(IShellPage associatedInstance)
RequestedOperation = DataPackageOperation.Move
};
ConcurrentBag<IStorageItem> items = new ConcurrentBag<IStorageItem>();
FilesystemResult result = (FilesystemResult)false;

var canFlush = true;
if (associatedInstance.SlimContentPage.IsItemSelected)
Expand Down Expand Up @@ -61,27 +60,27 @@ await Task.WhenAll(associatedInstance.SlimContentPage.SelectedItems.ToList().Sel
}
else if (listedItem.PrimaryItemAttribute == StorageItemTypes.File || listedItem is ZipItem)
{
result = await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(listedItem.ItemPath)
var result = await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(listedItem.ItemPath)
.OnSuccess(t => items.Add(t));
if (!result)
{
throw new IOException($"Failed to process {listedItem.ItemPath}.");
throw new IOException($"Failed to process {listedItem.ItemPath}.", (int)result.ErrorCode);
}
}
else
{
result = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(listedItem.ItemPath)
var result = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(listedItem.ItemPath)
.OnSuccess(t => items.Add(t));
if (!result)
{
throw new IOException($"Failed to process {listedItem.ItemPath}.");
throw new IOException($"Failed to process {listedItem.ItemPath}.", (int)result.ErrorCode);
}
}
}));
}
catch
catch (Exception ex)
{
if (result.ErrorCode == FileSystemStatusCode.Unauthorized)
if (ex.HResult == (int)FileSystemStatusCode.Unauthorized)
{
// Try again with fulltrust process
var connection = await AppServiceConnectionHelper.Instance;
Expand Down Expand Up @@ -139,7 +138,6 @@ public static async Task CopyItem(IShellPage associatedInstance)
ConcurrentBag<IStorageItem> items = new ConcurrentBag<IStorageItem>();

string copySourcePath = associatedInstance.FilesystemViewModel.WorkingDirectory;
FilesystemResult result = (FilesystemResult)false;

var canFlush = true;
if (associatedInstance.SlimContentPage.IsItemSelected)
Expand All @@ -162,27 +160,27 @@ await Task.WhenAll(associatedInstance.SlimContentPage.SelectedItems.ToList().Sel
}
else if (listedItem.PrimaryItemAttribute == StorageItemTypes.File || listedItem is ZipItem)
{
result = await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(listedItem.ItemPath)
var result = await associatedInstance.FilesystemViewModel.GetFileFromPathAsync(listedItem.ItemPath)
.OnSuccess(t => items.Add(t));
if (!result)
{
throw new IOException($"Failed to process {listedItem.ItemPath}.");
throw new IOException($"Failed to process {listedItem.ItemPath}.", (int)result.ErrorCode);
}
}
else
{
result = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(listedItem.ItemPath)
var result = await associatedInstance.FilesystemViewModel.GetFolderFromPathAsync(listedItem.ItemPath)
.OnSuccess(t => items.Add(t));
if (!result)
{
throw new IOException($"Failed to process {listedItem.ItemPath}.");
throw new IOException($"Failed to process {listedItem.ItemPath}.", (int)result.ErrorCode);
}
}
}));
}
catch
catch (Exception ex)
{
if (result.ErrorCode == FileSystemStatusCode.Unauthorized)
if (ex.HResult == (int)FileSystemStatusCode.Unauthorized)
{
// Try again with fulltrust process
var connection = await AppServiceConnectionHelper.Instance;
Expand Down
3 changes: 1 addition & 2 deletions Files/UserControls/InnerNavigationToolbar.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@
Grid.Column="0"
HorizontalAlignment="Left"
VerticalAlignment="Stretch"
DefaultLabelPosition="Right"
Loaded="ContextCommandBar_Loaded">
DefaultLabelPosition="Right">
<CommandBar.Resources>
<ResourceDictionary>
<SolidColorBrush x:Key="CommandBarBackgroundOpen" Color="Transparent" />
Expand Down
9 changes: 2 additions & 7 deletions Files/UserControls/InnerNavigationToolbar.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using Files.Common;
using Files.Extensions;
using Files.Helpers;
using Files.Services;
using Files.ViewModels;
using Microsoft.Toolkit.Mvvm.DependencyInjection;
Expand Down Expand Up @@ -141,8 +142,6 @@ public ICommand SetCompactOverlayCommand
/// <returns></returns>
private string GetLocalizedString(string str) => str.GetLocalized();

private List<ShellNewEntry> cachedNewContextMenuEntries { get; set; }

private void NewEmptySpace_Opening(object sender, object e)
{
if (!ViewModel.InstanceViewModel.CanCreateFileInPage)
Expand All @@ -151,6 +150,7 @@ private void NewEmptySpace_Opening(object sender, object e)
shell.ForEach(x => NewEmptySpace.Items.Remove(x));
return;
}
var cachedNewContextMenuEntries = ContextFlyoutItemHelper.CachedNewContextMenuEntries.IsCompletedSuccessfully ? ContextFlyoutItemHelper.CachedNewContextMenuEntries.Result : null;
if (cachedNewContextMenuEntries == null)
{
return;
Expand Down Expand Up @@ -192,10 +192,5 @@ private void NewEmptySpace_Opening(object sender, object e)
}
}
}

private async void ContextCommandBar_Loaded(object sender, RoutedEventArgs e)
{
cachedNewContextMenuEntries = await ShellNewEntryExtensions.GetNewContextMenuEntries();
}
}
}
4 changes: 2 additions & 2 deletions Files/Views/LayoutModes/ColumnViewBase.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -389,7 +389,7 @@ private void FileList_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
if (item.PrimaryItemAttribute == StorageItemTypes.Folder)
{
listViewItem = FileList.ContainerFromItem(item) as ListViewItem;
ItemInvoked?.Invoke(new ColumnParam { NavPathParam = item.ItemPath, ListView = FileList }, EventArgs.Empty);
ItemInvoked?.Invoke(new ColumnParam { NavPathParam = (item is ShortcutItem sht ? sht.TargetPath : item.ItemPath), ListView = FileList }, EventArgs.Empty);
}
else
{
Expand Down Expand Up @@ -446,7 +446,7 @@ private void FileList_ItemTapped(object sender, TappedRoutedEventArgs e)
if (item.PrimaryItemAttribute == StorageItemTypes.Folder)
{
listViewItem = FileList.ContainerFromItem(item) as ListViewItem;
ItemInvoked?.Invoke(new ColumnParam { NavPathParam = item.ItemPath, ListView = FileList }, EventArgs.Empty);
ItemInvoked?.Invoke(new ColumnParam { NavPathParam = (item is ShortcutItem sht ? sht.TargetPath : item.ItemPath), ListView = FileList }, EventArgs.Empty);
}
else
{
Expand Down