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

Feature: Added a splash screen #12979

Merged
merged 10 commits into from
Jul 20, 2023
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
154 changes: 82 additions & 72 deletions src/Files.App/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,69 +95,65 @@ private IHost ConfigureHost()
{
return Host.CreateDefaultBuilder()
.UseEnvironment(ApplicationService.AppEnvironment.ToString())
.ConfigureLogging(builder =>
builder
.ConfigureLogging(builder => builder
.AddProvider(new FileLoggerProvider(Path.Combine(ApplicationData.Current.LocalFolder.Path, "debug.log")))
.SetMinimumLevel(LogLevel.Information)
)
.ConfigureServices(services =>
services
.AddSingleton<IUserSettingsService, UserSettingsService>()
.AddSingleton<IAppearanceSettingsService, AppearanceSettingsService>(sp => new AppearanceSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<IGeneralSettingsService, GeneralSettingsService>(sp => new GeneralSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<IFoldersSettingsService, FoldersSettingsService>(sp => new FoldersSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<IApplicationSettingsService, ApplicationSettingsService>(sp => new ApplicationSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<IPreviewPaneSettingsService, PreviewPaneSettingsService>(sp => new PreviewPaneSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<ILayoutSettingsService, LayoutSettingsService>(sp => new LayoutSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<IAppSettingsService, AppSettingsService>(sp => new AppSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<IFileTagsSettingsService, FileTagsSettingsService>()
.AddSingleton<IPageContext, PageContext>()
.AddSingleton<IContentPageContext, ContentPageContext>()
.AddSingleton<IDisplayPageContext, DisplayPageContext>()
.AddSingleton<IWindowContext, WindowContext>()
.AddSingleton<IMultitaskingContext, MultitaskingContext>()
.AddSingleton<ITagsContext, TagsContext>()
.AddSingleton<IDialogService, DialogService>()
.AddSingleton<IImageService, ImagingService>()
.AddSingleton<IThreadingService, ThreadingService>()
.AddSingleton<ILocalizationService, LocalizationService>()
.AddSingleton<ICloudDetector, CloudDetector>()
.AddSingleton<IFileTagsService, FileTagsService>()
.AddSingleton<ICommandManager, CommandManager>()
.AddSingleton<IModifiableCommandManager, ModifiableCommandManager>()
.AddSingleton<IApplicationService, ApplicationService>()
.SetMinimumLevel(LogLevel.Information))
.ConfigureServices(services => services
.AddSingleton<IUserSettingsService, UserSettingsService>()
.AddSingleton<IAppearanceSettingsService, AppearanceSettingsService>(sp => new AppearanceSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<IGeneralSettingsService, GeneralSettingsService>(sp => new GeneralSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<IFoldersSettingsService, FoldersSettingsService>(sp => new FoldersSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<IApplicationSettingsService, ApplicationSettingsService>(sp => new ApplicationSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<IPreviewPaneSettingsService, PreviewPaneSettingsService>(sp => new PreviewPaneSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<ILayoutSettingsService, LayoutSettingsService>(sp => new LayoutSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<IAppSettingsService, AppSettingsService>(sp => new AppSettingsService((sp.GetService<IUserSettingsService>() as UserSettingsService).GetSharingContext()))
.AddSingleton<IFileTagsSettingsService, FileTagsSettingsService>()
.AddSingleton<IPageContext, PageContext>()
.AddSingleton<IContentPageContext, ContentPageContext>()
.AddSingleton<IDisplayPageContext, DisplayPageContext>()
.AddSingleton<IWindowContext, WindowContext>()
.AddSingleton<IMultitaskingContext, MultitaskingContext>()
.AddSingleton<ITagsContext, TagsContext>()
.AddSingleton<IDialogService, DialogService>()
.AddSingleton<IImageService, ImagingService>()
.AddSingleton<IThreadingService, ThreadingService>()
.AddSingleton<ILocalizationService, LocalizationService>()
.AddSingleton<ICloudDetector, CloudDetector>()
.AddSingleton<IFileTagsService, FileTagsService>()
.AddSingleton<ICommandManager, CommandManager>()
.AddSingleton<IModifiableCommandManager, ModifiableCommandManager>()
.AddSingleton<IApplicationService, ApplicationService>()
#if UWP
.AddSingleton<IStorageService, WindowsStorageService>()
.AddSingleton<IStorageService, WindowsStorageService>()
#else
.AddSingleton<IStorageService, NativeStorageService>()
.AddSingleton<IStorageService, NativeStorageService>()
#endif
.AddSingleton<IFtpStorageService, FtpStorageService>()
.AddSingleton<IAddItemService, AddItemService>()
.AddSingleton<IFtpStorageService, FtpStorageService>()
.AddSingleton<IAddItemService, AddItemService>()
#if STABLE || PREVIEW
.AddSingleton<IUpdateService, SideloadUpdateService>()
.AddSingleton<IUpdateService, SideloadUpdateService>()
#else
.AddSingleton<IUpdateService, UpdateService>()
.AddSingleton<IUpdateService, UpdateService>()
#endif
.AddSingleton<IPreviewPopupService, PreviewPopupService>()
.AddSingleton<IDateTimeFormatterFactory, DateTimeFormatterFactory>()
.AddSingleton<IDateTimeFormatter, UserDateTimeFormatter>()
.AddSingleton<IVolumeInfoFactory, VolumeInfoFactory>()
.AddSingleton<ISizeProvider, UserSizeProvider>()
.AddSingleton<IQuickAccessService, QuickAccessService>()
.AddSingleton<IResourcesService, ResourcesService>()
.AddSingleton<IJumpListService, JumpListService>()
.AddSingleton<IRemovableDrivesService, RemovableDrivesService>()
.AddSingleton<INetworkDrivesService, NetworkDrivesService>()
.AddSingleton<MainPageViewModel>()
.AddSingleton<PreviewPaneViewModel>()
.AddSingleton<SidebarViewModel>()
.AddSingleton<SettingsViewModel>()
.AddSingleton<DrivesViewModel>()
.AddSingleton<NetworkDrivesViewModel>()
.AddSingleton<OngoingTasksViewModel>()
.AddSingleton<AppearanceViewModel>()
)
.Build();
.AddSingleton<IPreviewPopupService, PreviewPopupService>()
.AddSingleton<IDateTimeFormatterFactory, DateTimeFormatterFactory>()
.AddSingleton<IDateTimeFormatter, UserDateTimeFormatter>()
.AddSingleton<IVolumeInfoFactory, VolumeInfoFactory>()
.AddSingleton<ISizeProvider, UserSizeProvider>()
.AddSingleton<IQuickAccessService, QuickAccessService>()
.AddSingleton<IResourcesService, ResourcesService>()
.AddSingleton<IJumpListService, JumpListService>()
.AddSingleton<IRemovableDrivesService, RemovableDrivesService>()
.AddSingleton<INetworkDrivesService, NetworkDrivesService>()
.AddSingleton<MainPageViewModel>()
.AddSingleton<PreviewPaneViewModel>()
.AddSingleton<SidebarViewModel>()
.AddSingleton<SettingsViewModel>()
.AddSingleton<DrivesViewModel>()
.AddSingleton<NetworkDrivesViewModel>()
.AddSingleton<OngoingTasksViewModel>()
.AddSingleton<AppearanceViewModel>()
).Build();
}

private static async Task InitializeAppComponentsAsync()
Expand Down Expand Up @@ -207,28 +203,42 @@ static async Task OptionalTask(Task task, bool condition)
/// <param name="e">Details about the launch request and process.</param>
protected override void OnLaunched(LaunchActivatedEventArgs e)
{
// Get AppActivationArguments
var appActivationArguments = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();
_ = ActivateAsync();

// Start tracking app usage
if (appActivationArguments.Data is Windows.ApplicationModel.Activation.IActivatedEventArgs activationEventArgs)
SystemInformation.Instance.TrackAppUse(activationEventArgs);
async Task ActivateAsync()
{
// Initialize and activate MainWindow
EnsureSuperEarlyWindow();

// Wait for the Window to initialize
await Task.Delay(10);

MainWindow.Instance.ShowSplashScreen();

// Wait for the UI to update
await Task.Delay(500);

// Configure Host and IoC
_host = ConfigureHost();
Ioc.Default.ConfigureServices(_host.Services);
// Get AppActivationArguments
var appActivationArguments = Microsoft.Windows.AppLifecycle.AppInstance.GetCurrent().GetActivatedEventArgs();

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

// Initialize and activate MainWindow
EnsureSuperEarlyWindow();
// Configure Host and IoC
_host = ConfigureHost();
Ioc.Default.ConfigureServices(_host.Services);

// TODO(s)
Logger = Ioc.Default.GetRequiredService<ILogger<App>>();
Logger.LogInformation($"App launched. Launch args type: {appActivationArguments.Data.GetType().Name}");
EnsureSettingsAndConfigurationAreBootstrapped();

_ = InitializeAppComponentsAsync().ContinueWith(t => Logger.LogWarning(t.Exception, "Error during InitializeAppComponentsAsync()"), TaskContinuationOptions.OnlyOnFaulted);
_ = MainWindow.Instance.InitializeApplication(appActivationArguments.Data);
// TODO: Remove App.Logger instance and replace with DI
Logger = Ioc.Default.GetRequiredService<ILogger<App>>();
Logger.LogInformation($"App launched. Launch args type: {appActivationArguments.Data.GetType().Name}");

_ = InitializeAppComponentsAsync().ContinueWith(t => Logger.LogWarning(t.Exception, "Error during InitializeAppComponentsAsync()"), TaskContinuationOptions.OnlyOnFaulted);

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

private static void EnsureSettingsAndConfigurationAreBootstrapped()
Expand Down
1 change: 1 addition & 0 deletions src/Files.App/GlobalUsings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
global using global::Files.App.Data.Models;
global using global::Files.App.Data.Parameters;
global using global::Files.App.Data.TemplateSelectors;
global using global::Files.App.Services;
global using global::Files.App.UserControls;
global using global::Files.App.ViewModels;
global using global::Files.App.ViewModels.UserControls;
Expand Down
52 changes: 26 additions & 26 deletions src/Files.App/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
// Licensed under the MIT License. See the LICENSE.

using Files.App.UserControls.MultitaskingControl;
using Files.Core.Utils.CommandLine;
using Microsoft.UI;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml.Controls;
Expand All @@ -19,20 +18,23 @@ namespace Files.App
{
public sealed partial class MainWindow : WindowEx
{
private readonly IApplicationService ApplicationService;

private MainPageViewModel mainPageViewModel;

private static MainWindow? _Instance;
public static MainWindow Instance => _Instance ??= new();

public IntPtr WindowHandle { get; }

private MainPageViewModel mainPageViewModel;

private IApplicationService ApplicationService { get; } = Ioc.Default.GetRequiredService<IApplicationService>();

private MainWindow()
{
ApplicationService = new ApplicationService();
yaira2 marked this conversation as resolved.
Show resolved Hide resolved

WindowHandle = this.GetWindowHandle();

InitializeComponent();

EnsureEarlyWindow();
}

Expand All @@ -41,30 +43,32 @@ private void EnsureEarlyWindow()
// Set PersistenceId
PersistenceId = "FilesMainWindow";

// Set title
AppWindow.Title = "Files";
// Set minimum sizes
MinHeight = 416;
MinWidth = 516;

// Set logo
AppWindow.Title = "Files";
AppWindow.SetIcon(Path.Combine(Package.Current.InstalledLocation.Path, ApplicationService.AppIcoPath));

// Extend title bar
AppWindow.TitleBar.ExtendsContentIntoTitleBar = true;

// Set window buttons background to transparent
AppWindow.TitleBar.ButtonBackgroundColor = Colors.Transparent;
AppWindow.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
}

// Set minimum sizes
base.MinHeight = 328;
base.MinWidth = 516;
public void ShowSplashScreen()
{
var rootFrame = EnsureWindowIsInitialized();

rootFrame.Navigate(typeof(SplashScreenPage));
}

public async Task InitializeApplication(object activatedEventArgs)
{
// Set system backdrop
SystemBackdrop = new AppSystemBackdrop();

mainPageViewModel = Ioc.Default.GetRequiredService<MainPageViewModel>();

var rootFrame = EnsureWindowIsInitialized();
Activate();

switch (activatedEventArgs)
{
Expand All @@ -78,7 +82,7 @@ public async Task InitializeApplication(object activatedEventArgs)
else
await InitializeFromCmdLineArgs(rootFrame, ppm);
}
else if (rootFrame.Content is null)
else if (rootFrame.Content is null || rootFrame.Content as SplashScreenPage is not null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation parameter
Expand Down Expand Up @@ -147,7 +151,7 @@ public async Task InitializeApplication(object activatedEventArgs)

case IFileActivatedEventArgs fileArgs:
var index = 0;
if (rootFrame.Content is null)
if (rootFrame.Content is null || rootFrame.Content as SplashScreenPage is not null)
{
// When the navigation stack isn't restored navigate to the first page,
// configuring the new page by passing required information as a navigation parameter
Expand All @@ -161,7 +165,7 @@ public async Task InitializeApplication(object activatedEventArgs)
break;
}

if (rootFrame.Content is null)
if (rootFrame.Content is null || rootFrame.Content as SplashScreenPage is not null)
rootFrame.Navigate(typeof(MainPage), null, new SuppressNavigationTransitionInfo());
}

Expand All @@ -170,18 +174,14 @@ private Frame EnsureWindowIsInitialized()
// NOTE:
// Do not repeat app initialization when the Window already has content,
// just ensure that the window is active
if (!(MainWindow.Instance.Content is Frame rootFrame))
if (Instance.Content is not Frame rootFrame)
{
// Set system backdrop
this.SystemBackdrop = new AppSystemBackdrop();

// Create a Frame to act as the navigation context and navigate to the first page
rootFrame = new Frame();
rootFrame.CacheSize = 1;
rootFrame = new() { CacheSize = 1 };
rootFrame.NavigationFailed += OnNavigationFailed;

// Place the frame in the current Window
MainWindow.Instance.Content = rootFrame;
Instance.Content = rootFrame;
}

return rootFrame;
Expand Down
37 changes: 37 additions & 0 deletions src/Files.App/Views/SplashScreenPage.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<!-- Copyright (c) 2023 Files Community. Licensed under the MIT License. See the LICENSE. -->
<Page
x:Class="Files.App.Views.SplashScreenPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">

<Grid>
<Image
x:Name="MainSplashScreenImage"
Width="420"
Source="\Assets\AppTiles\Dev\SplashScreen.png" />

<ProgressRing
x:Name="MainProgressRing"
Margin="0,0,0,88"
VerticalAlignment="Bottom"
Foreground="{ThemeResource ApplicationForegroundThemeBrush}"
IsIndeterminate="True" />

<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SizeChangesState">
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="640" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="MainSplashScreenImage.Width" Value="480" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</Page>
18 changes: 18 additions & 0 deletions src/Files.App/Views/SplashScreenPage.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// Copyright (c) 2023 Files Community
// Licensed under the MIT License. See the LICENSE.

using Microsoft.UI.Xaml.Controls;

namespace Files.App.Views
{
/// <summary>
/// Display the app splash screen.
/// </summary>
public sealed partial class SplashScreenPage : Page
{
public SplashScreenPage()
{
InitializeComponent();
}
}
}