Compare commits

...

13 Commits

Author SHA1 Message Date
Vladimir Sokolov
48c5f59be2
Merge da0d2e1b70 into 0db85d0aa9 2025-03-06 17:32:27 +10:00
Vladimir Sokolov
da0d2e1b70
Merge branch 'master' into Master_PR 2025-03-06 17:32:24 +10:00
Vova
db08498a89 Addition: Device Name and ID are displayed when the controller is turned off, but the controller is configured.
Added the "Name" property for controllers.
Changed the controller setup message to be more informative.
2025-03-06 17:13:11 +10:00
Evan Husted
0db85d0aa9 HLE: optional hack: disable IsAnyInternetRequestAccepted 2025-03-05 23:57:48 -06:00
Evan Husted
44632e5d8b misc: ConfigurationFileFormat version 68 2025-03-05 23:03:55 -06:00
Evan Husted
551d2c1134 misc: chore: add/remove event handler as window is opened/closed 2025-03-05 23:01:37 -06:00
Vova
7a43dcb513 Merge branch 'Master_PR' of https://github.com/Goodfeat/Ryujinx_alt into Master_PR 2025-03-06 14:52:48 +10:00
Vova
f2329d0e8a Fixed bug with turning off active gamepad (independent profiles)
When switching profiles, if the profile does not belong to the gamepad itself, the gamepad began to be displayed as turned off.
Fixed a bug where the return button did not return the initially selected gamepad
2025-03-06 14:52:30 +10:00
Evan Husted
25cc9b24b4 misc: chore: compat database code cleanups 2025-03-05 22:40:55 -06:00
Evan Husted
638c616ab7 misc: Move systems-like classes out of the base of the Ryujinx project and into Ryujinx.Ava.Systems 2025-03-05 22:27:37 -06:00
Evan Husted
109f0fc659 misc: chore: Cleanup unused using directives 2025-03-05 22:21:05 -06:00
Evan Husted
dfcb8a7fc0 misc: chore: Use RyujinxControl<T> in more places 2025-03-05 22:18:13 -06:00
Evan Husted
d87d3235e9 misc: chore: Move the windows that are shown via ContentDialogs out of Ryujinx.Ava.UI.Windows (they're not windows) 2025-03-05 22:06:20 -06:00
73 changed files with 392 additions and 444 deletions

View File

@ -9,7 +9,8 @@ namespace Ryujinx.Common.Configuration
public enum DirtyHack : byte public enum DirtyHack : byte
{ {
Xc2MenuSoftlockFix = 1, Xc2MenuSoftlockFix = 1,
ShaderTranslationDelay = 2 // ShaderTranslationDelay = 2
NifmServiceDisableIsAnyInternetRequestAccepted = 3
} }
public readonly struct EnabledDirtyHack(DirtyHack hack, int value) public readonly struct EnabledDirtyHack(DirtyHack hack, int value)

View File

@ -21,6 +21,11 @@ namespace Ryujinx.Common.Configuration.Hid
/// </summary> /// </summary>
public string Id { get; set; } public string Id { get; set; }
/// <summary>
/// Controller name
/// </summary>
public string Name { get; set; }
/// <summary> /// <summary>
/// Controller's Type /// Controller's Type
/// </summary> /// </summary>

View File

@ -1,7 +1,4 @@
using Gommon; using Gommon;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Helper;
using System;
using System.Linq; using System.Linq;
namespace Ryujinx.Common namespace Ryujinx.Common

View File

@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm
// CreateGeneralServiceOld() -> object<nn::nifm::detail::IGeneralService> // CreateGeneralServiceOld() -> object<nn::nifm::detail::IGeneralService>
public ResultCode CreateGeneralServiceOld(ServiceCtx context) public ResultCode CreateGeneralServiceOld(ServiceCtx context)
{ {
MakeObject(context, new IGeneralService()); MakeObject(context, new IGeneralService(context));
return ResultCode.Success; return ResultCode.Success;
} }
@ -22,7 +22,7 @@ namespace Ryujinx.HLE.HOS.Services.Nifm
// CreateGeneralService(u64, pid) -> object<nn::nifm::detail::IGeneralService> // CreateGeneralService(u64, pid) -> object<nn::nifm::detail::IGeneralService>
public ResultCode CreateGeneralService(ServiceCtx context) public ResultCode CreateGeneralService(ServiceCtx context)
{ {
MakeObject(context, new IGeneralService()); MakeObject(context, new IGeneralService(context));
return ResultCode.Success; return ResultCode.Success;
} }

View File

@ -1,4 +1,5 @@
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.HLE.HOS.Services.Nifm.StaticService.GeneralService; using Ryujinx.HLE.HOS.Services.Nifm.StaticService.GeneralService;
@ -17,12 +18,12 @@ namespace Ryujinx.HLE.HOS.Services.Nifm.StaticService
private UnicastIPAddressInformation _targetAddressInfoCache = null; private UnicastIPAddressInformation _targetAddressInfoCache = null;
private string _cacheChosenInterface = null; private string _cacheChosenInterface = null;
public IGeneralService() public IGeneralService(ServiceCtx context)
{ {
_generalServiceDetail = new GeneralServiceDetail _generalServiceDetail = new GeneralServiceDetail
{ {
ClientId = GeneralServiceManager.Count, ClientId = GeneralServiceManager.Count,
IsAnyInternetRequestAccepted = true, // NOTE: Why not accept any internet request? IsAnyInternetRequestAccepted = !context.Device.DirtyHacks.IsEnabled(DirtyHack.NifmServiceDisableIsAnyInternetRequestAccepted), // NOTE: Why not accept any internet request?
}; };
NetworkChange.NetworkAddressChanged += LocalInterfaceCacheHandler; NetworkChange.NetworkAddressChanged += LocalInterfaceCacheHandler;

View File

@ -1,6 +1,5 @@
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy; using Ryujinx.HLE.HOS.Services.Ldn.UserServiceCreator.LdnRyu.Proxy;
using Ryujinx.HLE.HOS.Services.Sockets.Bsd.Types;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;

View File

@ -6922,6 +6922,31 @@
"zh_TW": "輸入裝置" "zh_TW": "輸入裝置"
} }
}, },
{
"ID": "ControllerSettingsWaitingConnectDevice",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Configuration found:\n\nName:\t{0}\nGUID:\t{1}\n\n Waiting for controller connection...",
"es_ES": "",
"fr_FR": "",
"he_IL": "",
"it_IT": "",
"ja_JP": "",
"ko_KR": "",
"no_NO": "",
"pl_PL": "",
"pt_BR": "",
"ru_RU": "",
"sv_SE": "",
"th_TH": "",
"tr_TR": "",
"uk_UA": "",
"zh_CN": "",
"zh_TW": ""
}
},
{ {
"ID": "ControllerSettingsRefresh", "ID": "ControllerSettingsRefresh",
"Translations": { "Translations": {

View File

@ -38,8 +38,8 @@ namespace Ryujinx.Ava.Common.Locale
{ LocaleKeys.RyujinxConfirm, [RyujinxApp.FullAppName] }, { LocaleKeys.RyujinxConfirm, [RyujinxApp.FullAppName] },
{ LocaleKeys.RyujinxUpdater, [RyujinxApp.FullAppName] }, { LocaleKeys.RyujinxUpdater, [RyujinxApp.FullAppName] },
{ LocaleKeys.RyujinxRebooter, [RyujinxApp.FullAppName] }, { LocaleKeys.RyujinxRebooter, [RyujinxApp.FullAppName] },
{ LocaleKeys.CompatibilityListSearchBoxWatermarkWithCount, [CompatibilityCsv.Entries.Length] }, { LocaleKeys.CompatibilityListSearchBoxWatermarkWithCount, [CompatibilityDatabase.Entries.Length] },
{ LocaleKeys.CompatibilityListTitle, [CompatibilityCsv.Entries.Length] } { LocaleKeys.CompatibilityListTitle, [CompatibilityDatabase.Entries.Length] }
}); });
Load(); Load();

View File

@ -1,5 +1,4 @@
using Avalonia.Markup.Xaml.MarkupExtensions; using Avalonia.Markup.Xaml.MarkupExtensions;
using Humanizer;
using Projektanker.Icons.Avalonia; using Projektanker.Icons.Avalonia;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;

View File

@ -26,9 +26,9 @@ namespace Ryujinx.Ava.Common
internal class TrimmerWindow : Ryujinx.Common.Logging.XCIFileTrimmerLog internal class TrimmerWindow : Ryujinx.Common.Logging.XCIFileTrimmerLog
{ {
private readonly XCITrimmerViewModel _viewModel; private readonly XciTrimmerViewModel _viewModel;
public TrimmerWindow(XCITrimmerViewModel viewModel) public TrimmerWindow(XciTrimmerViewModel viewModel)
{ {
_viewModel = viewModel; _viewModel = viewModel;
} }

View File

@ -2,6 +2,7 @@ using DiscordRPC;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Audio.Backends.SDL2;
using Ryujinx.Ava; using Ryujinx.Ava;
using Ryujinx.Ava.Systems;
using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
@ -11,7 +12,6 @@ using Ryujinx.Common.Configuration.Hid.Keyboard;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.GAL;
using Ryujinx.Graphics.GAL.Multithreading;
using Ryujinx.Graphics.OpenGL; using Ryujinx.Graphics.OpenGL;
using Ryujinx.Graphics.Vulkan; using Ryujinx.Graphics.Vulkan;
using Ryujinx.HLE; using Ryujinx.HLE;

View File

@ -5,6 +5,7 @@ using Gommon;
using Projektanker.Icons.Avalonia; using Projektanker.Icons.Avalonia;
using Projektanker.Icons.Avalonia.FontAwesome; using Projektanker.Icons.Avalonia.FontAwesome;
using Projektanker.Icons.Avalonia.MaterialDesign; using Projektanker.Icons.Avalonia.MaterialDesign;
using Ryujinx.Ava.Systems;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities; using Ryujinx.Ava.Utilities;

View File

@ -91,10 +91,12 @@
<Content Include="..\..\distribution\legal\THIRDPARTY.md"> <Content Include="..\..\distribution\legal\THIRDPARTY.md">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>THIRDPARTY.md</TargetPath> <TargetPath>THIRDPARTY.md</TargetPath>
<Visible>False</Visible>
</Content> </Content>
<Content Include="..\..\LICENSE.txt"> <Content Include="..\..\LICENSE.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
<TargetPath>LICENSE.txt</TargetPath> <TargetPath>LICENSE.txt</TargetPath>
<Visible>False</Visible>
</Content> </Content>
</ItemGroup> </ItemGroup>

View File

@ -6,7 +6,6 @@ using Avalonia.Threading;
using DiscordRPC; using DiscordRPC;
using LibHac.Common; using LibHac.Common;
using LibHac.Ns; using LibHac.Ns;
using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.Dummy; using Ryujinx.Audio.Backends.Dummy;
using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.OpenAL;
using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Audio.Backends.SDL2;
@ -35,11 +34,9 @@ using Ryujinx.Graphics.GAL.Multithreading;
using Ryujinx.Graphics.Gpu; using Ryujinx.Graphics.Gpu;
using Ryujinx.Graphics.OpenGL; using Ryujinx.Graphics.OpenGL;
using Ryujinx.Graphics.Vulkan; using Ryujinx.Graphics.Vulkan;
using Ryujinx.HLE;
using Ryujinx.HLE.FileSystem; 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.HOS.SystemState;
using Ryujinx.Input; using Ryujinx.Input;
using Ryujinx.Input.HLE; using Ryujinx.Input.HLE;
using SkiaSharp; using SkiaSharp;
@ -62,7 +59,7 @@ using Size = Avalonia.Size;
using Switch = Ryujinx.HLE.Switch; using Switch = Ryujinx.HLE.Switch;
using VSyncMode = Ryujinx.Common.Configuration.VSyncMode; using VSyncMode = Ryujinx.Common.Configuration.VSyncMode;
namespace Ryujinx.Ava namespace Ryujinx.Ava.Systems
{ {
internal class AppHost internal class AppHost
{ {

View File

@ -36,7 +36,7 @@ namespace Ryujinx.Ava.Systems.AppLibrary
{ {
_id = value; _id = value;
Compatibility = CompatibilityCsv.Find(value); Compatibility = CompatibilityDatabase.Find(value);
RichPresenceSpec = PlayReports.Analyzer.TryGetSpec(IdString, out GameSpec gameSpec) RichPresenceSpec = PlayReports.Analyzer.TryGetSpec(IdString, out GameSpec gameSpec)
? gameSpec ? gameSpec
: default(Optional<GameSpec>); : default(Optional<GameSpec>);

View File

@ -1,5 +1,4 @@
using System; using System;
using System.Collections.Generic;
namespace Ryujinx.Ava.Systems.AppLibrary namespace Ryujinx.Ava.Systems.AppLibrary
{ {

View File

@ -11,24 +11,9 @@ using System.Text;
namespace Ryujinx.Ava.Systems namespace Ryujinx.Ava.Systems
{ {
public struct ColumnIndices(Func<ReadOnlySpan<char>, int> getIndex) public class CompatibilityDatabase
{ {
public const string TitleIdCol = "\"title_id\""; static CompatibilityDatabase() => Load();
public const string GameNameCol = "\"game_name\"";
public const string LabelsCol = "\"labels\"";
public const string StatusCol = "\"status\"";
public const string LastUpdatedCol = "\"last_updated\"";
public readonly int TitleId = getIndex(TitleIdCol);
public readonly int GameName = getIndex(GameNameCol);
public readonly int Labels = getIndex(LabelsCol);
public readonly int Status = getIndex(StatusCol);
public readonly int LastUpdated = getIndex(LastUpdatedCol);
}
public class CompatibilityCsv
{
static CompatibilityCsv() => Load();
public static void Load() public static void Load()
{ {
@ -65,16 +50,6 @@ namespace Ryujinx.Ava.Systems
public static CompatibilityEntry Find(ulong titleId) public static CompatibilityEntry Find(ulong titleId)
=> Find(titleId.ToString("X16")); => Find(titleId.ToString("X16"));
public static LocaleKeys? GetStatus(string titleId)
=> Find(titleId)?.Status;
public static LocaleKeys? GetStatus(ulong titleId) => GetStatus(titleId.ToString("X16"));
public static string GetLabels(string titleId)
=> Find(titleId)?.FormattedIssueLabels;
public static string GetLabels(ulong titleId) => GetLabels(titleId.ToString("X16"));
} }
public class CompatibilityEntry public class CompatibilityEntry
@ -135,6 +110,7 @@ namespace Ryujinx.Ava.Systems
public string FormattedIssueLabels => Labels public string FormattedIssueLabels => Labels
.Select(FormatLabelName) .Select(FormatLabelName)
.Where(x => x != null)
.JoinToString(", "); .JoinToString(", ");
public override string ToString() => public override string ToString() =>
@ -158,7 +134,6 @@ namespace Ryujinx.Ava.Systems
"gui" => "GUI", "gui" => "GUI",
"help wanted" => "Help Wanted", "help wanted" => "Help Wanted",
"horizon" => "Horizon", "horizon" => "Horizon",
"infra" => "Project Infra",
"invalid" => "Invalid", "invalid" => "Invalid",
"kernel" => "Kernel", "kernel" => "Kernel",
"ldn" => "LDN", "ldn" => "LDN",
@ -172,9 +147,9 @@ namespace Ryujinx.Ava.Systems
"ldn-untested" => "LDN Untested", "ldn-untested" => "LDN Untested",
"ldn-broken" => "LDN Broken", "ldn-broken" => "LDN Broken",
"ldn-partial" => "Partial LDN", "ldn-partial" => "Partial LDN",
"nvdec" => "NVDEC", "nvdec" => "GPU Video Decoding",
"services" => "NX Services", "services" => "HLE Services",
"services-horizon" => "Horizon OS Services", "services-horizon" => "New HLE Services",
"slow" => "Runs Slow", "slow" => "Runs Slow",
"crash" => "Crashes", "crash" => "Crashes",
"deadlock" => "Deadlock", "deadlock" => "Deadlock",
@ -182,7 +157,7 @@ namespace Ryujinx.Ava.Systems
"opengl" => "OpenGL", "opengl" => "OpenGL",
"opengl-backend-bug" => "OpenGL Backend Bug", "opengl-backend-bug" => "OpenGL Backend Bug",
"vulkan-backend-bug" => "Vulkan Backend Bug", "vulkan-backend-bug" => "Vulkan Backend Bug",
"mac-bug" => "Mac-specific Bug(s)", "mac-bug" => "Mac-specific Problems",
"amd-vendor-bug" => "AMD GPU Bug", "amd-vendor-bug" => "AMD GPU Bug",
"intel-vendor-bug" => "Intel GPU Bug", "intel-vendor-bug" => "Intel GPU Bug",
"loader-allocator" => "Loader Allocator", "loader-allocator" => "Loader Allocator",
@ -191,18 +166,22 @@ namespace Ryujinx.Ava.Systems
"UE4" => "Unreal Engine 4", "UE4" => "Unreal Engine 4",
"homebrew" => "Homebrew Content", "homebrew" => "Homebrew Content",
"online-broken" => "Online Broken", "online-broken" => "Online Broken",
_ => Capitalize(labelName) _ => null
}; };
}
public static string Capitalize(string value) public struct ColumnIndices(Func<ReadOnlySpan<char>, int> getIndex)
{ {
if (value == string.Empty) private const string TitleIdCol = "\"title_id\"";
return string.Empty; private const string GameNameCol = "\"game_name\"";
private const string LabelsCol = "\"labels\"";
private const string StatusCol = "\"status\"";
private const string LastUpdatedCol = "\"last_updated\"";
char firstChar = value[0]; public readonly int TitleId = getIndex(TitleIdCol);
string rest = value[1..]; public readonly int GameName = getIndex(GameNameCol);
public readonly int Labels = getIndex(LabelsCol);
return $"{char.ToUpper(firstChar)}{rest}"; public readonly int Status = getIndex(StatusCol);
} public readonly int LastUpdated = getIndex(LastUpdatedCol);
} }
} }

View File

@ -15,7 +15,7 @@ namespace Ryujinx.Ava.Systems.Configuration
/// <summary> /// <summary>
/// The current version of the file format /// The current version of the file format
/// </summary> /// </summary>
public const int CurrentVersion = 67; public const int CurrentVersion = 68;
/// <summary> /// <summary>
/// Version of the configuration file format /// Version of the configuration file format

View File

@ -161,8 +161,6 @@ namespace Ryujinx.Ava.Systems.Configuration
Hacks.Xc2MenuSoftlockFix.Value = hacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix); Hacks.Xc2MenuSoftlockFix.Value = hacks.IsEnabled(DirtyHack.Xc2MenuSoftlockFix);
Hacks.EnableShaderTranslationDelay.Value = hacks.IsEnabled(DirtyHack.ShaderTranslationDelay);
Hacks.ShaderTranslationDelay.Value = hacks[DirtyHack.ShaderTranslationDelay].CoerceAtLeast(0);
} }
if (configurationFileUpdated) if (configurationFileUpdated)
@ -441,6 +439,8 @@ namespace Ryujinx.Ava.Systems.Configuration
(65, static cff => cff.UpdateCheckerType = cff.CheckUpdatesOnStart ? UpdaterType.PromptAtStartup : UpdaterType.Off), (65, static cff => cff.UpdateCheckerType = cff.CheckUpdatesOnStart ? UpdaterType.PromptAtStartup : UpdaterType.Off),
(66, static cff => cff.DisableInputWhenOutOfFocus = false), (66, static cff => cff.DisableInputWhenOutOfFocus = false),
(67, static cff => cff.FocusLostActionType = cff.DisableInputWhenOutOfFocus ? FocusLostType.BlockInput : FocusLostType.DoNothing) (67, static cff => cff.FocusLostActionType = cff.DisableInputWhenOutOfFocus ? FocusLostType.BlockInput : FocusLostType.DoNothing)
// 68 was the version that added per-game configs; the file structure did not change
// the version was increased so external tools could know that your Ryujinx version has per-game config capabilities.
); );
} }
} }

View File

@ -11,7 +11,6 @@ using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.HLE.HOS.SystemState;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using RyuLogger = Ryujinx.Common.Logging.Logger; using RyuLogger = Ryujinx.Common.Logging.Logger;
@ -684,18 +683,15 @@ namespace Ryujinx.Ava.Systems.Configuration
public ReactiveObject<bool> Xc2MenuSoftlockFix { get; private set; } public ReactiveObject<bool> Xc2MenuSoftlockFix { get; private set; }
public ReactiveObject<bool> EnableShaderTranslationDelay { get; private set; } public ReactiveObject<bool> DisableNifmIsAnyInternetRequestAccepted { get; private set; }
public ReactiveObject<int> ShaderTranslationDelay { get; private set; }
public HacksSection() public HacksSection()
{ {
ShowDirtyHacks = new ReactiveObject<bool>(); ShowDirtyHacks = new ReactiveObject<bool>();
Xc2MenuSoftlockFix = new ReactiveObject<bool>(); Xc2MenuSoftlockFix = new ReactiveObject<bool>();
Xc2MenuSoftlockFix.Event += HackChanged; Xc2MenuSoftlockFix.Event += HackChanged;
EnableShaderTranslationDelay = new ReactiveObject<bool>(); DisableNifmIsAnyInternetRequestAccepted = new ReactiveObject<bool>();
EnableShaderTranslationDelay.Event += HackChanged; DisableNifmIsAnyInternetRequestAccepted.Event += HackChanged;
ShaderTranslationDelay = new ReactiveObject<int>();
} }
private void HackChanged(object sender, ReactiveEventArgs<bool> rxe) private void HackChanged(object sender, ReactiveEventArgs<bool> rxe)
@ -726,8 +722,8 @@ namespace Ryujinx.Ava.Systems.Configuration
if (Xc2MenuSoftlockFix) if (Xc2MenuSoftlockFix)
Apply(DirtyHack.Xc2MenuSoftlockFix); Apply(DirtyHack.Xc2MenuSoftlockFix);
if (EnableShaderTranslationDelay) if (DisableNifmIsAnyInternetRequestAccepted)
Apply(DirtyHack.ShaderTranslationDelay, ShaderTranslationDelay); Apply(DirtyHack.NifmServiceDisableIsAnyInternetRequestAccepted);
return enabledHacks.ToArray(); return enabledHacks.ToArray();

View File

@ -269,6 +269,7 @@ namespace Ryujinx.Ava.Systems.Configuration
Version = InputConfig.CurrentVersion, Version = InputConfig.CurrentVersion,
Backend = InputBackendType.WindowKeyboard, Backend = InputBackendType.WindowKeyboard,
Id = "0", Id = "0",
Name = "Keyboard",
PlayerIndex = PlayerIndex.Player1, PlayerIndex = PlayerIndex.Player1,
ControllerType = ControllerType.ProController, ControllerType = ControllerType.ProController,
LeftJoycon = new LeftJoyconCommonConfig<Key> LeftJoycon = new LeftJoyconCommonConfig<Key>

View File

@ -9,10 +9,9 @@ using Ryujinx.Common.Logging;
using Ryujinx.HLE; using Ryujinx.HLE;
using Ryujinx.HLE.Loaders.Processes; using Ryujinx.HLE.Loaders.Processes;
using Ryujinx.Horizon; using Ryujinx.Horizon;
using Ryujinx.Horizon.Prepo.Types;
using System.Text; using System.Text;
namespace Ryujinx.Ava namespace Ryujinx.Ava.Systems
{ {
public static class DiscordIntegrationModule public static class DiscordIntegrationModule
{ {
@ -124,7 +123,7 @@ namespace Ryujinx.Ava
_currentApp = null; _currentApp = null;
} }
private static void HandlePlayReport(PlayReport playReport) private static void HandlePlayReport(Horizon.Prepo.Types.PlayReport playReport)
{ {
if (_discordClient is null) return; if (_discordClient is null) return;
if (!TitleIDs.CurrentApplication.Value.HasValue) return; if (!TitleIDs.CurrentApplication.Value.HasValue) return;

View File

@ -1,8 +1,6 @@
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Utilities; using Ryujinx.Ava.Utilities;
using SkiaSharp;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
@ -10,7 +8,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava namespace Ryujinx.Ava.Systems
{ {
internal static class Rebooter internal static class Rebooter
{ {

View File

@ -27,7 +27,7 @@ using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava namespace Ryujinx.Ava.Systems
{ {
internal static class Updater internal static class Updater
{ {

View File

@ -9,10 +9,10 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Views.Misc;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities; using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Views.Dialog;
using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration;
using Ryujinx.Common.Helper; using Ryujinx.Common.Helper;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
@ -80,13 +80,13 @@ namespace Ryujinx.Ava.UI.Controls
public async void OpenTitleUpdateManager_Click(object sender, RoutedEventArgs args) public async void OpenTitleUpdateManager_Click(object sender, RoutedEventArgs args)
{ {
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
await TitleUpdateWindow.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication); await TitleUpdateManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication);
} }
public async void OpenDownloadableContentManager_Click(object sender, RoutedEventArgs args) public async void OpenDownloadableContentManager_Click(object sender, RoutedEventArgs args)
{ {
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
await DownloadableContentManagerWindow.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication); await DownloadableContentManagerView.Show(viewModel.ApplicationLibrary, viewModel.SelectedApplication);
} }
public async void OpenCheatManager_Click(object sender, RoutedEventArgs args) public async void OpenCheatManager_Click(object sender, RoutedEventArgs args)
@ -127,7 +127,7 @@ namespace Ryujinx.Ava.UI.Controls
public async void OpenModManager_Click(object sender, RoutedEventArgs args) public async void OpenModManager_Click(object sender, RoutedEventArgs args)
{ {
if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel }) if (sender is MenuItem { DataContext: MainWindowViewModel { SelectedApplication: not null } viewModel })
await ModManagerWindow.Show( await ModManagerView.Show(
viewModel.SelectedApplication.Id, viewModel.SelectedApplication.Id,
viewModel.SelectedApplication.IdBase, viewModel.SelectedApplication.IdBase,
viewModel.ApplicationLibrary, viewModel.ApplicationLibrary,

View File

@ -1,6 +1,5 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Layout;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;

View File

@ -2,9 +2,9 @@ using SkiaSharp;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
namespace Ryujinx.Ava.UI.Windows namespace Ryujinx.Ava.UI.Helpers
{ {
static class IconColorPicker public static class IconColorPicker
{ {
private const int ColorsPerLine = 64; private const int ColorsPerLine = 64;
private const int TotalColors = ColorsPerLine * ColorsPerLine; private const int TotalColors = ColorsPerLine * ColorsPerLine;

View File

@ -22,6 +22,8 @@ namespace Ryujinx.Ava.UI.Models.Input
public float StrongRumble { get; set; } public float StrongRumble { get; set; }
public string Id { get; set; } public string Id { get; set; }
public string Name { get; set; }
public ControllerType ControllerType { get; set; } public ControllerType ControllerType { get; set; }
public PlayerIndex PlayerIndex { get; set; } public PlayerIndex PlayerIndex { get; set; }
@ -111,6 +113,7 @@ namespace Ryujinx.Ava.UI.Models.Input
if (config != null) if (config != null)
{ {
Id = config.Id; Id = config.Id;
Name = config.Name;
ControllerType = config.ControllerType; ControllerType = config.ControllerType;
PlayerIndex = config.PlayerIndex; PlayerIndex = config.PlayerIndex;
@ -201,6 +204,7 @@ namespace Ryujinx.Ava.UI.Models.Input
StandardControllerInputConfig config = new() StandardControllerInputConfig config = new()
{ {
Id = Id, Id = Id,
Name = Name,
Backend = InputBackendType.GamepadSDL2, Backend = InputBackendType.GamepadSDL2,
PlayerIndex = PlayerIndex, PlayerIndex = PlayerIndex,
ControllerType = ControllerType, ControllerType = ControllerType,

View File

@ -2,12 +2,14 @@ using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Keyboard; using Ryujinx.Common.Configuration.Hid.Keyboard;
using System.Xml.Linq;
namespace Ryujinx.Ava.UI.Models.Input namespace Ryujinx.Ava.UI.Models.Input
{ {
public partial class KeyboardInputConfig : BaseModel public partial class KeyboardInputConfig : BaseModel
{ {
public string Id { get; set; } public string Id { get; set; }
public string Name { get; set; }
public ControllerType ControllerType { get; set; } public ControllerType ControllerType { get; set; }
public PlayerIndex PlayerIndex { get; set; } public PlayerIndex PlayerIndex { get; set; }
@ -53,6 +55,7 @@ namespace Ryujinx.Ava.UI.Models.Input
if (config != null) if (config != null)
{ {
Id = config.Id; Id = config.Id;
Name = config.Name;
ControllerType = config.ControllerType; ControllerType = config.ControllerType;
PlayerIndex = config.PlayerIndex; PlayerIndex = config.PlayerIndex;
@ -100,6 +103,7 @@ namespace Ryujinx.Ava.UI.Models.Input
StandardKeyboardInputConfig config = new() StandardKeyboardInputConfig config = new()
{ {
Id = Id, Id = Id,
Name = Name,
Backend = InputBackendType.WindowKeyboard, Backend = InputBackendType.WindowKeyboard,
PlayerIndex = PlayerIndex, PlayerIndex = PlayerIndex,
ControllerType = ControllerType, ControllerType = ControllerType,

View File

@ -7,12 +7,12 @@ using Avalonia.Styling;
using Avalonia.Threading; using Avalonia.Threading;
using FluentAvalonia.UI.Windowing; using FluentAvalonia.UI.Windowing;
using Gommon; using Gommon;
using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Windows; using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities; using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Views.Dialog;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Logging; using Ryujinx.Common.Logging;
using System; using System;
@ -150,7 +150,7 @@ namespace Ryujinx.Ava
private async void AboutRyujinx_OnClick(object sender, EventArgs e) private async void AboutRyujinx_OnClick(object sender, EventArgs e)
{ {
await AboutWindow.Show(); await AboutView.Show();
} }
} }
} }

View File

@ -3,7 +3,6 @@ using Avalonia.Styling;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using Gommon; using Gommon;
using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.Systems.Configuration;
using System; using System;

View File

@ -1,17 +1,17 @@
using Gommon; using Gommon;
using Ryujinx.Ava.Systems; using Ryujinx.Ava.Systems;
using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Windows; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class CompatibilityViewModel : BaseModel public class CompatibilityViewModel : BaseModel, IDisposable
{ {
private bool _onlyShowOwnedGames = true; private readonly ApplicationLibrary _appLibrary;
private IEnumerable<CompatibilityEntry> _currentEntries = CompatibilityCsv.Entries; private IEnumerable<CompatibilityEntry> _currentEntries = CompatibilityDatabase.Entries;
private string[] _ownedGameTitleIds = []; private string[] _ownedGameTitleIds = [];
public IEnumerable<CompatibilityEntry> CurrentEntries => OnlyShowOwnedGames public IEnumerable<CompatibilityEntry> CurrentEntries => OnlyShowOwnedGames
@ -21,14 +21,26 @@ namespace Ryujinx.Ava.UI.ViewModels
public CompatibilityViewModel() {} public CompatibilityViewModel() {}
private void AppCountUpdated(object _, ApplicationCountUpdatedEventArgs __)
=> _ownedGameTitleIds = _appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray();
public CompatibilityViewModel(ApplicationLibrary appLibrary) public CompatibilityViewModel(ApplicationLibrary appLibrary)
{ {
appLibrary.ApplicationCountUpdated += (_, _) _appLibrary = appLibrary;
=> _ownedGameTitleIds = appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray();
_ownedGameTitleIds = appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray(); AppCountUpdated(null, null);
_appLibrary.ApplicationCountUpdated += AppCountUpdated;
} }
void IDisposable.Dispose()
{
GC.SuppressFinalize(this);
_appLibrary.ApplicationCountUpdated -= AppCountUpdated;
}
private bool _onlyShowOwnedGames = true;
public bool OnlyShowOwnedGames public bool OnlyShowOwnedGames
{ {
get => _onlyShowOwnedGames; get => _onlyShowOwnedGames;
@ -46,11 +58,11 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
if (string.IsNullOrEmpty(searchTerm)) if (string.IsNullOrEmpty(searchTerm))
{ {
SetEntries(CompatibilityCsv.Entries); SetEntries(CompatibilityDatabase.Entries);
return; return;
} }
SetEntries(CompatibilityCsv.Entries.Where(x => SetEntries(CompatibilityDatabase.Entries.Where(x =>
x.GameName.ContainsIgnoreCase(searchTerm) x.GameName.ContainsIgnoreCase(searchTerm)
|| x.TitleId.Check(tid => tid.ContainsIgnoreCase(searchTerm)))); || x.TitleId.Check(tid => tid.ContainsIgnoreCase(searchTerm))));
} }

View File

@ -1,9 +1,5 @@
using Avalonia.Svg.Skia; using Avalonia.Svg.Skia;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Input;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models.Input; using Ryujinx.Ava.UI.Models.Input;
using Ryujinx.Ava.UI.Views.Input; using Ryujinx.Ava.UI.Views.Input;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;

View File

@ -51,6 +51,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
private int _device; private int _device;
private object _configViewModel; private object _configViewModel;
[ObservableProperty] private string _profileName; [ObservableProperty] private string _profileName;
[ObservableProperty] private bool _notificationIsVisible; // Automatically call the NotificationView property with OnPropertyChanged()
[ObservableProperty] private string _notificationText; // Automatically call the NotificationText property with OnPropertyChanged()
private bool _isLoaded; private bool _isLoaded;
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
@ -88,13 +90,14 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public bool IsKeyboard => !IsController; public bool IsKeyboard => !IsController;
public bool IsRight { get; set; } public bool IsRight { get; set; }
public bool IsLeft { get; set; } public bool IsLeft { get; set; }
public int DeviceIndexBeforeChange { get; set; } public string RevertDeviceId { get; set; }
public bool HasLed => SelectedGamepad.Features.HasFlag(GamepadFeaturesFlag.Led); public bool HasLed => SelectedGamepad.Features.HasFlag(GamepadFeaturesFlag.Led);
public bool CanClearLed => SelectedGamepad.Name.ContainsIgnoreCase("DualSense"); public bool CanClearLed => SelectedGamepad.Name.ContainsIgnoreCase("DualSense");
public bool _isChangeTrackingActive; public bool _isChangeTrackingActive;
public bool _isModified; public bool _isModified;
public bool IsModified public bool IsModified
{ {
get => _isModified; get => _isModified;
@ -107,7 +110,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public event Action NotifyChangesEvent; public event Action NotifyChangesEvent;
public string _profileChoose; public string _profileChoose;
public string ProfileChoose public string ProfileChoose
{ {
@ -116,7 +118,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
{ {
// When you select a profile, the settings from the profile will be applied. // When you select a profile, the settings from the profile will be applied.
// To save the settings, you still need to click the apply button // To save the settings, you still need to click the apply button
_profileChoose = value; _profileChoose = value;
LoadProfile(); LoadProfile();
OnPropertyChanged(); OnPropertyChanged();
@ -167,7 +168,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
LoadDevice(); LoadDevice();
LoadProfiles(); LoadProfiles();
DeviceIndexBeforeChange = Device; RevertDeviceId = Devices[Device].Id;
_isLoaded = true; _isLoaded = true;
_isChangeTrackingActive = true; _isChangeTrackingActive = true;
OnPropertyChanged(); OnPropertyChanged();
@ -179,6 +180,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
get => _controller; get => _controller;
set set
{ {
MarkAsChanged();
_controller = value; _controller = value;
if (_controller == -1) if (_controller == -1)
@ -216,7 +219,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
LoadInputDriver(); LoadInputDriver();
LoadProfiles(); LoadProfiles();
SetChangeTrackingActive();
} }
OnPropertyChanged(); OnPropertyChanged();
@ -258,10 +260,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
get => _device; get => _device;
set set
{ {
if (!IsModified) MarkAsChanged();
{
DeviceIndexBeforeChange = _device;
}
_device = value < 0 ? 0 : value; _device = value < 0 ? 0 : value;
@ -282,8 +281,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
} }
} }
FindPairedDevice(); FindPairedDeviceInConfigFile();
SetChangeTrackingActive();
OnPropertyChanged(); OnPropertyChanged();
NotifyChanges(); NotifyChanges();
} }
@ -292,18 +290,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public InputConfig Config { get; set; } public InputConfig Config { get; set; }
public bool _notificationView;
public bool NotificationView
{
get => _notificationView;
set
{
_notificationView = value;
OnPropertyChanged();
}
}
public InputViewModel(UserControl owner) : this() public InputViewModel(UserControl owner) : this()
{ {
if (Program.PreviewerDetached) if (Program.PreviewerDetached)
@ -363,50 +349,46 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
ConfigViewModel = new ControllerInputViewModel(this, new GamepadInputConfig(controllerInputConfig), VisualStick); ConfigViewModel = new ControllerInputViewModel(this, new GamepadInputConfig(controllerInputConfig), VisualStick);
} }
FindPairedDevice(); FindPairedDeviceInConfigFile();
} }
private void FindPairedDevice() private void FindPairedDeviceInConfigFile()
{ {
// This feature allows you to display a notification // This function allows you to output a message about the device configuration found in the file
// if a configuration is found, but the gamepad is not connected. // NOTE: if the configuration is found, we display the message "Waiting for controller connection",
if (Config != null) // but only if the id gamepad belongs to the selected player
NotificationIsVisible = Config != null && Devices.FirstOrDefault(d => d.Id == Config.Id).Id != Config.Id && Config.PlayerIndex == PlayerId;
if (NotificationIsVisible)
{ {
(DeviceType Type, string Id, string Name) activeDevice = Devices.FirstOrDefault(d => d.Id == Config.Id); if (string.IsNullOrEmpty(Config.Name))
if (activeDevice.Id != Config.Id)
{ {
// display notification when input device is turned off, and NotificationText = $"{LocaleManager.Instance[LocaleKeys.ControllerSettingsWaitingConnectDevice].Format("No information", Config.Id)}";
// if device and configuration do not match (different controllers)
NotificationView = true;
} }
else else
{ {
NotificationView = false; NotificationText = $"{LocaleManager.Instance[LocaleKeys.ControllerSettingsWaitingConnectDevice].Format(Config.Name, Config.Id)}";
} }
} }
else
{
NotificationView = false;
}
} }
private void SetChangeTrackingActive()
{
if (_isChangeTrackingActive) private void MarkAsChanged()
{ {
//If tracking is active, then allow changing the modifier
if (!IsModified && _isChangeTrackingActive)
{
RevertDeviceId = Devices[Device].Id; // Remember the device to undo changes
IsModified = true; IsModified = true;
} }
} }
public void DisableDeviceForSaving() public void UnlinkDevice()
{ {
// "Disabled" mode is available after unbinding the device // "Disabled" mode is available after unbinding the device
// NOTE: the IsModified flag to be able to apply the settings. // NOTE: the IsModified flag to be able to apply the settings.
NotificationIsVisible = false;
IsModified = true; IsModified = true;
NotificationView = false;
} }
@ -477,34 +459,31 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
private async void HandleOnGamepadDisconnected(string id) private async void HandleOnGamepadDisconnected(string id)
{ {
_isChangeTrackingActive = false; _isChangeTrackingActive = false; // Disable configuration change tracking
await Dispatcher.UIThread.InvokeAsync(() => await Dispatcher.UIThread.InvokeAsync(() =>
{ {
LoadDevices(); LoadDevices();
IsModified = true; IsModified = true;
LoadSavedConfiguration(); RevertChanges();
FindPairedDevice(); FindPairedDeviceInConfigFile();
_isChangeTrackingActive = true; _isChangeTrackingActive = true; // Enable configuration change tracking
return System.Threading.Tasks.Task.CompletedTask; return System.Threading.Tasks.Task.CompletedTask;
}); });
} }
private async void HandleOnGamepadConnected(string id) private async void HandleOnGamepadConnected(string id)
{ {
_isChangeTrackingActive = false; _isChangeTrackingActive = false; // Disable configuration change tracking
await Dispatcher.UIThread.InvokeAsync(() => await Dispatcher.UIThread.InvokeAsync(() =>
{ {
LoadDevices(); LoadDevices();
if (Config != null)
{
// Load configuration after connection if it is in the configuration file
IsModified = true; IsModified = true;
LoadSavedConfiguration(); RevertChanges();
}
_isChangeTrackingActive = true; _isChangeTrackingActive = true;// Enable configuration change tracking
}); });
} }
@ -678,12 +657,14 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
if (activeDevice.Type == DeviceType.Keyboard) if (activeDevice.Type == DeviceType.Keyboard)
{ {
string id = activeDevice.Id; string id = activeDevice.Id;
string name = activeDevice.Name;
config = new StandardKeyboardInputConfig config = new StandardKeyboardInputConfig
{ {
Version = InputConfig.CurrentVersion, Version = InputConfig.CurrentVersion,
Backend = InputBackendType.WindowKeyboard, Backend = InputBackendType.WindowKeyboard,
Id = id, Id = id,
Name = name,
ControllerType = ControllerType.ProController, ControllerType = ControllerType.ProController,
LeftJoycon = new LeftJoyconCommonConfig<Key> LeftJoycon = new LeftJoyconCommonConfig<Key>
{ {
@ -733,12 +714,14 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
bool isNintendoStyle = Devices.ToList().FirstOrDefault(x => x.Id == activeDevice.Id).Name.Contains("Nintendo"); bool isNintendoStyle = Devices.ToList().FirstOrDefault(x => x.Id == activeDevice.Id).Name.Contains("Nintendo");
string id = activeDevice.Id.Split(" ")[0]; string id = activeDevice.Id.Split(" ")[0];
string name = activeDevice.Name;
config = new StandardControllerInputConfig config = new StandardControllerInputConfig
{ {
Version = InputConfig.CurrentVersion, Version = InputConfig.CurrentVersion,
Backend = InputBackendType.GamepadSDL2, Backend = InputBackendType.GamepadSDL2,
Id = id, Id = id,
Name = name,
ControllerType = ControllerType.ProController, ControllerType = ControllerType.ProController,
DeadzoneLeft = 0.1f, DeadzoneLeft = 0.1f,
DeadzoneRight = 0.1f, DeadzoneRight = 0.1f,
@ -810,8 +793,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public void LoadProfileButton() public void LoadProfileButton()
{ {
IsModified = true;
LoadProfile(); LoadProfile();
IsModified = true;
} }
public async void LoadProfile() public async void LoadProfile()
@ -865,12 +848,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
{ {
_isLoaded = false; _isLoaded = false;
config.Id = null; // ignore device IDs (there is no longer a need to store device IDs for presets due to their independence from devices) config.Id = Config.Id; // Set current device id instead of changing device(independent profiles)
LoadConfiguration(config); LoadConfiguration(config);
// This line of code hard-links profiles to controllers, the commented line allows profiles to be applied to all controllers //LoadDevice(); This line of code hard-links profiles to controllers, the commented line allows profiles to be applied to all controllers
// LoadDevice();
_isLoaded = true; _isLoaded = true;
@ -880,6 +862,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public async void SaveProfile() public async void SaveProfile()
{ {
if (Device == 0) if (Device == 0)
{ {
return; return;
@ -930,6 +913,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]); await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]);
} }
} }
} }
public async void RemoveProfile() public async void RemoveProfile()
@ -961,22 +945,13 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
} }
} }
public void LoadSavedConfiguration() public void RevertChanges()
{ {
// Restores settings and sets the previously selected device to the last saved state Device = Devices.ToList().FindIndex(d => d.Id == RevertDeviceId);
// NOTE: The current order allows the configuration and device to be loaded correctly until the configuration is changed.
if (IsModified) // Fixes random gamepad appearance in "disabled" option
{
Device = DeviceIndexBeforeChange;
LoadDevice(); LoadDevice();
LoadConfiguration(); LoadConfiguration();
IsModified = false;
OnPropertyChanged(); OnPropertyChanged();
} IsModified = false;
} }
public void Save() public void Save()
@ -988,7 +963,9 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
} }
IsModified = false; IsModified = false;
DeviceIndexBeforeChange = Device;
RevertDeviceId = Devices[Device].Id; // Remember selected device after saving
List <InputConfig> newConfig = []; List <InputConfig> newConfig = [];
newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value); newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value);
@ -1019,6 +996,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
: (ConfigViewModel as ControllerInputViewModel).Config.GetConfig(); : (ConfigViewModel as ControllerInputViewModel).Config.GetConfig();
config.ControllerType = Controllers[_controller].Type; config.ControllerType = Controllers[_controller].Type;
config.PlayerIndex = _playerId; config.PlayerIndex = _playerId;
config.Name = device.Name;
int i = newConfig.FindIndex(x => x.PlayerIndex == PlayerId); int i = newConfig.FindIndex(x => x.PlayerIndex == PlayerId);
if (i == -1) if (i == -1)

View File

@ -3,7 +3,6 @@ using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Media.Imaging;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
@ -17,6 +16,7 @@ using LibHac.Ns;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
using Ryujinx.Ava.Systems;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.Models;
@ -46,7 +46,6 @@ using System.Collections.ObjectModel;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Key = Ryujinx.Input.Key; using Key = Ryujinx.Input.Key;

View File

@ -16,11 +16,12 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
[ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix; [ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
[ObservableProperty] private bool _nifmDisableIsAnyInternetRequestAccepted = ConfigurationState.Instance.Hacks.DisableNifmIsAnyInternetRequestAccepted;
public static string Xc2MenuFixTooltip { get; } = Lambda.String(sb => public static string Xc2MenuFixTooltip { get; } = Lambda.String(sb =>
{ {
sb.AppendLine( sb.AppendLine(
"This fix applies a 2ms delay (via 'Thread.Sleep(2)') every time the game tries to read data from the emulated Switch filesystem.") "This hack applies a 2ms delay (via 'Thread.Sleep(2)') every time the game tries to read data from the emulated Switch filesystem.")
.AppendLine(); .AppendLine();
sb.AppendLine("From the issue on GitHub:").AppendLine(); sb.AppendLine("From the issue on GitHub:").AppendLine();
@ -29,5 +30,14 @@ namespace Ryujinx.Ava.UI.ViewModels
"there is a low chance that the game will softlock, " + "there is a low chance that the game will softlock, " +
"the submenu won't show up, while background music is still there."); "the submenu won't show up, while background music is still there.");
}); });
public static string NifmDisableIsAnyInternetRequestAcceptedTooltip { get; } = Lambda.String(sb =>
{
sb.AppendLine(
"This hack simply sets 'IsAnyInternetRequestAccepted' to 'false' when initializing the Nifm IGeneralService.")
.AppendLine();
sb.Append("Lets DOOM 2016 go in game.");
});
} }
} }

View File

@ -757,6 +757,8 @@ namespace Ryujinx.Ava.UI.ViewModels
// Dirty Hacks // Dirty Hacks
config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFix; config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFix;
config.Hacks.DisableNifmIsAnyInternetRequestAccepted.Value =
DirtyHacks.NifmDisableIsAnyInternetRequestAccepted;
config.ToFileFormat().SaveConfig(Program.ConfigurationPath); config.ToFileFormat().SaveConfig(Program.ConfigurationPath);

View File

@ -16,7 +16,7 @@ using static Ryujinx.Common.Utilities.XCIFileTrimmer;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class XCITrimmerViewModel : BaseModel public class XciTrimmerViewModel : BaseModel
{ {
private const long _bytesPerMB = 1024 * 1024; private const long _bytesPerMB = 1024 * 1024;
private enum ProcessingMode private enum ProcessingMode
@ -46,7 +46,7 @@ namespace Ryujinx.Ava.UI.ViewModels
private SortField _sortField = SortField.Name; private SortField _sortField = SortField.Name;
private bool _sortAscending = true; private bool _sortAscending = true;
public XCITrimmerViewModel(MainWindowViewModel mainWindowViewModel) public XciTrimmerViewModel(MainWindowViewModel mainWindowViewModel)
{ {
_logger = new XCITrimmerLog.TrimmerWindow(this); _logger = new XCITrimmerLog.TrimmerWindow(this);
_mainWindowViewModel = mainWindowViewModel; _mainWindowViewModel = mainWindowViewModel;
@ -254,9 +254,9 @@ namespace Ryujinx.Ava.UI.ViewModels
private class CompareXCITrimmerFiles : IComparer<XCITrimmerFileModel> private class CompareXCITrimmerFiles : IComparer<XCITrimmerFileModel>
{ {
private XCITrimmerViewModel _viewModel; private XciTrimmerViewModel _viewModel;
public CompareXCITrimmerFiles(XCITrimmerViewModel ViewModel) public CompareXCITrimmerFiles(XciTrimmerViewModel ViewModel)
{ {
_viewModel = ViewModel; _viewModel = ViewModel;
} }

View File

@ -1,5 +1,5 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.UI.Windows.AboutWindow" x:Class="Ryujinx.Ava.UI.Views.Dialog.AboutView"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

View File

@ -1,8 +1,6 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Styling;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;
@ -13,11 +11,11 @@ using Ryujinx.Common.Helper;
using System.Threading.Tasks; using System.Threading.Tasks;
using Button = Avalonia.Controls.Button; using Button = Avalonia.Controls.Button;
namespace Ryujinx.Ava.UI.Windows namespace Ryujinx.Ava.UI.Views.Dialog
{ {
public partial class AboutWindow : RyujinxControl<AboutWindowViewModel> public partial class AboutView : RyujinxControl<AboutWindowViewModel>
{ {
public AboutWindow() public AboutView()
{ {
InitializeComponent(); InitializeComponent();
@ -34,7 +32,7 @@ namespace Ryujinx.Ava.UI.Windows
PrimaryButtonText = string.Empty, PrimaryButtonText = string.Empty,
SecondaryButtonText = string.Empty, SecondaryButtonText = string.Empty,
CloseButtonText = LocaleManager.Instance[LocaleKeys.UserProfilesClose], CloseButtonText = LocaleManager.Instance[LocaleKeys.UserProfilesClose],
Content = new AboutWindow { ViewModel = viewModel } Content = new AboutView { ViewModel = viewModel }
}; };
await ContentDialogHelper.ShowAsync(contentDialog.ApplyStyles()); await ContentDialogHelper.ShowAsync(contentDialog.ApplyStyles());

View File

@ -7,7 +7,7 @@
xmlns:ui="using:FluentAvalonia.UI.Controls" xmlns:ui="using:FluentAvalonia.UI.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Ryujinx.Ava.UI.Views.Misc.ApplicationDataView" x:Class="Ryujinx.Ava.UI.Views.Dialog.ApplicationDataView"
x:DataType="viewModels:ApplicationDataViewModel"> x:DataType="viewModels:ApplicationDataViewModel">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Image Margin="0" <Image Margin="0"

View File

@ -12,7 +12,7 @@ using Ryujinx.Ava.Systems.AppLibrary;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Views.Misc namespace Ryujinx.Ava.UI.Views.Dialog
{ {
public partial class ApplicationDataView : RyujinxControl<ApplicationDataViewModel> public partial class ApplicationDataView : RyujinxControl<ApplicationDataViewModel>
{ {

View File

@ -7,7 +7,7 @@
xmlns:models="using:Ryujinx.Ava.Common.Models" xmlns:models="using:Ryujinx.Ava.Common.Models"
xmlns:viewModels="using:Ryujinx.Ava.UI.ViewModels" xmlns:viewModels="using:Ryujinx.Ava.UI.ViewModels"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Ryujinx.Ava.UI.Views.Misc.DlcSelectView" x:Class="Ryujinx.Ava.UI.Views.Dialog.DlcSelectView"
x:DataType="viewModels:DlcSelectViewModel"> x:DataType="viewModels:DlcSelectViewModel">
<Grid RowDefinitions="*,Auto,*"> <Grid RowDefinitions="*,Auto,*">
<TextBlock <TextBlock

View File

@ -1,6 +1,4 @@
using Avalonia.Controls; using FluentAvalonia.UI.Controls;
using Avalonia.Styling;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;
@ -9,7 +7,7 @@ using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.AppLibrary;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Views.Misc namespace Ryujinx.Ava.UI.Views.Dialog
{ {
public partial class DlcSelectView : RyujinxControl<DlcSelectViewModel> public partial class DlcSelectView : RyujinxControl<DlcSelectViewModel>
{ {

View File

@ -1,5 +1,5 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.UI.Windows.DownloadableContentManagerWindow" x:Class="Ryujinx.Ava.UI.Views.Dialog.DownloadableContentManagerView"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

View File

@ -6,26 +6,16 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Common.Helper; using Ryujinx.Common.Helper;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Windows namespace Ryujinx.Ava.UI.Views.Dialog
{ {
public partial class DownloadableContentManagerWindow : UserControl public partial class DownloadableContentManagerView : RyujinxControl<DownloadableContentManagerViewModel>
{ {
public DownloadableContentManagerViewModel ViewModel; public DownloadableContentManagerView()
public DownloadableContentManagerWindow()
{ {
DataContext = this;
InitializeComponent();
}
public DownloadableContentManagerWindow(ApplicationLibrary applicationLibrary, ApplicationData applicationData)
{
DataContext = ViewModel = new DownloadableContentManagerViewModel(applicationLibrary, applicationData);
InitializeComponent(); InitializeComponent();
} }
@ -36,8 +26,11 @@ namespace Ryujinx.Ava.UI.Windows
PrimaryButtonText = string.Empty, PrimaryButtonText = string.Empty,
SecondaryButtonText = string.Empty, SecondaryButtonText = string.Empty,
CloseButtonText = string.Empty, CloseButtonText = string.Empty,
Content = new DownloadableContentManagerWindow(applicationLibrary, applicationData),
Title = string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowTitle], applicationData.Name, applicationData.IdBaseString), Title = string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowTitle], applicationData.Name, applicationData.IdBaseString),
Content = new DownloadableContentManagerView
{
ViewModel = new DownloadableContentManagerViewModel(applicationLibrary, applicationData)
}
}; };
Style bottomBorder = new(x => x.OfType<Grid>().Name("DialogSpace").Child().OfType<Border>()); Style bottomBorder = new(x => x.OfType<Grid>().Name("DialogSpace").Child().OfType<Border>());

View File

@ -10,7 +10,7 @@
Width="500" Width="500"
Height="380" Height="380"
mc:Ignorable="d" mc:Ignorable="d"
x:Class="Ryujinx.Ava.UI.Windows.ModManagerWindow" x:Class="Ryujinx.Ava.UI.Views.Dialog.ModManagerView"
x:CompileBindings="True" x:CompileBindings="True"
x:DataType="viewModels:ModManagerViewModel" x:DataType="viewModels:ModManagerViewModel"
Focusable="True"> Focusable="True">

View File

@ -7,27 +7,17 @@ using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Common.Helper; using Ryujinx.Common.Helper;
using System.Threading.Tasks; using System.Threading.Tasks;
using Button = Avalonia.Controls.Button; using Button = Avalonia.Controls.Button;
namespace Ryujinx.Ava.UI.Windows namespace Ryujinx.Ava.UI.Views.Dialog
{ {
public partial class ModManagerWindow : UserControl public partial class ModManagerView : RyujinxControl<ModManagerViewModel>
{ {
public readonly ModManagerViewModel ViewModel; public ModManagerView()
public ModManagerWindow()
{ {
DataContext = this;
InitializeComponent();
}
public ModManagerWindow(ulong titleId, ulong titleIdBase, ApplicationLibrary applicationLibrary)
{
DataContext = ViewModel = new ModManagerViewModel(titleId, titleIdBase, applicationLibrary);
InitializeComponent(); InitializeComponent();
} }
@ -38,7 +28,10 @@ namespace Ryujinx.Ava.UI.Windows
PrimaryButtonText = string.Empty, PrimaryButtonText = string.Empty,
SecondaryButtonText = string.Empty, SecondaryButtonText = string.Empty,
CloseButtonText = string.Empty, CloseButtonText = string.Empty,
Content = new ModManagerWindow(titleId, titleIdBase, appLibrary), Content = new ModManagerView
{
ViewModel = new ModManagerViewModel(titleId, titleIdBase, appLibrary)
},
Title = string.Format(LocaleManager.Instance[LocaleKeys.ModWindowTitle], titleName, titleId.ToString("X16")), Title = string.Format(LocaleManager.Instance[LocaleKeys.ModWindowTitle], titleName, titleId.ToString("X16")),
}; };

View File

@ -1,5 +1,5 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.UI.Windows.TitleUpdateWindow" x:Class="Ryujinx.Ava.UI.Views.Dialog.TitleUpdateManagerView"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"

View File

@ -6,26 +6,16 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Common.Helper; using Ryujinx.Common.Helper;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Windows namespace Ryujinx.Ava.UI.Views.Dialog
{ {
public partial class TitleUpdateWindow : UserControl public partial class TitleUpdateManagerView : RyujinxControl<TitleUpdateViewModel>
{ {
public readonly TitleUpdateViewModel ViewModel; public TitleUpdateManagerView()
public TitleUpdateWindow()
{ {
DataContext = this;
InitializeComponent();
}
public TitleUpdateWindow(ApplicationLibrary applicationLibrary, ApplicationData applicationData)
{
DataContext = ViewModel = new TitleUpdateViewModel(applicationLibrary, applicationData);
InitializeComponent(); InitializeComponent();
} }
@ -36,8 +26,11 @@ namespace Ryujinx.Ava.UI.Windows
PrimaryButtonText = string.Empty, PrimaryButtonText = string.Empty,
SecondaryButtonText = string.Empty, SecondaryButtonText = string.Empty,
CloseButtonText = string.Empty, CloseButtonText = string.Empty,
Content = new TitleUpdateWindow(applicationLibrary, applicationData),
Title = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.GameUpdateWindowHeading, applicationData.Name, applicationData.IdBaseString), Title = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.GameUpdateWindowHeading, applicationData.Name, applicationData.IdBaseString),
Content = new TitleUpdateManagerView
{
ViewModel = new TitleUpdateViewModel(applicationLibrary, applicationData)
}
}; };
Style bottomBorder = new(x => x.OfType<Grid>().Name("DialogSpace").Child().OfType<Border>()); Style bottomBorder = new(x => x.OfType<Grid>().Name("DialogSpace").Child().OfType<Border>());

View File

@ -1,5 +1,5 @@
<UserControl <UserControl
x:Class="Ryujinx.Ava.UI.Windows.XCITrimmerWindow" x:Class="Ryujinx.Ava.UI.Views.Dialog.XciTrimmerView"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
@ -10,7 +10,7 @@
xmlns:models="clr-namespace:Ryujinx.Ava.Common.Models" xmlns:models="clr-namespace:Ryujinx.Ava.Common.Models"
Width="700" Width="700"
Height="600" Height="600"
x:DataType="viewModels:XCITrimmerViewModel" x:DataType="viewModels:XciTrimmerViewModel"
Focusable="True" Focusable="True"
mc:Ignorable="d"> mc:Ignorable="d">
<Grid Margin="20 0 20 0" RowDefinitions="Auto,Auto,*,Auto,Auto"> <Grid Margin="20 0 20 0" RowDefinitions="Auto,Auto,*,Auto,Auto">
@ -151,7 +151,7 @@
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
VerticalAlignment="Center" VerticalAlignment="Center"
CornerRadius="5" CornerRadius="5"
IsVisible="{Binding $parent[UserControl].((viewModels:XCITrimmerViewModel)DataContext).Processing}" IsVisible="{Binding $parent[UserControl].((viewModels:XciTrimmerViewModel)DataContext).Processing}"
Maximum="100" Maximum="100"
Minimum="0" Minimum="0"
Value="{Binding PercentageProgress}" /> Value="{Binding PercentageProgress}" />

View File

@ -4,27 +4,17 @@ using Avalonia.Styling;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Windows namespace Ryujinx.Ava.UI.Views.Dialog
{ {
public partial class XCITrimmerWindow : UserControl public partial class XciTrimmerView : RyujinxControl<XciTrimmerViewModel>
{ {
public XCITrimmerViewModel ViewModel; public XciTrimmerView()
public XCITrimmerWindow()
{ {
DataContext = this;
InitializeComponent();
}
public XCITrimmerWindow(MainWindowViewModel mainWindowViewModel)
{
DataContext = ViewModel = new XCITrimmerViewModel(mainWindowViewModel);
InitializeComponent(); InitializeComponent();
} }
@ -35,7 +25,10 @@ namespace Ryujinx.Ava.UI.Windows
PrimaryButtonText = string.Empty, PrimaryButtonText = string.Empty,
SecondaryButtonText = string.Empty, SecondaryButtonText = string.Empty,
CloseButtonText = string.Empty, CloseButtonText = string.Empty,
Content = new XCITrimmerWindow(RyujinxApp.MainWindow.ViewModel), Content = new XciTrimmerView
{
ViewModel = new XciTrimmerViewModel(RyujinxApp.MainWindow.ViewModel)
},
Title = LocaleManager.Instance[LocaleKeys.XCITrimmerWindowTitle] Title = LocaleManager.Instance[LocaleKeys.XCITrimmerWindowTitle]
}; };
@ -70,7 +63,7 @@ namespace Ryujinx.Ava.UI.Windows
public void Sort_Checked(object sender, RoutedEventArgs args) public void Sort_Checked(object sender, RoutedEventArgs args)
{ {
if (sender is RadioButton { Tag: string sortField }) if (sender is RadioButton { Tag: string sortField })
ViewModel.SortingField = Enum.Parse<XCITrimmerViewModel.SortField>(sortField); ViewModel.SortingField = Enum.Parse<XciTrimmerViewModel.SortField>(sortField);
} }
public void Order_Checked(object sender, RoutedEventArgs args) public void Order_Checked(object sender, RoutedEventArgs args)

View File

@ -75,7 +75,7 @@
Margin="5,0,0,0" Margin="5,0,0,0"
VerticalAlignment="Center" VerticalAlignment="Center"
ToolTip.Tip="{ext:Locale ControllerSettingsCancelCurrentChangesToolTip}" ToolTip.Tip="{ext:Locale ControllerSettingsCancelCurrentChangesToolTip}"
Command="{Binding LoadSavedConfiguration}"> Command="{Binding RevertChanges}">
<ui:SymbolIcon <ui:SymbolIcon
Symbol="Undo" Symbol="Undo"
FontSize="15" FontSize="15"
@ -201,20 +201,20 @@
</Grid> </Grid>
</Grid> </Grid>
</StackPanel> </StackPanel>
<ContentControl IsVisible="{Binding NotificationView}"> <ContentControl IsVisible="{Binding NotificationIsVisible}">
<ContentControl.Content> <ContentControl.Content>
<StackPanel> <StackPanel>
<TextBlock <TextBlock
Margin="5,20,0,0" Margin="5,20,0,0"
Text="{ext:Locale ControllerSettingsDisableDeviceForSaving}" /> Text="{Binding NotificationText}" />
<Button <Button
MinWidth="0" MinWidth="0"
Width="90" Width="90"
Height="27" Height="27"
Margin="5,10,0,0" Margin="0,10,0,0"
VerticalAlignment="Center" VerticalAlignment="Center"
Command="{Binding DisableDeviceForSaving}"> Command="{Binding UnlinkDevice}">
<TextBlock <TextBlock
Text="{ext:Locale ControllerSettingsUnlink}" Text="{ext:Locale ControllerSettingsUnlink}"
VerticalAlignment="Center" VerticalAlignment="Center"

View File

@ -184,11 +184,6 @@ namespace Ryujinx.Ava.UI.Views.Input
} }
} }
private void FlagInputConfigChanged()
{
(DataContext as KeyboardInputViewModel)!.ParentModel.IsModified = true;
}
private void MouseClick(object sender, PointerPressedEventArgs e) private void MouseClick(object sender, PointerPressedEventArgs e)
{ {
bool shouldUnbind = e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed; bool shouldUnbind = e.GetCurrentPoint(this).Properties.IsMiddleButtonPressed;
@ -207,47 +202,45 @@ namespace Ryujinx.Ava.UI.Views.Input
private void DeleteBind() private void DeleteBind()
{ {
if (DataContext is not KeyboardInputViewModel viewModel)
return;
if (_currentAssigner != null) if (_currentAssigner != null)
{ {
Dictionary<string, Action> buttonActions = new Dictionary<string, Action> Dictionary<string, Action> buttonActions = new Dictionary<string, Action>
{ {
{ "ButtonZl", () => viewModel.Config.ButtonZl = Key.Unbound }, { "ButtonZl", () => ViewModel.Config.ButtonZl = Key.Unbound },
{ "ButtonL", () => viewModel.Config.ButtonL = Key.Unbound }, { "ButtonL", () => ViewModel.Config.ButtonL = Key.Unbound },
{ "ButtonMinus", () => viewModel.Config.ButtonMinus = Key.Unbound }, { "ButtonMinus", () => ViewModel.Config.ButtonMinus = Key.Unbound },
{ "LeftStickButton", () => viewModel.Config.LeftStickButton = Key.Unbound }, { "LeftStickButton", () => ViewModel.Config.LeftStickButton = Key.Unbound },
{ "LeftStickUp", () => viewModel.Config.LeftStickUp = Key.Unbound }, { "LeftStickUp", () => ViewModel.Config.LeftStickUp = Key.Unbound },
{ "LeftStickDown", () => viewModel.Config.LeftStickDown = Key.Unbound }, { "LeftStickDown", () => ViewModel.Config.LeftStickDown = Key.Unbound },
{ "LeftStickRight", () => viewModel.Config.LeftStickRight = Key.Unbound }, { "LeftStickRight", () => ViewModel.Config.LeftStickRight = Key.Unbound },
{ "LeftStickLeft", () => viewModel.Config.LeftStickLeft = Key.Unbound }, { "LeftStickLeft", () => ViewModel.Config.LeftStickLeft = Key.Unbound },
{ "DpadUp", () => viewModel.Config.DpadUp = Key.Unbound }, { "DpadUp", () => ViewModel.Config.DpadUp = Key.Unbound },
{ "DpadDown", () => viewModel.Config.DpadDown = Key.Unbound }, { "DpadDown", () => ViewModel.Config.DpadDown = Key.Unbound },
{ "DpadLeft", () => viewModel.Config.DpadLeft = Key.Unbound }, { "DpadLeft", () => ViewModel.Config.DpadLeft = Key.Unbound },
{ "DpadRight", () => viewModel.Config.DpadRight = Key.Unbound }, { "DpadRight", () => ViewModel.Config.DpadRight = Key.Unbound },
{ "LeftButtonSr", () => viewModel.Config.LeftButtonSr = Key.Unbound }, { "LeftButtonSr", () => ViewModel.Config.LeftButtonSr = Key.Unbound },
{ "LeftButtonSl", () => viewModel.Config.LeftButtonSl = Key.Unbound }, { "LeftButtonSl", () => ViewModel.Config.LeftButtonSl = Key.Unbound },
{ "RightButtonSr", () => viewModel.Config.RightButtonSr = Key.Unbound }, { "RightButtonSr", () => ViewModel.Config.RightButtonSr = Key.Unbound },
{ "RightButtonSl", () => viewModel.Config.RightButtonSl = Key.Unbound }, { "RightButtonSl", () => ViewModel.Config.RightButtonSl = Key.Unbound },
{ "ButtonZr", () => viewModel.Config.ButtonZr = Key.Unbound }, { "ButtonZr", () => ViewModel.Config.ButtonZr = Key.Unbound },
{ "ButtonR", () => viewModel.Config.ButtonR = Key.Unbound }, { "ButtonR", () => ViewModel.Config.ButtonR = Key.Unbound },
{ "ButtonPlus", () => viewModel.Config.ButtonPlus = Key.Unbound }, { "ButtonPlus", () => ViewModel.Config.ButtonPlus = Key.Unbound },
{ "ButtonA", () => viewModel.Config.ButtonA = Key.Unbound }, { "ButtonA", () => ViewModel.Config.ButtonA = Key.Unbound },
{ "ButtonB", () => viewModel.Config.ButtonB = Key.Unbound }, { "ButtonB", () => ViewModel.Config.ButtonB = Key.Unbound },
{ "ButtonX", () => viewModel.Config.ButtonX = Key.Unbound }, { "ButtonX", () => ViewModel.Config.ButtonX = Key.Unbound },
{ "ButtonY", () => viewModel.Config.ButtonY = Key.Unbound }, { "ButtonY", () => ViewModel.Config.ButtonY = Key.Unbound },
{ "RightStickButton", () => viewModel.Config.RightStickButton = Key.Unbound }, { "RightStickButton", () => ViewModel.Config.RightStickButton = Key.Unbound },
{ "RightStickUp", () => viewModel.Config.RightStickUp = Key.Unbound }, { "RightStickUp", () => ViewModel.Config.RightStickUp = Key.Unbound },
{ "RightStickDown", () => viewModel.Config.RightStickDown = Key.Unbound }, { "RightStickDown", () => ViewModel.Config.RightStickDown = Key.Unbound },
{ "RightStickRight", () => viewModel.Config.RightStickRight = Key.Unbound }, { "RightStickRight", () => ViewModel.Config.RightStickRight = Key.Unbound },
{ "RightStickLeft", () => viewModel.Config.RightStickLeft = Key.Unbound } { "RightStickLeft", () => ViewModel.Config.RightStickLeft = Key.Unbound }
}; };
if (buttonActions.TryGetValue(_currentAssigner.ToggledButton.Name, out Action action)) if (buttonActions.TryGetValue(_currentAssigner.ToggledButton.Name, out Action action))
{ {
action(); action();
FlagInputConfigChanged(); ViewModel.ParentModel.IsModified = true;
} }
} }
} }

View File

@ -1,5 +1,4 @@
using Avalonia; using Avalonia;
using Avalonia.Controls;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;

View File

@ -1,4 +1,3 @@
using Avalonia.Controls;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;

View File

@ -1,4 +1,3 @@
using Avalonia.Controls;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;

View File

@ -13,7 +13,7 @@ using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities; using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Views.Misc; using Ryujinx.Ava.UI.Views.Dialog;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Helper; using Ryujinx.Common.Helper;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
@ -46,8 +46,8 @@ namespace Ryujinx.Ava.UI.Views.Main
CheatManagerMenuItem.Command = Commands.CreateSilentFail(OpenCheatManagerForCurrentApp); CheatManagerMenuItem.Command = Commands.CreateSilentFail(OpenCheatManagerForCurrentApp);
InstallFileTypesMenuItem.Command = Commands.Create(InstallFileTypes); InstallFileTypesMenuItem.Command = Commands.Create(InstallFileTypes);
UninstallFileTypesMenuItem.Command = Commands.Create(UninstallFileTypes); UninstallFileTypesMenuItem.Command = Commands.Create(UninstallFileTypes);
XciTrimmerMenuItem.Command = Commands.Create(XCITrimmerWindow.Show); XciTrimmerMenuItem.Command = Commands.Create(XciTrimmerView.Show);
AboutWindowMenuItem.Command = Commands.Create(AboutWindow.Show); AboutWindowMenuItem.Command = Commands.Create(AboutView.Show);
CompatibilityListMenuItem.Command = Commands.Create(() => CompatibilityListWindow.Show()); CompatibilityListMenuItem.Command = Commands.Create(() => CompatibilityListWindow.Show());
UpdateMenuItem.Command = MainWindowViewModel.UpdateCommand; UpdateMenuItem.Command = MainWindowViewModel.UpdateCommand;

View File

@ -1,5 +1,4 @@
using Avalonia; using Avalonia;
using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Threading; using Avalonia.Threading;

View File

@ -29,7 +29,7 @@
<TextBlock <TextBlock
Foreground="{DynamicResource SecondaryTextColor}" Foreground="{DynamicResource SecondaryTextColor}"
TextDecorations="Underline" TextDecorations="Underline"
Text="Highly specific hacks &amp; tricks to alleviate performance issues, crashing, or freezing. Will cause issues." /> Text="Highly specific hacks &amp; tricks to alleviate performance issues, crashing, or freezing. Can cause issues." />
<StackPanel <StackPanel
Margin="0,10,0,0" Margin="0,10,0,0"
Orientation="Horizontal" Orientation="Horizontal"
@ -43,6 +43,18 @@
Text="Xenoblade Chronicles 2 Menu Softlock Fix" /> Text="Xenoblade Chronicles 2 Menu Softlock Fix" />
</StackPanel> </StackPanel>
<Separator/> <Separator/>
<StackPanel
Margin="0,10,0,0"
Orientation="Horizontal"
HorizontalAlignment="Center"
ToolTip.Tip="{Binding DirtyHacks.NifmDisableIsAnyInternetRequestAcceptedTooltip}">
<CheckBox
Margin="0"
IsChecked="{Binding DirtyHacks.NifmDisableIsAnyInternetRequestAccepted}"/>
<TextBlock
VerticalAlignment="Center"
Text="Disable IsAnyInternetRequestAccepted" />
</StackPanel>
</StackPanel> </StackPanel>
</Border> </Border>
</ScrollViewer> </ScrollViewer>

View File

@ -3,7 +3,9 @@ using Avalonia.Controls.Primitives;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.LogicalTree; using Avalonia.LogicalTree;
using Avalonia.Threading;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Input; using Ryujinx.Input;
@ -15,7 +17,7 @@ using Key = Ryujinx.Common.Configuration.Hid.Key;
namespace Ryujinx.Ava.UI.Views.Settings namespace Ryujinx.Ava.UI.Views.Settings
{ {
public partial class SettingsHotkeysView : UserControl public partial class SettingsHotkeysView : RyujinxControl<SettingsViewModel>
{ {
private ButtonKeyAssigner _currentAssigner; private ButtonKeyAssigner _currentAssigner;
private readonly IGamepadDriver _avaloniaKeyboardDriver; private readonly IGamepadDriver _avaloniaKeyboardDriver;
@ -115,45 +117,49 @@ namespace Ryujinx.Ava.UI.Views.Settings
{ {
if (e.ButtonValue.HasValue) if (e.ButtonValue.HasValue)
{ {
SettingsViewModel viewModel = (DataContext) as SettingsViewModel;
Button buttonValue = e.ButtonValue.Value; Button buttonValue = e.ButtonValue.Value;
Dispatcher.UIThread.Post(() =>
{
switch (button.Name) switch (button.Name)
{ {
case "ToggleVSyncMode": case "ToggleVSyncMode":
viewModel.KeyboardHotkey.ToggleVSyncMode = buttonValue.AsHidType<Key>(); ViewModel.KeyboardHotkey.ToggleVSyncMode = buttonValue.AsHidType<Key>();
break; break;
case "Screenshot": case "Screenshot":
viewModel.KeyboardHotkey.Screenshot = buttonValue.AsHidType<Key>(); ViewModel.KeyboardHotkey.Screenshot = buttonValue.AsHidType<Key>();
break; break;
case "ShowUI": case "ShowUI":
viewModel.KeyboardHotkey.ShowUI = buttonValue.AsHidType<Key>(); ViewModel.KeyboardHotkey.ShowUI = buttonValue.AsHidType<Key>();
break; break;
case "Pause": case "Pause":
viewModel.KeyboardHotkey.Pause = buttonValue.AsHidType<Key>(); ViewModel.KeyboardHotkey.Pause = buttonValue.AsHidType<Key>();
break; break;
case "ToggleMute": case "ToggleMute":
viewModel.KeyboardHotkey.ToggleMute = buttonValue.AsHidType<Key>(); ViewModel.KeyboardHotkey.ToggleMute = buttonValue.AsHidType<Key>();
break; break;
case "ResScaleUp": case "ResScaleUp":
viewModel.KeyboardHotkey.ResScaleUp = buttonValue.AsHidType<Key>(); ViewModel.KeyboardHotkey.ResScaleUp = buttonValue.AsHidType<Key>();
break; break;
case "ResScaleDown": case "ResScaleDown":
viewModel.KeyboardHotkey.ResScaleDown = buttonValue.AsHidType<Key>(); ViewModel.KeyboardHotkey.ResScaleDown = buttonValue.AsHidType<Key>();
break; break;
case "VolumeUp": case "VolumeUp":
viewModel.KeyboardHotkey.VolumeUp = buttonValue.AsHidType<Key>(); ViewModel.KeyboardHotkey.VolumeUp = buttonValue.AsHidType<Key>();
break; break;
case "VolumeDown": case "VolumeDown":
viewModel.KeyboardHotkey.VolumeDown = buttonValue.AsHidType<Key>(); ViewModel.KeyboardHotkey.VolumeDown = buttonValue.AsHidType<Key>();
break; break;
case "CustomVSyncIntervalIncrement": case "CustomVSyncIntervalIncrement":
viewModel.KeyboardHotkey.CustomVSyncIntervalIncrement = buttonValue.AsHidType<Key>(); ViewModel.KeyboardHotkey.CustomVSyncIntervalIncrement =
buttonValue.AsHidType<Key>();
break; break;
case "CustomVSyncIntervalDecrement": case "CustomVSyncIntervalDecrement":
viewModel.KeyboardHotkey.CustomVSyncIntervalDecrement = buttonValue.AsHidType<Key>(); ViewModel.KeyboardHotkey.CustomVSyncIntervalDecrement =
buttonValue.AsHidType<Key>();
break; break;
} }
});
} }
}; };

View File

@ -1,16 +1,14 @@
using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using System; using System;
namespace Ryujinx.Ava.UI.Views.Settings namespace Ryujinx.Ava.UI.Views.Settings
{ {
public partial class SettingsNetworkView : UserControl public partial class SettingsNetworkView : RyujinxControl<SettingsViewModel>
{ {
private readonly Random _random; private readonly Random _random;
public SettingsViewModel ViewModel;
public SettingsNetworkView() public SettingsNetworkView()
{ {
_random = new Random(); _random = new Random();

View File

@ -1,13 +1,12 @@
using Avalonia.Controls; using Avalonia.Controls;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using TimeZone = Ryujinx.Ava.UI.Models.TimeZone; using TimeZone = Ryujinx.Ava.UI.Models.TimeZone;
namespace Ryujinx.Ava.UI.Views.Settings namespace Ryujinx.Ava.UI.Views.Settings
{ {
public partial class SettingsSystemView : UserControl public partial class SettingsSystemView : RyujinxControl<SettingsViewModel>
{ {
public SettingsViewModel ViewModel;
public SettingsSystemView() public SettingsSystemView()
{ {
InitializeComponent(); InitializeComponent();

View File

@ -3,10 +3,10 @@ using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Gommon; using Gommon;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Utilities; using Ryujinx.Ava.Utilities;
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -14,20 +14,18 @@ using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Views.Settings namespace Ryujinx.Ava.UI.Views.Settings
{ {
public partial class SettingsUiView : UserControl public partial class SettingsUiView : RyujinxControl<SettingsViewModel>
{ {
public SettingsViewModel ViewModel;
public SettingsUiView() public SettingsUiView()
{ {
InitializeComponent(); InitializeComponent();
AddGameDirButton.Command = AddGameDirButton.Command =
Commands.Create(() => AddDirButton(GameDirPathBox, ViewModel.GameDirectories, true)); Commands.Create(() => AddDirButton(GameDirPathBox, ViewModel.GameDirectories));
AddAutoloadDirButton.Command = AddAutoloadDirButton.Command =
Commands.Create(() => AddDirButton(AutoloadDirPathBox, ViewModel.AutoloadDirectories, false)); Commands.Create(() => AddDirButton(AutoloadDirPathBox, ViewModel.AutoloadDirectories));
} }
private async Task AddDirButton(TextBox addDirBox, AvaloniaList<string> directories, bool isGameList) private async Task AddDirButton(TextBox addDirBox, AvaloniaList<string> directories)
{ {
string path = addDirBox.Text; string path = addDirBox.Text;

View File

@ -8,7 +8,6 @@ using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.Models;
using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Account.Acc;
using System;
using UserProfile = Ryujinx.Ava.UI.Models.UserProfile; using UserProfile = Ryujinx.Ava.UI.Models.UserProfile;
namespace Ryujinx.Ava.UI.Views.User namespace Ryujinx.Ava.UI.Views.User

View File

@ -1,4 +1,3 @@
using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Navigation; using FluentAvalonia.UI.Navigation;

View File

@ -1,4 +1,3 @@
using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Threading; using Avalonia.Threading;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;

View File

@ -1,10 +1,8 @@
using Avalonia.Collections; using Avalonia.Collections;
using LibHac.Tools.FsSystem;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS; using Ryujinx.HLE.HOS;
using System.Collections.Generic; using System.Collections.Generic;

View File

@ -1,25 +1,24 @@
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Styling;
using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Windowing;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Windows namespace Ryujinx.Ava.UI.Windows
{ {
public partial class CompatibilityListWindow : StyleableAppWindow public partial class CompatibilityListWindow : StyleableAppWindow
{ {
public static Task Show(string titleId = null) => public static async Task Show(string titleId = null)
ShowAsync(new CompatibilityListWindow
{ {
DataContext = new CompatibilityViewModel(RyujinxApp.MainWindow.ViewModel.ApplicationLibrary), using CompatibilityViewModel compatWindow = new(RyujinxApp.MainWindow.ViewModel.ApplicationLibrary);
await ShowAsync(new CompatibilityListWindow
{
DataContext = compatWindow,
SearchBoxFlush = { Text = titleId ?? string.Empty }, SearchBoxFlush = { Text = titleId ?? string.Empty },
SearchBoxNormal = { Text = titleId ?? string.Empty } SearchBoxNormal = { Text = titleId ?? string.Empty }
}); });
}
public CompatibilityListWindow() : base(useCustomTitleBar: true, 37) public CompatibilityListWindow() : base(useCustomTitleBar: true, 37)
{ {

View File

@ -1,25 +1,9 @@
using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Input;
using Avalonia.Media.Imaging;
using FluentAvalonia.Core;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Projektanker.Icons.Avalonia;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.ViewModels.Input;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Common.Configuration;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.Input;
using System; using System;
using System.IO;
using System.Linq; using System.Linq;
using Key = Avalonia.Input.Key;
namespace Ryujinx.Ava.UI.Windows namespace Ryujinx.Ava.UI.Windows

View File

@ -7,13 +7,12 @@ using Avalonia.Platform;
using Avalonia.Threading; using Avalonia.Threading;
using DynamicData; using DynamicData;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Windowing;
using Gommon; using Gommon;
using LibHac.Ns; using LibHac.Ns;
using LibHac.Tools.FsSystem;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
using Ryujinx.Ava.Systems;
using Ryujinx.Ava.UI.Applet; using Ryujinx.Ava.UI.Applet;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;

View File

@ -8,7 +8,6 @@ using FluentAvalonia.UI.Windowing;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.ViewModels;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Windows namespace Ryujinx.Ava.UI.Windows