Skip to content
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

Code Quality: Improved app startup routine 2 - Checkpoint 2 #14045

Closed
wants to merge 11 commits into from
1 change: 0 additions & 1 deletion src/Files.App/Actions/Start/PinToStartAction.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.

using CommunityToolkit.Mvvm.DependencyInjection;
using Files.Core.Storage;

namespace Files.App.Actions
Expand Down
32 changes: 23 additions & 9 deletions src/Files.App/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,10 @@ protected override void OnLaunched(LaunchActivatedEventArgs e)
async Task ActivateAsync()
{
// Get AppActivationArguments
var appActivationArguments = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
var isStartupTask = appActivationArguments.Data is Windows.ApplicationModel.Activation.IStartupTaskActivatedEventArgs;
var appActivationArguments =
Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
var isStartupTask =
appActivationArguments.Data is Windows.ApplicationModel.Activation.IStartupTaskActivatedEventArgs;

if (!isStartupTask)
{
Expand All @@ -82,7 +84,8 @@ async Task ActivateAsync()
}

// Start tracking app usage
if (appActivationArguments.Data is Windows.ApplicationModel.Activation.IActivatedEventArgs activationEventArgs)
if (appActivationArguments.Data is Windows.ApplicationModel.Activation.IActivatedEventArgs
activationEventArgs)
SystemInformation.Instance.TrackAppUse(activationEventArgs);

// Configure the DI (dependency injection) container
Expand Down Expand Up @@ -130,13 +133,18 @@ async Task ActivateAsync()
await SplashScreenLoadingTCS!.Task.WithTimeoutAsync(TimeSpan.FromMilliseconds(500));
SplashScreenLoadingTCS = null;

// Initialize most required components
_ = AppLifecycleHelper.InitializeMandatoryAsync();
await MainWindow.Instance.InitializeApplicationAsync(appActivationArguments.Data);

// Create a system tray icon
SystemTrayIcon = new SystemTrayIcon().Show();

_ = MainWindow.Instance.InitializeApplicationAsync(appActivationArguments.Data);
}

await AppLifecycleHelper.InitializeAppComponentsAsync();
// Continue initialization once the initial screen is loaded
await Task.Delay(50);
_ = AppLifecycleHelper.InitializeLateAsync();


if (isStartupTask && isLeaveAppRunning)
{
Expand All @@ -145,10 +153,11 @@ async Task ActivateAsync()
App.Current.Exit();
}
else
await AppLifecycleHelper.CheckAppUpdate();
_ = AppLifecycleHelper.CheckUpdatesAsync();
}
}


/// <summary>
/// Gets invoked when the application is activated.
/// </summary>
Expand All @@ -159,7 +168,12 @@ public async Task OnActivatedAsync(AppActivationArguments activatedEventArgs)

// InitializeApplication accesses UI, needs to be called on UI thread
await MainWindow.Instance.DispatcherQueue.EnqueueOrInvokeAsync(()
=> MainWindow.Instance.InitializeApplicationAsync(activatedEventArgsData));
=>
{
// Important: To initialize app after resuming from background, we need to reset Window's content
MainWindow.Instance.Content = null;
return MainWindow.Instance.InitializeApplicationAsync(activatedEventArgsData);
});
}

/// <summary>
Expand Down Expand Up @@ -234,7 +248,7 @@ private async void Window_Closed(object sender, WindowEventArgs args)
if (!AppModel.ForceProcessTermination)
{
args.Handled = true;
_ = AppLifecycleHelper.CheckAppUpdate();
_ = AppLifecycleHelper.CheckUpdatesAsync();
return;
}
}
Expand Down
5 changes: 2 additions & 3 deletions src/Files.App/Data/Models/AppModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ public int TabStripSelectedIndex

if (value >= 0 && value < MainPageViewModel.AppInstances.Count)
{
Frame rootFrame = (Frame)MainWindow.Instance.Content;
var mainView = (MainPage)rootFrame.Content;
mainView.ViewModel.SelectedTabItem = MainPageViewModel.AppInstances[value];
if (MainWindow.Instance.GetMainPage() is { } mainPage)
mainPage.ViewModel.SelectedTabItem = MainPageViewModel.AppInstances[value];
Comment on lines 38 to +41
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might as well combine the IF statements.

}
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/Files.App/Extensions/UIExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;

namespace Files.App.Extensions
{
public static class UIExtensions
{
public static MainPage? GetMainPage(this MainWindow mainWindow)
{
return GetContentRoot(mainWindow) as MainPage;
}

public static FrameworkElement? GetContentRoot(this MainWindow mainWindow)
{
return (mainWindow.Content as ContentControl)?.Content as FrameworkElement;
}
}
}
50 changes: 29 additions & 21 deletions src/Files.App/Helpers/Application/AppLifecycleHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,45 +26,51 @@ namespace Files.App.Helpers
/// </summary>
public static class AppLifecycleHelper
{
private static Task OptionalTaskAsync(Task task, bool condition)
{
if (condition)
return task;

return Task.CompletedTask;
}

/// <summary>
/// Initializes the app components.
/// </summary>
public static async Task InitializeAppComponentsAsync()
public static async Task InitializeLateAsync(CancellationToken cancellationToken = default)
{
var userSettingsService = Ioc.Default.GetRequiredService<IUserSettingsService>();
var addItemService = Ioc.Default.GetRequiredService<IAddItemService>();
var generalSettingsService = userSettingsService.GeneralSettingsService;

// Start off a list of tasks we need to run before we can continue startup
await Task.WhenAll(
OptionalTaskAsync(CloudDrivesManager.UpdateDrivesAsync(), generalSettingsService.ShowCloudDrivesSection),
App.LibraryManager.UpdateLibrariesAsync(),
OptionalTaskAsync(WSLDistroManager.UpdateDrivesAsync(), generalSettingsService.ShowWslSection),
OptionalTaskAsync(App.FileTagsManager.UpdateFileTagsAsync(), generalSettingsService.ShowFileTagsSection),
App.QuickAccessManager.InitializeAsync()
);
var networkDrivesViewModel = Ioc.Default.GetRequiredService<NetworkDrivesViewModel>();
var generalSettingsService = Ioc.Default.GetRequiredService<IUserSettingsService>().GeneralSettingsService;

await Task.WhenAll(
JumpListHelper.InitializeUpdatesAsync(),
addItemService.InitializeAsync(),
ContextMenu.WarmUpQueryContextMenuAsync()
ContextMenu.WarmUpQueryContextMenuAsync(),
OptionalTaskAsync(WSLDistroManager.UpdateDrivesAsync(), generalSettingsService.ShowWslSection),
OptionalTaskAsync(App.FileTagsManager.UpdateFileTagsAsync(), generalSettingsService.ShowFileTagsSection),
OptionalTaskAsync(CloudDrivesManager.UpdateDrivesAsync(), generalSettingsService.ShowCloudDrivesSection),
networkDrivesViewModel.UpdateDrivesAsync()
);

FileTagsHelper.UpdateTagsDb();
}

static Task OptionalTaskAsync(Task task, bool condition)
{
if (condition)
return task;
public static async Task InitializeMandatoryAsync(CancellationToken cancellationToken = default)
{
var drivesViewModel = Ioc.Default.GetRequiredService<DrivesViewModel>();

return Task.CompletedTask;
}
await Task.WhenAll(
App.LibraryManager.UpdateLibrariesAsync(),
App.QuickAccessManager.InitAsync(cancellationToken),
drivesViewModel.UpdateDrivesAsync()
);
}

/// <summary>
/// Checks application updates and download if available.
/// </summary>
public static async Task CheckAppUpdate()
public static async Task CheckUpdatesAsync()
{
var updateService = Ioc.Default.GetRequiredService<IUpdateService>();

Expand Down Expand Up @@ -178,7 +184,9 @@ public static IHost ConfigureHost()
/// </summary>
public static void SaveSessionTabs()
{
var userSettingsService = Ioc.Default.GetRequiredService<IUserSettingsService>();
var userSettingsService = Ioc.Default.GetService<IUserSettingsService>();
if (userSettingsService is null)
return;

userSettingsService.GeneralSettingsService.LastSessionTabList = MainPageViewModel.AppInstances.DefaultIfEmpty().Select(tab =>
{
Expand Down
Loading