Skip to content

Commit

Permalink
Implement splash screen manager
Browse files Browse the repository at this point in the history
  • Loading branch information
Drombeys committed Apr 27, 2024
1 parent 556d34b commit ae2868c
Show file tree
Hide file tree
Showing 9 changed files with 117 additions and 49 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using ImeSense.Launchers.Belarus.Models;

namespace ImeSense.Launchers.Belarus.Core.Manager;

public interface ISplashScreenManager
{
CancellationToken CancellationToken { get; }
InformationMessage SplashScreenMessage { get; }
int CurrentProgress { get; set; }
int MaxProgress { get; set; }
void UpdateInformation(InformationMessage splashScreenMessage);
void Cancel();
}
28 changes: 17 additions & 11 deletions src/ImeSense.Launchers.Belarus.Core/Manager/InitializerManager.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System.Collections.ObjectModel;
using System;
using System.Diagnostics;

using ImeSense.Launchers.Belarus.Core.Helpers;
using ImeSense.Launchers.Belarus.Core.Models;
using ImeSense.Launchers.Belarus.Core.Services;
using ImeSense.Launchers.Belarus.Core.Storage;
using ImeSense.Launchers.Belarus.Models;

using Microsoft.Extensions.Logging;

Expand All @@ -30,49 +31,54 @@ public class InitializerManager(
public bool IsGameReleaseCurrent { get; private set; } = true;
public bool IsUserAuthorized { get; private set; }

public async Task InitializeAsync(CancellationToken cancellationToken = default)
public async Task InitializeAsync(ISplashScreenManager splashScreenManager)
{
try {
var stopwatch = new Stopwatch();
stopwatch.Start();
_launcherStorage.IsCheckGitHubConnection = await CheckGitHubConnectionAsync(cancellationToken);

splashScreenManager.UpdateInformation(new InformationMessage(
_localeManager.GetStringByKey("LocalizedStrings.Loading"),
_localeManager.GetStringByKey("LocalizedStrings.AccessingRepository")));

_launcherStorage.IsCheckGitHubConnection = await CheckGitHubConnectionAsync(splashScreenManager.CancellationToken);
_logger.LogInformation("Check GitHub connection time: {Time}", stopwatch.ElapsedMilliseconds);

var locale = _userManager?.UserSettings?.Locale;
if (_launcherStorage.IsCheckGitHubConnection) {
var isLauncherReleaseCurrent = await IsLauncherReleaseCurrentAsync(cancellationToken);
var isLauncherReleaseCurrent = await IsLauncherReleaseCurrentAsync(splashScreenManager.CancellationToken);
_logger.LogInformation("Check launcher update time: {Time}", stopwatch.ElapsedMilliseconds);
if (!isLauncherReleaseCurrent) {
var pathLauncherUpdater = Path.Combine(DirectoryStorage.Base,
FileNameStorage.SBLauncherUpdater);
await _updaterService.UpdaterAsync(UriStorage.LauncherApiUri, pathLauncherUpdater, cancellationToken);
await _updaterService.UpdaterAsync(UriStorage.LauncherApiUri, pathLauncherUpdater, splashScreenManager.CancellationToken);

var updater = Launcher.Launch(pathLauncherUpdater);
updater?.Start();

return;
}

_launcherStorage.GitHubRelease = await _gitStorageApiService.GetLastReleaseAsync(cancellationToken: cancellationToken);
_launcherStorage.GitHubRelease = await _gitStorageApiService.GetLastReleaseAsync(cancellationToken: splashScreenManager.CancellationToken);
_logger.LogInformation("Check last release time: {Time}", stopwatch.ElapsedMilliseconds);

IsGameReleaseCurrent = await IsGameReleaseCurrentAsync(cancellationToken);
IsGameReleaseCurrent = await IsGameReleaseCurrentAsync(splashScreenManager.CancellationToken);
IsUserAuthorized = File.Exists(PathStorage.LauncherSetting);

if (IsUserAuthorized) {
await Task.Factory.StartNew(() => LoadNewsAsync(locale, cancellationToken));
await Task.Factory.StartNew(() => LoadNewsAsync(locale, splashScreenManager.CancellationToken));
} else {
await Task.Factory.StartNew(() => LoadNewsAsync(cancellationToken: cancellationToken));
await Task.Factory.StartNew(() => LoadNewsAsync(cancellationToken: splashScreenManager.CancellationToken));
}
await Task.Factory.StartNew(() => LoadWebResourcesAsync(cancellationToken: cancellationToken));
await Task.Factory.StartNew(() => LoadWebResourcesAsync(cancellationToken: splashScreenManager.CancellationToken));
} else {
if (IsUserAuthorized) {
_launcherStorage.NewsContents = new(LoadErrorNews(locale) ?? []);
} else {
_launcherStorage.NewsContents = new(LoadErrorNews() ?? []);
}

_launcherStorage.GitHubRelease = await FileDataHelper.LoadDataAsync<GitHubRelease>(PathStorage.CurrentRelease, cancellationToken);
_launcherStorage.GitHubRelease = await FileDataHelper.LoadDataAsync<GitHubRelease>(PathStorage.CurrentRelease, splashScreenManager.CancellationToken);
}

stopwatch.Stop();
Expand Down
33 changes: 33 additions & 0 deletions src/ImeSense.Launchers.Belarus.Core/Manager/SplashScreenManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using ImeSense.Launchers.Belarus.Models;

using ReactiveUI;
using ReactiveUI.Fody.Helpers;

namespace ImeSense.Launchers.Belarus.Core.Manager;

public class SplashScreenManager : ReactiveObject, ISplashScreenManager
{
private readonly CancellationTokenSource _cts = new();

public CancellationToken CancellationToken { get; }
[Reactive] public InformationMessage SplashScreenMessage { get; private set; }
[Reactive] public int CurrentProgress { get; set; } = 0;
public int MaxProgress { get; set; }

public SplashScreenManager()
{
CancellationToken = _cts.Token;
SplashScreenMessage = new InformationMessage("Title", "Description");
}

public void Cancel()
{
_cts.Cancel();
}

public void UpdateInformation(InformationMessage splashScreenMessage)
{
CurrentProgress++;
SplashScreenMessage = splashScreenMessage;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
namespace ImeSense.Launchers.Belarus.Models;

public record struct InformationMessage(string Title, string Description);
28 changes: 9 additions & 19 deletions src/ImeSense.Launchers.Belarus/App.axaml.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
using Avalonia;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using ImeSense.Launchers.Belarus.Models;
using ImeSense.Launchers.Belarus.Services;
using ImeSense.Launchers.Belarus.ViewModels;
using ImeSense.Launchers.Belarus.Views;
Expand Down Expand Up @@ -49,7 +48,6 @@ private static ServiceCollection ConfigureServices()
return services;
}


public override void Initialize()
{
var logger = _serviceProvider.GetRequiredService<ILogger<App>>();
Expand All @@ -66,14 +64,14 @@ public override void Initialize()
public override async void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) {
var splashScreenViewModel = _serviceProvider.GetRequiredService<SplashScreenViewModel>();

var initializerManager = _serviceProvider.GetRequiredService<InitializerManager>();
var userManager = _serviceProvider.GetRequiredService<UserManager>();
await userManager.LoadAsync(splashScreenViewModel.CancellationToken);
initializerManager.InitializeLocale();

var localeManager = _serviceProvider.GetRequiredService<IApplicationLocaleManager>();
var splashScreenManager = _serviceProvider.GetRequiredService<ISplashScreenManager>();
splashScreenManager.MaxProgress = 3;

await userManager.LoadAsync(splashScreenManager.CancellationToken);
initializerManager.InitializeLocale();

var mainViewModel = _serviceProvider.GetRequiredService<MainWindowViewModel>();
desktop.MainWindow = new MainWindow {
Expand All @@ -82,18 +80,10 @@ public override async void OnFrameworkInitializationCompleted()
desktop.MainWindow.Show();

try {
mainViewModel.ShowSplashScreenImpl(splashScreenViewModel);
splashScreenViewModel.Progress++;
splashScreenViewModel.InformationMessage = new InformationMessage(
localeManager.GetStringByKey("LocalizedStrings.Loading"),
localeManager.GetStringByKey("LocalizedStrings.AccessingRepository"));
await initializerManager.InitializeAsync(splashScreenViewModel.CancellationToken);
splashScreenViewModel.Progress++;
splashScreenViewModel.InformationMessage = new InformationMessage(
localeManager.GetStringByKey("LocalizedStrings.Loading"),
localeManager.GetStringByKey("LocalizedStrings.DataInitialization"));
await mainViewModel.InitializeAsync(splashScreenViewModel.CancellationToken);
splashScreenViewModel.Progress++;
mainViewModel.ShowSplashScreenImpl();

await initializerManager.InitializeAsync(splashScreenManager);
await mainViewModel.InitializeAsync(splashScreenManager);
} catch (TaskCanceledException) {
desktop.Shutdown();
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public static IServiceCollection AddManagers(this IServiceCollection services)
services.AddSingleton<UserManager>();
services.AddSingleton<InitializerManager>();
services.AddSingleton<IApplicationLocaleManager, AxamlLocaleManager>();
services.AddScoped<ISplashScreenManager, SplashScreenManager>();

return services;
}
Expand Down
3 changes: 0 additions & 3 deletions src/ImeSense.Launchers.Belarus/Models/InformationMessage.cs

This file was deleted.

20 changes: 15 additions & 5 deletions src/ImeSense.Launchers.Belarus/ViewModels/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using ImeSense.Launchers.Belarus.Models;

namespace ImeSense.Launchers.Belarus.ViewModels;

Expand All @@ -20,20 +21,24 @@ public class MainWindowViewModel : ReactiveObject
private readonly IUpdaterService _updaterService;
private readonly InitializerManager _initializerManager;
private readonly ViewModelLocator _viewModelLocator;
private readonly IApplicationLocaleManager _localeManager;
private readonly StartGameViewModel _startGameViewModel;
private readonly LauncherViewModel _launcherViewModel;
private readonly SplashScreenViewModel _splashScreenViewModel;

[Reactive] public ReactiveObject PageViewModel { get; set; } = null!;

public MainWindowViewModel(ILogger<MainWindowViewModel>? logger, InitializerManager initializerManager,
IUpdaterService updaterService, ViewModelLocator viewModelLocator)
IUpdaterService updaterService, ViewModelLocator viewModelLocator, IApplicationLocaleManager localeManager)
{
_logger = logger;
_initializerManager = initializerManager;
_updaterService = updaterService;
_viewModelLocator = viewModelLocator;
_localeManager = localeManager;
_startGameViewModel = viewModelLocator.StartGameViewModel;
_launcherViewModel = viewModelLocator.LauncherViewModel;
_splashScreenViewModel = _viewModelLocator.SplashScreenViewModel;
}

public MainWindowViewModel()
Expand All @@ -45,17 +50,22 @@ public MainWindowViewModel()
_initializerManager = null!;
_updaterService = null!;
_viewModelLocator = null!;
_localeManager = null!;
_splashScreenViewModel = null!;
}

public async Task InitializeAsync(CancellationToken cancellationToken = default)
public async Task InitializeAsync(ISplashScreenManager splashScreenManager)
{
var stopwatch = new Stopwatch();
stopwatch.Start();

splashScreenManager.UpdateInformation(new InformationMessage(
_localeManager.GetStringByKey("LocalizedStrings.Loading"),
_localeManager.GetStringByKey("LocalizedStrings.DataInitialization")));

ProcessHelper.KillAllXrEngine();

var isCurrentRelease = _initializerManager.IsGameReleaseCurrent;

if (File.Exists(PathStorage.LauncherSetting)) {
try {
if (!isCurrentRelease) {
Expand Down Expand Up @@ -94,8 +104,8 @@ public void ShowStartGameImpl()
PageViewModel = _startGameViewModel;
}

public void ShowSplashScreenImpl(SplashScreenViewModel splash)
public void ShowSplashScreenImpl()
{
PageViewModel = splash;
PageViewModel = _splashScreenViewModel;
}
}
37 changes: 26 additions & 11 deletions src/ImeSense.Launchers.Belarus/ViewModels/SplashScreenViewModel.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Reactive;

using ImeSense.Launchers.Belarus.Core.Manager;
using ImeSense.Launchers.Belarus.Helpers;
using ImeSense.Launchers.Belarus.Models;

using ReactiveUI;
Expand All @@ -10,30 +11,44 @@ namespace ImeSense.Launchers.Belarus.ViewModels;

public class SplashScreenViewModel : ReactiveObject
{
private readonly CancellationTokenSource _cts = new();
public CancellationToken CancellationToken => _cts.Token;

private readonly IWindowManager _windowManager;
public ReactiveCommand<Unit, Unit> Cancel { get; set; } = null!;
[Reactive] public InformationMessage? InformationMessage { get; set; }
[Reactive] public int Progress { get; set; } = 0;
[Reactive] public int MaxProgress { get; set; } = 3;
ISplashScreenManager SplashScreen { get; set; }

[Reactive] public InformationMessage InformationMessage { get; set; }
[Reactive] public int Progress { get; set; }
public int MaxProgress { get; private set; }

public ReactiveCommand<Unit, Unit> Cancel { get; set; } = null!;

public SplashScreenViewModel()
{
ExceptionHelper.ThrowIfEmptyConstructorNotInDesignTime($"{nameof(StartGameViewModel)}");

_windowManager = null!;
SplashScreen = null!;
}

public SplashScreenViewModel(IWindowManager windowManager) : base()
public SplashScreenViewModel(IWindowManager windowManager, ISplashScreenManager splashScreen)
{
InformationMessage = new InformationMessage("Title", "Description");
Cancel = ReactiveCommand.Create(CancelImpl);
_windowManager = windowManager;
SplashScreen = splashScreen;
Progress = SplashScreen.CurrentProgress;
MaxProgress = SplashScreen.MaxProgress;

this.WhenAnyValue(
x => x.SplashScreen.CurrentProgress,
x => x.SplashScreen.SplashScreenMessage)
.Subscribe(u => {
Progress = u.Item1;
InformationMessage = u.Item2;
});

Cancel = ReactiveCommand.Create(CancelImpl);
}

private void CancelImpl()
{
_cts.Cancel();
SplashScreen.Cancel();
_windowManager.Close();
}
}

0 comments on commit ae2868c

Please sign in to comment.