Ava UI: Refactor async usage (#5516)

* Remove `async void`

* Async LoadApplications

* Formatting and such

* Remove async from InstallUpdate

* Update src/Ryujinx.Ava/UI/Controls/ApplicationContextMenu.axaml.cs

Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>

* Cleanup LoadApplications()

* Cleanup

* Formatting

* Revert some stuff

* Cleanup

* Update src/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs

Co-authored-by: Ac_K <Acoustik666@gmail.com>

* Ack suggestions

* Whitespace

* Fix Peri suggestion

* Add missing trailing commas

* Remove redundant method override

* Remove Dispatcher.UIThread.InvokeAsync/Post where possible

---------

Co-authored-by: TSR Berry <20988865+TSRBerry@users.noreply.github.com>
Co-authored-by: Ac_K <Acoustik666@gmail.com>
This commit is contained in:
Isaac Marovitz 2023-09-25 18:04:58 -04:00 committed by GitHub
parent 53bd4c9f60
commit d6d3cdd573
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 230 additions and 303 deletions

View file

@ -104,7 +104,7 @@ namespace Ryujinx.Ava
{ {
"Light" => ThemeVariant.Light, "Light" => ThemeVariant.Light,
"Dark" => ThemeVariant.Dark, "Dark" => ThemeVariant.Dark,
_ => ThemeVariant.Default _ => ThemeVariant.Default,
}; };
if (enableCustomTheme) if (enableCustomTheme)

View file

@ -3,7 +3,6 @@ using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Rendering;
using Avalonia.Threading; using Avalonia.Threading;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.Dummy; using Ryujinx.Audio.Backends.Dummy;

View file

@ -145,7 +145,7 @@ namespace Ryujinx.Ava.Common
var result = await storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions var result = await storageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{ {
Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle], Title = LocaleManager.Instance[LocaleKeys.FolderDialogExtractTitle],
AllowMultiple = false AllowMultiple = false,
}); });
if (result.Count == 0) if (result.Count == 0)

View file

@ -1,6 +1,5 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Input; using Ryujinx.Input;
using System; using System;

View file

@ -82,12 +82,9 @@ namespace Ryujinx.Modules
{ {
Logger.Error?.Print(LogClass.Application, "Failed to convert the current Ryujinx version!"); Logger.Error?.Print(LogClass.Application, "Failed to convert the current Ryujinx version!");
Dispatcher.UIThread.Post(async () => await ContentDialogHelper.CreateWarningDialog(
{ LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedMessage],
await ContentDialogHelper.CreateWarningDialog( LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]);
LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedMessage],
LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]);
});
_running = false; _running = false;
@ -114,10 +111,9 @@ namespace Ryujinx.Modules
{ {
if (showVersionUpToDate) if (showVersionUpToDate)
{ {
Dispatcher.UIThread.Post(async () => await ContentDialogHelper.CreateUpdaterInfoDialog(
{ LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage],
await ContentDialogHelper.CreateUpdaterInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage], ""); "");
});
} }
_running = false; _running = false;
@ -134,10 +130,9 @@ namespace Ryujinx.Modules
{ {
if (showVersionUpToDate) if (showVersionUpToDate)
{ {
Dispatcher.UIThread.Post(async () => await ContentDialogHelper.CreateUpdaterInfoDialog(
{ LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage],
await ContentDialogHelper.CreateUpdaterInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage], ""); "");
});
} }
_running = false; _running = false;
@ -149,10 +144,8 @@ namespace Ryujinx.Modules
{ {
Logger.Error?.Print(LogClass.Application, exception.Message); Logger.Error?.Print(LogClass.Application, exception.Message);
Dispatcher.UIThread.Post(async () => await ContentDialogHelper.CreateErrorDialog(
{ LocaleManager.Instance[LocaleKeys.DialogUpdaterFailedToGetVersionMessage]);
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterFailedToGetVersionMessage]);
});
_running = false; _running = false;
@ -167,12 +160,9 @@ namespace Ryujinx.Modules
{ {
Logger.Error?.Print(LogClass.Application, "Failed to convert the received Ryujinx version from Github!"); Logger.Error?.Print(LogClass.Application, "Failed to convert the received Ryujinx version from Github!");
Dispatcher.UIThread.Post(async () => await ContentDialogHelper.CreateWarningDialog(
{ LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage],
await ContentDialogHelper.CreateWarningDialog( LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]);
LocaleManager.Instance[LocaleKeys.DialogUpdaterConvertFailedGithubMessage],
LocaleManager.Instance[LocaleKeys.DialogUpdaterCancelUpdateMessage]);
});
_running = false; _running = false;
@ -183,10 +173,9 @@ namespace Ryujinx.Modules
{ {
if (showVersionUpToDate) if (showVersionUpToDate)
{ {
Dispatcher.UIThread.Post(async () => await ContentDialogHelper.CreateUpdaterInfoDialog(
{ LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage],
await ContentDialogHelper.CreateUpdaterInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUpdaterAlreadyOnLatestVersionMessage], ""); "");
});
} }
_running = false; _running = false;
@ -212,7 +201,7 @@ namespace Ryujinx.Modules
_buildSize = -1; _buildSize = -1;
} }
Dispatcher.UIThread.Post(async () => await Dispatcher.UIThread.InvokeAsync(async () =>
{ {
// Show a message asking the user if they want to update // Show a message asking the user if they want to update
var shouldUpdate = await ContentDialogHelper.CreateChoiceDialog( var shouldUpdate = await ContentDialogHelper.CreateChoiceDialog(
@ -222,7 +211,7 @@ namespace Ryujinx.Modules
if (shouldUpdate) if (shouldUpdate)
{ {
UpdateRyujinx(mainWindow, _buildUrl); await UpdateRyujinx(mainWindow, _buildUrl);
} }
else else
{ {
@ -241,7 +230,7 @@ namespace Ryujinx.Modules
return result; return result;
} }
private static async void UpdateRyujinx(Window parent, string downloadUrl) private static async Task UpdateRyujinx(Window parent, string downloadUrl)
{ {
_updateSuccessful = false; _updateSuccessful = false;
@ -579,27 +568,24 @@ namespace Ryujinx.Modules
} }
} }
private static async void InstallUpdate(TaskDialog taskDialog, string updateFile) private static void InstallUpdate(TaskDialog taskDialog, string updateFile)
{ {
// Extract Update // Extract Update
taskDialog.SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterExtracting]; taskDialog.SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterExtracting];
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal); taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
await Task.Run(() => if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS())
{ {
if (OperatingSystem.IsLinux() || OperatingSystem.IsMacOS()) ExtractTarGzipFile(taskDialog, updateFile, _updateDir);
{ }
ExtractTarGzipFile(taskDialog, updateFile, _updateDir); else if (OperatingSystem.IsWindows())
} {
else if (OperatingSystem.IsWindows()) ExtractZipFile(taskDialog, updateFile, _updateDir);
{ }
ExtractZipFile(taskDialog, updateFile, _updateDir); else
} {
else throw new NotSupportedException();
{ }
throw new NotSupportedException();
}
});
// Delete downloaded zip // Delete downloaded zip
File.Delete(updateFile); File.Delete(updateFile);
@ -613,36 +599,33 @@ namespace Ryujinx.Modules
if (!OperatingSystem.IsMacOS()) if (!OperatingSystem.IsMacOS())
{ {
// Replace old files // Replace old files
await Task.Run(() => double count = 0;
foreach (string file in allFiles)
{ {
double count = 0; count++;
foreach (string file in allFiles) try
{ {
count++; File.Move(file, file + ".ryuold");
try
{
File.Move(file, file + ".ryuold");
Dispatcher.UIThread.Post(() => Dispatcher.UIThread.InvokeAsync(() =>
{
taskDialog.SetProgressBarState(GetPercentage(count, allFiles.Count), TaskDialogProgressState.Normal);
});
}
catch
{ {
Logger.Warning?.Print(LogClass.Application, LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.UpdaterRenameFailed, file)); taskDialog.SetProgressBarState(GetPercentage(count, allFiles.Count), TaskDialogProgressState.Normal);
} });
} }
catch
Dispatcher.UIThread.Post(() =>
{ {
taskDialog.SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterAddingFiles]; Logger.Warning?.Print(LogClass.Application, LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.UpdaterRenameFailed, file));
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal); }
}); }
MoveAllFilesOver(_updatePublishDir, _homeDir, taskDialog); Dispatcher.UIThread.InvokeAsync(() =>
{
taskDialog.SubHeader = LocaleManager.Instance[LocaleKeys.UpdaterAddingFiles];
taskDialog.SetProgressBarState(0, TaskDialogProgressState.Normal);
}); });
MoveAllFilesOver(_updatePublishDir, _homeDir, taskDialog);
Directory.Delete(_updateDir, true); Directory.Delete(_updateDir, true);
} }
@ -658,12 +641,11 @@ namespace Ryujinx.Modules
{ {
if (showWarnings) if (showWarnings)
{ {
Dispatcher.UIThread.Post(async () => Dispatcher.UIThread.InvokeAsync(() =>
{ ContentDialogHelper.CreateWarningDialog(
await ContentDialogHelper.CreateWarningDialog(
LocaleManager.Instance[LocaleKeys.DialogUpdaterArchNotSupportedMessage], LocaleManager.Instance[LocaleKeys.DialogUpdaterArchNotSupportedMessage],
LocaleManager.Instance[LocaleKeys.DialogUpdaterArchNotSupportedSubMessage]); LocaleManager.Instance[LocaleKeys.DialogUpdaterArchNotSupportedSubMessage])
}); );
} }
return false; return false;
@ -673,12 +655,11 @@ namespace Ryujinx.Modules
{ {
if (showWarnings) if (showWarnings)
{ {
Dispatcher.UIThread.Post(async () => Dispatcher.UIThread.InvokeAsync(() =>
{ ContentDialogHelper.CreateWarningDialog(
await ContentDialogHelper.CreateWarningDialog(
LocaleManager.Instance[LocaleKeys.DialogUpdaterNoInternetMessage], LocaleManager.Instance[LocaleKeys.DialogUpdaterNoInternetMessage],
LocaleManager.Instance[LocaleKeys.DialogUpdaterNoInternetSubMessage]); LocaleManager.Instance[LocaleKeys.DialogUpdaterNoInternetSubMessage])
}); );
} }
return false; return false;
@ -688,12 +669,11 @@ namespace Ryujinx.Modules
{ {
if (showWarnings) if (showWarnings)
{ {
Dispatcher.UIThread.Post(async () => Dispatcher.UIThread.InvokeAsync(() =>
{ ContentDialogHelper.CreateWarningDialog(
await ContentDialogHelper.CreateWarningDialog(
LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildMessage], LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildMessage],
LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage]); LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage])
}); );
} }
return false; return false;
@ -705,21 +685,19 @@ namespace Ryujinx.Modules
{ {
if (ReleaseInformation.IsFlatHubBuild()) if (ReleaseInformation.IsFlatHubBuild())
{ {
Dispatcher.UIThread.Post(async () => Dispatcher.UIThread.InvokeAsync(() =>
{ ContentDialogHelper.CreateWarningDialog(
await ContentDialogHelper.CreateWarningDialog(
LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle], LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle],
LocaleManager.Instance[LocaleKeys.DialogUpdaterFlatpakNotSupportedMessage]); LocaleManager.Instance[LocaleKeys.DialogUpdaterFlatpakNotSupportedMessage])
}); );
} }
else else
{ {
Dispatcher.UIThread.Post(async () => Dispatcher.UIThread.InvokeAsync(() =>
{ ContentDialogHelper.CreateWarningDialog(
await ContentDialogHelper.CreateWarningDialog(
LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle], LocaleManager.Instance[LocaleKeys.UpdaterDisabledWarningTitle],
LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage]); LocaleManager.Instance[LocaleKeys.DialogUpdaterDirtyBuildSubMessage])
}); );
} }
} }

View file

@ -106,7 +106,7 @@ namespace Ryujinx.Ava.UI.Applet
bool error = false; bool error = false;
string inputText = args.InitialText ?? ""; string inputText = args.InitialText ?? "";
Dispatcher.UIThread.Post(async () => Dispatcher.UIThread.InvokeAsync(async () =>
{ {
try try
{ {
@ -149,7 +149,7 @@ namespace Ryujinx.Ava.UI.Applet
bool showDetails = false; bool showDetails = false;
Dispatcher.UIThread.Post(async () => Dispatcher.UIThread.InvokeAsync(async () =>
{ {
try try
{ {

View file

@ -54,7 +54,7 @@ namespace Ryujinx.Ava.UI.Controls
{ {
if (sender is MenuItem { DataContext: MainWindowViewModel viewModel }) if (sender is MenuItem { DataContext: MainWindowViewModel viewModel })
{ {
OpenSaveDirectory(viewModel, SaveDataType.Account, userId: new UserId((ulong)viewModel.AccountManager.LastOpenedUser.UserId.High, (ulong)viewModel.AccountManager.LastOpenedUser.UserId.Low)); OpenSaveDirectory(viewModel, SaveDataType.Account, new UserId((ulong)viewModel.AccountManager.LastOpenedUser.UserId.High, (ulong)viewModel.AccountManager.LastOpenedUser.UserId.Low));
} }
} }
@ -62,14 +62,14 @@ namespace Ryujinx.Ava.UI.Controls
{ {
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel; var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
OpenSaveDirectory(viewModel, SaveDataType.Device, userId: default); OpenSaveDirectory(viewModel, SaveDataType.Device, default);
} }
public void OpenBcatSaveDirectory_Click(object sender, RoutedEventArgs args) public void OpenBcatSaveDirectory_Click(object sender, RoutedEventArgs args)
{ {
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel; var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
OpenSaveDirectory(viewModel, SaveDataType.Bcat, userId: default); OpenSaveDirectory(viewModel, SaveDataType.Bcat, default);
} }
private static void OpenSaveDirectory(MainWindowViewModel viewModel, SaveDataType saveDataType, UserId userId) private static void OpenSaveDirectory(MainWindowViewModel viewModel, SaveDataType saveDataType, UserId userId)
@ -158,11 +158,12 @@ namespace Ryujinx.Ava.UI.Controls
if (viewModel?.SelectedApplication != null) if (viewModel?.SelectedApplication != null)
{ {
UserResult result = await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance[LocaleKeys.DialogWarning], UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionMessage, viewModel.SelectedApplication.TitleName), LocaleManager.Instance[LocaleKeys.DialogWarning],
LocaleManager.Instance[LocaleKeys.InputDialogYes], LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogPPTCDeletionMessage, viewModel.SelectedApplication.TitleName),
LocaleManager.Instance[LocaleKeys.InputDialogNo], LocaleManager.Instance[LocaleKeys.InputDialogYes],
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); LocaleManager.Instance[LocaleKeys.InputDialogNo],
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
if (result == UserResult.Yes) if (result == UserResult.Yes)
{ {
@ -205,11 +206,12 @@ namespace Ryujinx.Ava.UI.Controls
if (viewModel?.SelectedApplication != null) if (viewModel?.SelectedApplication != null)
{ {
UserResult result = await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance[LocaleKeys.DialogWarning], UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogShaderDeletionMessage, viewModel.SelectedApplication.TitleName), LocaleManager.Instance[LocaleKeys.DialogWarning],
LocaleManager.Instance[LocaleKeys.InputDialogYes], LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogShaderDeletionMessage, viewModel.SelectedApplication.TitleName),
LocaleManager.Instance[LocaleKeys.InputDialogNo], LocaleManager.Instance[LocaleKeys.InputDialogYes],
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); LocaleManager.Instance[LocaleKeys.InputDialogNo],
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
if (result == UserResult.Yes) if (result == UserResult.Yes)
{ {
@ -335,13 +337,13 @@ namespace Ryujinx.Ava.UI.Controls
} }
} }
public void RunApplication_Click(object sender, RoutedEventArgs args) public async void RunApplication_Click(object sender, RoutedEventArgs args)
{ {
var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel; var viewModel = (sender as MenuItem)?.DataContext as MainWindowViewModel;
if (viewModel?.SelectedApplication != null) if (viewModel?.SelectedApplication != null)
{ {
viewModel.LoadApplication(viewModel.SelectedApplication.Path); await viewModel.LoadApplication(viewModel.SelectedApplication.Path);
} }
} }
} }

View file

@ -212,9 +212,9 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
Patterns = new[] { "*.nsp" }, Patterns = new[] { "*.nsp" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" }, AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" },
MimeTypes = new[] { "application/x-nx-nsp" } MimeTypes = new[] { "application/x-nx-nsp" },
} },
} },
}); });
foreach (var file in result) foreach (var file in result)

View file

@ -26,6 +26,7 @@ using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Account.Acc;
using Ryujinx.HLE.Ui; using Ryujinx.HLE.Ui;
using Ryujinx.Input.HLE;
using Ryujinx.Modules; using Ryujinx.Modules;
using Ryujinx.Ui.App.Common; using Ryujinx.Ui.App.Common;
using Ryujinx.Ui.Common; using Ryujinx.Ui.Common;
@ -39,7 +40,6 @@ using System.IO;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Image = SixLabors.ImageSharp.Image; using Image = SixLabors.ImageSharp.Image;
using InputManager = Ryujinx.Input.HLE.InputManager;
using Key = Ryujinx.Input.Key; using Key = Ryujinx.Input.Key;
using MissingKeyException = LibHac.Common.Keys.MissingKeyException; using MissingKeyException = LibHac.Common.Keys.MissingKeyException;
using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState; using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState;
@ -1068,9 +1068,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
Logger.Error?.Print(LogClass.Application, ex.ToString()); Logger.Error?.Print(LogClass.Application, ex.ToString());
static async void Action() => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys); await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys);
Dispatcher.UIThread.Post(Action);
} }
} }
catch (Exception ex) catch (Exception ex)
@ -1163,16 +1161,13 @@ namespace Ryujinx.Ava.UI.ViewModels
AppHost?.DisposeContext(); AppHost?.DisposeContext();
} }
private void HandleRelaunch() private async Task HandleRelaunch()
{ {
if (UserChannelPersistence.PreviousIndex != -1 && UserChannelPersistence.ShouldRestart) if (UserChannelPersistence.PreviousIndex != -1 && UserChannelPersistence.ShouldRestart)
{ {
UserChannelPersistence.ShouldRestart = false; UserChannelPersistence.ShouldRestart = false;
Dispatcher.UIThread.Post(() => await LoadApplication(_currentEmulatedGamePath);
{
LoadApplication(_currentEmulatedGamePath);
});
} }
else else
{ {
@ -1191,7 +1186,7 @@ namespace Ryujinx.Ava.UI.ViewModels
Application.Current.Styles.TryGetResource(args.VSyncEnabled Application.Current.Styles.TryGetResource(args.VSyncEnabled
? "VsyncEnabled" ? "VsyncEnabled"
: "VsyncDisabled", : "VsyncDisabled",
Avalonia.Application.Current.ActualThemeVariant, Application.Current.ActualThemeVariant,
out object color); out object color);
if (color is not null) if (color is not null)
@ -1283,7 +1278,7 @@ namespace Ryujinx.Ava.UI.ViewModels
Glyph = Glyph.Grid; Glyph = Glyph.Grid;
} }
public async void InstallFirmwareFromFile() public async Task InstallFirmwareFromFile()
{ {
var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{ {
@ -1294,21 +1289,21 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
Patterns = new[] { "*.xci", "*.zip" }, Patterns = new[] { "*.xci", "*.zip" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci", "public.zip-archive" }, AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci", "public.zip-archive" },
MimeTypes = new[] { "application/x-nx-xci", "application/zip" } MimeTypes = new[] { "application/x-nx-xci", "application/zip" },
}, },
new("XCI") new("XCI")
{ {
Patterns = new[] { "*.xci" }, Patterns = new[] { "*.xci" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" }, AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" },
MimeTypes = new[] { "application/x-nx-xci" } MimeTypes = new[] { "application/x-nx-xci" },
}, },
new("ZIP") new("ZIP")
{ {
Patterns = new[] { "*.zip" }, Patterns = new[] { "*.zip" },
AppleUniformTypeIdentifiers = new[] { "public.zip-archive" }, AppleUniformTypeIdentifiers = new[] { "public.zip-archive" },
MimeTypes = new[] { "application/zip" } MimeTypes = new[] { "application/zip" },
}, },
} },
}); });
if (result.Count > 0) if (result.Count > 0)
@ -1317,11 +1312,11 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public async void InstallFirmwareFromFolder() public async Task InstallFirmwareFromFolder()
{ {
var result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions var result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{ {
AllowMultiple = false AllowMultiple = false,
}); });
if (result.Count > 0) if (result.Count > 0)
@ -1352,7 +1347,7 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public async void ExitCurrentState() public async Task ExitCurrentState()
{ {
if (WindowState == WindowState.FullScreen) if (WindowState == WindowState.FullScreen)
{ {
@ -1377,7 +1372,7 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public async void ManageProfiles() public async Task ManageProfiles()
{ {
await NavigationDialogHost.Show(AccountManager, ContentManager, VirtualFileSystem, LibHacHorizonManager.RyujinxClient); await NavigationDialogHost.Show(AccountManager, ContentManager, VirtualFileSystem, LibHacHorizonManager.RyujinxClient);
} }
@ -1387,7 +1382,7 @@ namespace Ryujinx.Ava.UI.ViewModels
AppHost.Device.System.SimulateWakeUpMessage(); AppHost.Device.System.SimulateWakeUpMessage();
} }
public async void OpenFile() public async Task OpenFile()
{ {
var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{ {
@ -1404,7 +1399,7 @@ namespace Ryujinx.Ava.UI.ViewModels
"com.ryujinx.xci", "com.ryujinx.xci",
"com.ryujinx.nca", "com.ryujinx.nca",
"com.ryujinx.nro", "com.ryujinx.nro",
"com.ryujinx.nso" "com.ryujinx.nso",
}, },
MimeTypes = new[] MimeTypes = new[]
{ {
@ -1412,63 +1407,63 @@ namespace Ryujinx.Ava.UI.ViewModels
"application/x-nx-xci", "application/x-nx-xci",
"application/x-nx-nca", "application/x-nx-nca",
"application/x-nx-nro", "application/x-nx-nro",
"application/x-nx-nso" "application/x-nx-nso",
} },
}, },
new("NSP") new("NSP")
{ {
Patterns = new[] { "*.nsp" }, Patterns = new[] { "*.nsp" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" }, AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" },
MimeTypes = new[] { "application/x-nx-nsp" } MimeTypes = new[] { "application/x-nx-nsp" },
}, },
new("XCI") new("XCI")
{ {
Patterns = new[] { "*.xci" }, Patterns = new[] { "*.xci" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" }, AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" },
MimeTypes = new[] { "application/x-nx-xci" } MimeTypes = new[] { "application/x-nx-xci" },
}, },
new("NCA") new("NCA")
{ {
Patterns = new[] { "*.nca" }, Patterns = new[] { "*.nca" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nca" }, AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nca" },
MimeTypes = new[] { "application/x-nx-nca" } MimeTypes = new[] { "application/x-nx-nca" },
}, },
new("NRO") new("NRO")
{ {
Patterns = new[] { "*.nro" }, Patterns = new[] { "*.nro" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nro" }, AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nro" },
MimeTypes = new[] { "application/x-nx-nro" } MimeTypes = new[] { "application/x-nx-nro" },
}, },
new("NSO") new("NSO")
{ {
Patterns = new[] { "*.nso" }, Patterns = new[] { "*.nso" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nso" }, AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nso" },
MimeTypes = new[] { "application/x-nx-nso" } MimeTypes = new[] { "application/x-nx-nso" },
}, },
} },
}); });
if (result.Count > 0) if (result.Count > 0)
{ {
LoadApplication(result[0].Path.LocalPath); await LoadApplication(result[0].Path.LocalPath);
} }
} }
public async void OpenFolder() public async Task OpenFolder()
{ {
var result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions var result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{ {
Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle], Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle],
AllowMultiple = false AllowMultiple = false,
}); });
if (result.Count > 0) if (result.Count > 0)
{ {
LoadApplication(result[0].Path.LocalPath); await LoadApplication(result[0].Path.LocalPath);
} }
} }
public async void LoadApplication(string path, bool startFullscreen = false, string titleName = "") public async Task LoadApplication(string path, bool startFullscreen = false, string titleName = "")
{ {
if (AppHost != null) if (AppHost != null)
{ {
@ -1505,35 +1500,30 @@ namespace Ryujinx.Ava.UI.ViewModels
this, this,
TopLevel); TopLevel);
async void Action() if (!await AppHost.LoadGuestApplication())
{ {
if (!await AppHost.LoadGuestApplication()) AppHost.DisposeContext();
{ AppHost = null;
AppHost.DisposeContext();
AppHost = null;
return; return;
}
CanUpdate = false;
LoadHeading = TitleName = titleName;
if (string.IsNullOrWhiteSpace(titleName))
{
LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, AppHost.Device.Processes.ActiveApplication.Name);
TitleName = AppHost.Device.Processes.ActiveApplication.Name;
}
SwitchToRenderer(startFullscreen);
_currentEmulatedGamePath = path;
Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
gameThread.Start();
} }
Dispatcher.UIThread.Post(Action); CanUpdate = false;
LoadHeading = TitleName = titleName;
if (string.IsNullOrWhiteSpace(titleName))
{
LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, AppHost.Device.Processes.ActiveApplication.Name);
TitleName = AppHost.Device.Processes.ActiveApplication.Name;
}
SwitchToRenderer(startFullscreen);
_currentEmulatedGamePath = path;
Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
gameThread.Start();
} }
public void SwitchToRenderer(bool startFullscreen) public void SwitchToRenderer(bool startFullscreen)
@ -1596,7 +1586,7 @@ namespace Ryujinx.Ava.UI.ViewModels
IsGameRunning = false; IsGameRunning = false;
Dispatcher.UIThread.InvokeAsync(() => Dispatcher.UIThread.InvokeAsync(async () =>
{ {
ShowMenuAndStatusBar = true; ShowMenuAndStatusBar = true;
ShowContent = true; ShowContent = true;
@ -1609,7 +1599,7 @@ namespace Ryujinx.Ava.UI.ViewModels
AppHost = null; AppHost = null;
HandleRelaunch(); await HandleRelaunch();
}); });
RendererHostControl.WindowCreated -= RendererHost_Created; RendererHostControl.WindowCreated -= RendererHost_Created;

View file

@ -78,14 +78,13 @@ namespace Ryujinx.Ava.UI.ViewModels
if (_graphicsBackendMultithreadingIndex != (int)ConfigurationState.Instance.Graphics.BackendThreading.Value) if (_graphicsBackendMultithreadingIndex != (int)ConfigurationState.Instance.Graphics.BackendThreading.Value)
{ {
Dispatcher.UIThread.Post(async () => Dispatcher.UIThread.InvokeAsync(() =>
{ ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningMessage],
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningMessage],
"", "",
"", "",
LocaleManager.Instance[LocaleKeys.InputDialogOk], LocaleManager.Instance[LocaleKeys.InputDialogOk],
LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningTitle]); LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningTitle])
}); );
} }
OnPropertyChanged(); OnPropertyChanged();

View file

@ -22,6 +22,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
using Path = System.IO.Path; using Path = System.IO.Path;
using SpanHelpers = LibHac.Common.SpanHelpers; using SpanHelpers = LibHac.Common.SpanHelpers;
@ -184,18 +185,12 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
else else
{ {
Dispatcher.UIThread.Post(async () => Dispatcher.UIThread.InvokeAsync(() => ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUpdateAddUpdateErrorMessage]));
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUpdateAddUpdateErrorMessage]);
});
} }
} }
catch (Exception ex) catch (Exception ex)
{ {
Dispatcher.UIThread.Post(async () => Dispatcher.UIThread.InvokeAsync(() => ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogLoadNcaErrorMessage, ex.Message, path)));
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogLoadNcaErrorMessage, ex.Message, path));
});
} }
} }
} }
@ -207,7 +202,7 @@ namespace Ryujinx.Ava.UI.ViewModels
SortUpdates(); SortUpdates();
} }
public async void Add() public async Task Add()
{ {
var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{ {
@ -218,9 +213,9 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
Patterns = new[] { "*.nsp" }, Patterns = new[] { "*.nsp" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" }, AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" },
MimeTypes = new[] { "application/x-nx-nsp" } MimeTypes = new[] { "application/x-nx-nsp" },
} },
} },
}); });
foreach (var file in result) foreach (var file in result)

View file

@ -17,7 +17,6 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Views.Main namespace Ryujinx.Ava.UI.Views.Main
{ {
@ -107,20 +106,14 @@ namespace Ryujinx.Ava.UI.Views.Main
await Window.ViewModel.AppHost?.ShowExitPrompt(); await Window.ViewModel.AppHost?.ShowExitPrompt();
} }
private async void PauseEmulation_Click(object sender, RoutedEventArgs e) private void PauseEmulation_Click(object sender, RoutedEventArgs e)
{ {
await Task.Run(() => Window.ViewModel.AppHost?.Pause();
{
Window.ViewModel.AppHost?.Pause();
});
} }
private async void ResumeEmulation_Click(object sender, RoutedEventArgs e) private void ResumeEmulation_Click(object sender, RoutedEventArgs e)
{ {
await Task.Run(() => Window.ViewModel.AppHost?.Resume();
{
Window.ViewModel.AppHost?.Resume();
});
} }
public async void OpenSettings(object sender, RoutedEventArgs e) public async void OpenSettings(object sender, RoutedEventArgs e)
@ -132,13 +125,13 @@ namespace Ryujinx.Ava.UI.Views.Main
ViewModel.LoadConfigurableHotKeys(); ViewModel.LoadConfigurableHotKeys();
} }
public void OpenMiiApplet(object sender, RoutedEventArgs e) public async void OpenMiiApplet(object sender, RoutedEventArgs e)
{ {
string contentPath = ViewModel.ContentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program); string contentPath = ViewModel.ContentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program);
if (!string.IsNullOrEmpty(contentPath)) if (!string.IsNullOrEmpty(contentPath))
{ {
ViewModel.LoadApplication(contentPath, false, "Mii Applet"); await ViewModel.LoadApplication(contentPath, false, "Mii Applet");
} }
} }
@ -196,8 +189,7 @@ namespace Ryujinx.Ava.UI.Views.Main
{ {
if (FileAssociationHelper.Install()) if (FileAssociationHelper.Install())
{ {
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesSuccessMessage], await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
} }
else else
{ {
@ -209,8 +201,7 @@ namespace Ryujinx.Ava.UI.Views.Main
{ {
if (FileAssociationHelper.Uninstall()) if (FileAssociationHelper.Uninstall())
{ {
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesSuccessMessage], await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
} }
else else
{ {

View file

@ -34,7 +34,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
{ {
var result = await window.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions var result = await window.StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{ {
AllowMultiple = false AllowMultiple = false,
}); });
if (result.Count > 0) if (result.Count > 0)
@ -75,9 +75,9 @@ namespace Ryujinx.Ava.UI.Views.Settings
{ {
Patterns = new[] { "*.xaml" }, Patterns = new[] { "*.xaml" },
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xaml" }, AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xaml" },
MimeTypes = new[] { "application/xaml+xml" } MimeTypes = new[] { "application/xaml+xml" },
} },
} },
}); });
if (result.Count > 0) if (result.Count > 0)

View file

@ -75,9 +75,9 @@ namespace Ryujinx.Ava.UI.Views.User
{ {
Patterns = new[] { "*.jpg", "*.jpeg", "*.png", "*.bmp" }, Patterns = new[] { "*.jpg", "*.jpeg", "*.png", "*.bmp" },
AppleUniformTypeIdentifiers = new[] { "public.jpeg", "public.png", "com.microsoft.bmp" }, AppleUniformTypeIdentifiers = new[] { "public.jpeg", "public.png", "com.microsoft.bmp" },
MimeTypes = new[] { "image/jpeg", "image/png", "image/bmp" } MimeTypes = new[] { "image/jpeg", "image/png", "image/bmp" },
} },
} },
}); });
if (result.Count > 0) if (result.Count > 0)

View file

@ -25,6 +25,7 @@ using Ryujinx.Ui.Common.Helper;
using System; using System;
using System.IO; using System.IO;
using System.Runtime.Versioning; using System.Runtime.Versioning;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Windows namespace Ryujinx.Ava.UI.Windows
@ -79,35 +80,11 @@ namespace Ryujinx.Ava.UI.Windows
if (Program.PreviewerDetached) if (Program.PreviewerDetached)
{ {
Initialize();
InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver()); InputManager = new InputManager(new AvaloniaKeyboardDriver(this), new SDL2GamepadDriver());
ViewModel.Initialize(
ContentManager,
StorageProvider,
ApplicationLibrary,
VirtualFileSystem,
AccountManager,
InputManager,
_userChannelPersistence,
LibHacHorizonManager,
UiHandler,
ShowLoading,
SwitchToGameControl,
SetMainContent,
this);
ViewModel.RefreshFirmwareStatus();
LoadGameList();
this.GetObservable(IsActiveProperty).Subscribe(IsActiveChanged); this.GetObservable(IsActiveProperty).Subscribe(IsActiveChanged);
this.ScalingChanged += OnScalingChanged; this.ScalingChanged += OnScalingChanged;
} }
ApplicationLibrary.ApplicationCountUpdated += ApplicationLibrary_ApplicationCountUpdated;
ApplicationLibrary.ApplicationAdded += ApplicationLibrary_ApplicationAdded;
} }
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
@ -122,36 +99,17 @@ namespace Ryujinx.Ava.UI.Windows
ViewModel.IsActive = obj; ViewModel.IsActive = obj;
} }
public void LoadGameList()
{
if (_isLoading)
{
return;
}
_isLoading = true;
LoadApplications();
_isLoading = false;
}
private void OnScalingChanged(object sender, EventArgs e) private void OnScalingChanged(object sender, EventArgs e)
{ {
Program.DesktopScaleFactor = this.RenderScaling; Program.DesktopScaleFactor = this.RenderScaling;
} }
public void AddApplication(ApplicationData applicationData)
{
Dispatcher.UIThread.InvokeAsync(() =>
{
ViewModel.Applications.Add(applicationData);
});
}
private void ApplicationLibrary_ApplicationAdded(object sender, ApplicationAddedEventArgs e) private void ApplicationLibrary_ApplicationAdded(object sender, ApplicationAddedEventArgs e)
{ {
AddApplication(e.AppData); Dispatcher.UIThread.Post(() =>
{
ViewModel.Applications.Add(e.AppData);
});
} }
private void ApplicationLibrary_ApplicationCountUpdated(object sender, ApplicationCountUpdatedEventArgs e) private void ApplicationLibrary_ApplicationCountUpdated(object sender, ApplicationCountUpdatedEventArgs e)
@ -183,7 +141,7 @@ namespace Ryujinx.Ava.UI.Windows
string path = new FileInfo(args.Application.Path).FullName; string path = new FileInfo(args.Application.Path).FullName;
ViewModel.LoadApplication(path); ViewModel.LoadApplication(path).Wait();
} }
args.Handled = true; args.Handled = true;
@ -202,13 +160,10 @@ namespace Ryujinx.Ava.UI.Windows
ViewModel.ShowContent = true; ViewModel.ShowContent = true;
ViewModel.IsLoadingIndeterminate = false; ViewModel.IsLoadingIndeterminate = false;
Dispatcher.UIThread.InvokeAsync(() => if (startFullscreen && ViewModel.WindowState != WindowState.FullScreen)
{ {
if (startFullscreen && ViewModel.WindowState != WindowState.FullScreen) ViewModel.ToggleFullscreen();
{ }
ViewModel.ToggleFullscreen();
}
});
} }
public void ShowLoading(bool startFullscreen = false) public void ShowLoading(bool startFullscreen = false)
@ -217,13 +172,10 @@ namespace Ryujinx.Ava.UI.Windows
ViewModel.ShowLoadProgress = true; ViewModel.ShowLoadProgress = true;
ViewModel.IsLoadingIndeterminate = true; ViewModel.IsLoadingIndeterminate = true;
Dispatcher.UIThread.InvokeAsync(() => if (startFullscreen && ViewModel.WindowState != WindowState.FullScreen)
{ {
if (startFullscreen && ViewModel.WindowState != WindowState.FullScreen) ViewModel.ToggleFullscreen();
{ }
ViewModel.ToggleFullscreen();
}
});
} }
private void Initialize() private void Initialize()
@ -255,7 +207,7 @@ namespace Ryujinx.Ava.UI.Windows
} }
[SupportedOSPlatform("linux")] [SupportedOSPlatform("linux")]
private static async void ShowVmMaxMapCountWarning() private static async Task ShowVmMaxMapCountWarning()
{ {
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LinuxVmMaxMapCountWarningTextSecondary, LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LinuxVmMaxMapCountWarningTextSecondary,
LinuxHelper.VmMaxMapCount, LinuxHelper.RecommendedVmMaxMapCount); LinuxHelper.VmMaxMapCount, LinuxHelper.RecommendedVmMaxMapCount);
@ -267,7 +219,7 @@ namespace Ryujinx.Ava.UI.Windows
} }
[SupportedOSPlatform("linux")] [SupportedOSPlatform("linux")]
private static async void ShowVmMaxMapCountDialog() private static async Task ShowVmMaxMapCountDialog()
{ {
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LinuxVmMaxMapCountDialogTextPrimary, LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LinuxVmMaxMapCountDialogTextPrimary,
LinuxHelper.RecommendedVmMaxMapCount); LinuxHelper.RecommendedVmMaxMapCount);
@ -317,8 +269,7 @@ namespace Ryujinx.Ava.UI.Windows
{ {
ShowKeyErrorOnLoad = false; ShowKeyErrorOnLoad = false;
Dispatcher.UIThread.Post(async () => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys).Wait();
UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys));
} }
if (OperatingSystem.IsLinux() && LinuxHelper.VmMaxMapCount < LinuxHelper.RecommendedVmMaxMapCount) if (OperatingSystem.IsLinux() && LinuxHelper.VmMaxMapCount < LinuxHelper.RecommendedVmMaxMapCount)
@ -327,11 +278,11 @@ namespace Ryujinx.Ava.UI.Windows
if (LinuxHelper.PkExecPath is not null) if (LinuxHelper.PkExecPath is not null)
{ {
Dispatcher.UIThread.Post(ShowVmMaxMapCountDialog); ShowVmMaxMapCountDialog().Wait();
} }
else else
{ {
Dispatcher.UIThread.Post(ShowVmMaxMapCountWarning); ShowVmMaxMapCountWarning().Wait();
} }
} }
@ -339,7 +290,7 @@ namespace Ryujinx.Ava.UI.Windows
{ {
_deferLoad = false; _deferLoad = false;
ViewModel.LoadApplication(_launchPath, _startFullscreen); ViewModel.LoadApplication(_launchPath, _startFullscreen).Wait();
} }
if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false)) if (ConfigurationState.Instance.CheckUpdatesOnStart.Value && Updater.CanUpdate(false))
@ -372,7 +323,7 @@ namespace Ryujinx.Ava.UI.Windows
ViewModel.WindowHeight = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeHeight * Program.WindowScaleFactor; ViewModel.WindowHeight = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeHeight * Program.WindowScaleFactor;
ViewModel.WindowWidth = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeWidth * Program.WindowScaleFactor; ViewModel.WindowWidth = ConfigurationState.Instance.Ui.WindowStartup.WindowSizeWidth * Program.WindowScaleFactor;
ViewModel.WindowState = ConfigurationState.Instance.Ui.WindowStartup.WindowMaximized.Value is true ? WindowState.Maximized : WindowState.Normal; ViewModel.WindowState = ConfigurationState.Instance.Ui.WindowStartup.WindowMaximized.Value ? WindowState.Maximized : WindowState.Normal;
if (CheckScreenBounds(savedPoint)) if (CheckScreenBounds(savedPoint))
{ {
@ -415,6 +366,30 @@ namespace Ryujinx.Ava.UI.Windows
{ {
base.OnOpened(e); base.OnOpened(e);
Initialize();
ViewModel.Initialize(
ContentManager,
StorageProvider,
ApplicationLibrary,
VirtualFileSystem,
AccountManager,
InputManager,
_userChannelPersistence,
LibHacHorizonManager,
UiHandler,
ShowLoading,
SwitchToGameControl,
SetMainContent,
this);
ApplicationLibrary.ApplicationCountUpdated += ApplicationLibrary_ApplicationCountUpdated;
ApplicationLibrary.ApplicationAdded += ApplicationLibrary_ApplicationAdded;
ViewModel.RefreshFirmwareStatus();
LoadApplications();
CheckLaunchState(); CheckLaunchState();
} }
@ -514,18 +489,15 @@ namespace Ryujinx.Ava.UI.Windows
}); });
} }
public async void LoadApplications() public void LoadApplications()
{ {
await Dispatcher.UIThread.InvokeAsync(() => ViewModel.Applications.Clear();
{
ViewModel.Applications.Clear();
StatusBarView.LoadProgressBar.IsVisible = true; StatusBarView.LoadProgressBar.IsVisible = true;
ViewModel.StatusBarProgressMaximum = 0; ViewModel.StatusBarProgressMaximum = 0;
ViewModel.StatusBarProgressValue = 0; ViewModel.StatusBarProgressValue = 0;
LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0); LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarGamesLoaded, 0, 0);
});
ReloadGameList(); ReloadGameList();
} }
@ -558,9 +530,17 @@ namespace Ryujinx.Ava.UI.Windows
_isLoading = true; _isLoading = true;
ApplicationLibrary.LoadApplications(ConfigurationState.Instance.Ui.GameDirs.Value, ConfigurationState.Instance.System.Language); Thread applicationLibraryThread = new(() =>
{
ApplicationLibrary.LoadApplications(ConfigurationState.Instance.Ui.GameDirs, ConfigurationState.Instance.System.Language);
_isLoading = false; _isLoading = false;
})
{
Name = "GUI.ApplicationLibraryThread",
IsBackground = true,
};
applicationLibraryThread.Start();
} }
} }
} }

View file

@ -3,7 +3,6 @@ using Avalonia.Controls.Primitives;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Platform; using Avalonia.Platform;
using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration;
using System;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
@ -25,11 +24,6 @@ namespace Ryujinx.Ava.UI.Windows
IconImage = new Bitmap(stream); IconImage = new Bitmap(stream);
} }
protected override void OnOpened(EventArgs e)
{
base.OnOpened(e);
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{ {
base.OnApplyTemplate(e); base.OnApplyTemplate(e);