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
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
9 changes: 6 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));
OnConnectionRequestReceived(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 void OnConnectionRequestReceived(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,10 @@ 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(async () =>
{
await Task.Run(() => 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