Skip to content
Open
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
111 changes: 73 additions & 38 deletions src/Files.App/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) Files Community
// Licensed under the MIT License.

using Files.Shared.Helpers;
using Microsoft.Extensions.Logging;
using Microsoft.UI;
using Microsoft.UI.Windowing;
Expand Down Expand Up @@ -71,7 +72,7 @@ public async Task InitializeApplicationAsync(object activatedEventArgs)
// WINUI3: When launching from commandline the argument is not ICommandLineActivatedEventArgs (#10370)
var ppm = CommandLineParser.ParseUntrustedCommands(launchArgs.Arguments);
if (ppm.IsEmpty())
rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo());
LaunchMainPage(rootFrame);
else
await InitializeFromCmdLineArgsAsync(rootFrame, ppm, Program.ConsumeLaunchCwd());
}
Expand All @@ -90,30 +91,35 @@ public async Task InitializeApplicationAsync(object activatedEventArgs)
}
else
{
rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo());
LaunchMainPage(rootFrame);
}
break;

case IProtocolActivatedEventArgs eventArgs:
if (eventArgs.Uri.AbsoluteUri == "files-dev:")
{
rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo());

// Bring to foreground (#14730)
Win32Helper.BringToForegroundEx(new(WindowHandle));

// Ensure app-level keyboard shortcuts work immediately after Win+E activation.
_ = EnsureContentHasKeyboardFocusAsync();
LaunchMainPage(rootFrame);
}
else
{
var parsedArgs = eventArgs.Uri.Query.TrimStart('?').Split('=');
var unescapedValue = Uri.UnescapeDataString(parsedArgs[1].Split('&')[0]);
if (parsedArgs[0] == "tab" && parsedArgs.Length > 3 &&
int.TryParse(parsedArgs[2].Split('&')[0], out var dx) &&
int.TryParse(parsedArgs[3], out var dy))
AppWindow?.Move(new(dx - 100, dy - 16));
var folder = (StorageFolder)await FilesystemTasks.Wrap(() => StorageFolder.GetFolderFromPathAsync(unescapedValue).AsTask());
string[] parsedArgs;
string? unescapedValue;
StorageFolder? folder;
try
{
parsedArgs = eventArgs.Uri.Query.TrimStart('?').Split('=');
unescapedValue = Uri.UnescapeDataString(parsedArgs[1].Split('&')[0]);
if (parsedArgs[0] == "tab" && parsedArgs.Length > 3 &&
int.TryParse(parsedArgs[2].Split('&')[0], out var dx) &&
int.TryParse(parsedArgs[3], out var dy))
AppWindow?.Move(new(dx - 100, dy - 16));
folder = (StorageFolder)await FilesystemTasks.Wrap(() => StorageFolder.GetFolderFromPathAsync(unescapedValue).AsTask());
}
catch
{
LaunchMainPage(rootFrame);
break;
}
if (folder is not null && !string.IsNullOrEmpty(folder.Path))
{
// Convert short name to long name (#6190)
Expand All @@ -136,12 +142,12 @@ public async Task InitializeApplicationAsync(object activatedEventArgs)
case "cmd":
var ppm = CommandLineParser.ParseUntrustedCommands(unescapedValue);
if (ppm.IsEmpty())
rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo());
LaunchMainPage(rootFrame);
else
await InitializeFromCmdLineArgsAsync(rootFrame, ppm, Environment.CurrentDirectory);
break;
default:
rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo());
LaunchMainPage(rootFrame);
break;
}
}
Expand All @@ -159,7 +165,7 @@ public async Task InitializeApplicationAsync(object activatedEventArgs)
}
else
{
rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo());
LaunchMainPage(rootFrame);
}
break;

Expand Down Expand Up @@ -200,14 +206,8 @@ public async Task InitializeApplicationAsync(object activatedEventArgs)
}
break;

case IStartupTaskActivatedEventArgs startupArgs:
// Just launch the app with no arguments
rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo());
break;

default:
// Just launch the app with no arguments
rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo());
LaunchMainPage(rootFrame);
break;
}

Expand Down Expand Up @@ -262,11 +262,12 @@ private async Task EnsureContentHasKeyboardFocusAsync()

private async Task InitializeFromCmdLineArgsAsync(Frame rootFrame, ParsedCommands parsedCommands, string activationPath = "")
{
async Task PerformNavigationAsync(string payload, string selectItem = null)
// Navigate to a folder in the UI
async Task PerformNavigationAsync(string? payload, string? selectItem = null)
{
if (!string.IsNullOrEmpty(payload))
{
payload = Constants.UserEnvironmentPaths.ShellPlaces.Get(payload.ToUpperInvariant(), payload);
payload = Constants.UserEnvironmentPaths.ShellPlaces.Get(payload.ToUpperInvariant(), payload)!;
var folder = (StorageFolder)await FilesystemTasks.Wrap(() => StorageFolder.GetFolderFromPathAsync(payload).AsTask());
if (folder is not null && !string.IsNullOrEmpty(folder.Path))
payload = folder.Path; // Convert short name to long name (#6190)
Expand Down Expand Up @@ -315,12 +316,42 @@ x.tabItem.NavigationParameter.NavigationParameter is PaneNavigationArguments pan
else
rootFrame.Navigate(typeof(MainPage), paneNavigationArgs, new SuppressNavigationTransitionInfo());
}

// Open a path (navigate to a folder in the UI / open a file depending on what the path attributes are)
async Task OpenPathAsync(string payload)
{
if (!string.IsNullOrEmpty(payload))
{
try
{
var target = Path.IsPathFullyQualified(payload) ? IO.Path.GetFullPath(payload) : IO.Path.GetFullPath(IO.Path.Combine(activationPath, payload));
var attributes = IO.File.GetAttributes(target);
if (attributes.HasFlag(IO.FileAttributes.Directory) || FileExtensionHelpers.IsBrowsableZipFile(target, out _))
await PerformNavigationAsync(target);
else
await LaunchHelper.LaunchAppAsync("explorer", payload, activationPath);
}
catch
{
await LaunchHelper.LaunchAppAsync("explorer", payload, activationPath);
}
}
else
{
await PerformNavigationAsync(null!);
}
}

foreach (var command in parsedCommands)
{
switch (command.Type)
{
case ParsedCommandType.OpenDirectory:
await OpenPathAsync(command.Payload);
break;
case ParsedCommandType.OpenPath:
await OpenPathAsync(command.Payload);
break;
case ParsedCommandType.ExplorerShellCommand:
var selectItemCommand = parsedCommands.FirstOrDefault(x => x.Type == ParsedCommandType.SelectItem);
await PerformNavigationAsync(command.Payload, selectItemCommand?.Payload);
Expand All @@ -333,7 +364,7 @@ x.tabItem.NavigationParameter.NavigationParameter is PaneNavigationArguments pan

case ParsedCommandType.TagFiles:
var tagService = Ioc.Default.GetService<IFileTagsSettingsService>();
var tag = tagService.GetTagsByName(command.Payload).FirstOrDefault();
var tag = tagService!.GetTagsByName(command.Payload).FirstOrDefault();
foreach (var file in command.Args.Skip(1))
{
var fileFRN = await FilesystemTasks.Wrap(() => StorageHelpers.ToStorageItem<IStorageItem>(file))
Expand All @@ -355,15 +386,8 @@ x.tabItem.NavigationParameter.NavigationParameter is PaneNavigationArguments pan
}
else
{
if (!string.IsNullOrEmpty(command.Payload))
{
var target = IO.Path.GetFullPath(IO.Path.Combine(activationPath, command.Payload));
await PerformNavigationAsync(target);
}
else
{
await PerformNavigationAsync(null);
}
await OpenPathAsync(command.Payload);
break;
}
break;

Expand Down Expand Up @@ -395,5 +419,16 @@ private void WindowManager_WindowMessageReceived(object? sender, WinUIEx.Messagi
e.Handled = true;
}
}

private void LaunchMainPage(Frame rootFrame)
{
rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo());

// Bring to foreground (#14730)
Win32Helper.BringToForegroundEx(new(WindowHandle));

// Ensure app-level keyboard shortcuts work immediately after Win+E activation.
_ = EnsureContentHasKeyboardFocusAsync();
}
}
}
Loading