Fix ~3500 analyser issues

See merge request ryubing/ryujinx!44
This commit is contained in:
MrKev 2025-05-30 17:08:34 -05:00 committed by LotP
parent 417df486b1
commit 361d0c5632
622 changed files with 3080 additions and 2652 deletions

View file

@ -3,11 +3,11 @@ using Avalonia.Threading;
using FluentAvalonia.UI.Controls;
using Gommon;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Common;
using Ryujinx.HLE;
using Ryujinx.HLE.HOS.Applets;
@ -179,11 +179,13 @@ namespace Ryujinx.Ava.UI.Applet
try
{
_parent.ViewModel.AppHost.NpadManager.BlockInputUpdates();
SoftwareKeyboardUIArgs args = new();
args.KeyboardMode = KeyboardMode.Default;
args.InitialText = "Ryujinx";
args.StringLengthMin = 1;
args.StringLengthMax = 25;
SoftwareKeyboardUIArgs args = new()
{
KeyboardMode = KeyboardMode.Default,
InitialText = "Ryujinx",
StringLengthMin = 1,
StringLengthMax = 25
};
(UserResult result, string userInput) =
await SwkbdAppletDialog.ShowInputDialog(LocaleManager.Instance[LocaleKeys.CabinetDialog], args);
if (result == UserResult.Ok)
@ -220,7 +222,6 @@ namespace Ryujinx.Ava.UI.Applet
dialogCloseEvent.WaitOne();
}
public void ExecuteProgram(Switch device, ProgramSpecifyKind kind, ulong value)
{
device.Configuration.UserChannelPersistence.ExecuteProgram(kind, value);
@ -240,7 +241,9 @@ namespace Ryujinx.Ava.UI.Applet
{
ErrorAppletWindow msgDialog = new(_parent, buttons, message)
{
Title = title, WindowStartupLocation = WindowStartupLocation.CenterScreen, Width = 400
Title = title,
WindowStartupLocation = WindowStartupLocation.CenterScreen,
Width = 400
};
object response = await msgDialog.Run();
@ -291,7 +294,8 @@ namespace Ryujinx.Ava.UI.Applet
profiles.Add(new Models.UserProfile(guest, nav));
ProfileSelectorDialogViewModel viewModel = new()
{
Profiles = profiles, SelectedUserId = _parent.AccountManager.LastOpenedUser.UserId
Profiles = profiles,
SelectedUserId = _parent.AccountManager.LastOpenedUser.UserId
};
(selected, _) = await ProfileSelectorDialog.ShowInputDialog(viewModel);

View file

@ -21,10 +21,10 @@ namespace Ryujinx.Ava.UI.Applet
public ProfileSelectorDialog(ProfileSelectorDialogViewModel viewModel)
{
DataContext = ViewModel = viewModel;
InitializeComponent();
}
private void Grid_PointerEntered(object sender, PointerEventArgs e)
{
if (sender is Grid { DataContext: UserProfile profile })
@ -61,7 +61,7 @@ namespace Ryujinx.Ava.UI.Applet
if (item is UserProfile originalItem)
{
UserProfileSft profile = new(originalItem.UserId, originalItem.Name, originalItem.Image);
if (profile.UserId == ViewModel.SelectedUserId)
{
profile.AccountState = AccountState.Open;
@ -98,13 +98,13 @@ namespace Ryujinx.Ava.UI.Applet
UserId result = UserId.Null;
bool input = false;
contentDialog.Closed += Handler;
await ContentDialogHelper.ShowAsync(contentDialog);
return (result, input);
void Handler(ContentDialog sender, ContentDialogClosedEventArgs eventArgs)
{
if (eventArgs.Result == ContentDialogResult.Primary)

View file

@ -7,12 +7,12 @@ using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Views.Dialog;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Views.Dialog;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Helper;
using Ryujinx.HLE.HOS;

View file

@ -1,4 +1,4 @@
using Avalonia;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;

View file

@ -154,12 +154,12 @@ namespace Ryujinx.Ava.UI.Controls
if (profile == null)
{
_ = Dispatcher.UIThread.InvokeAsync(async ()
_ = Dispatcher.UIThread.InvokeAsync(async ()
=> await ContentDialogHelper.CreateErrorDialog(
LocaleManager.Instance[LocaleKeys.DialogUserProfileDeletionWarningMessage]));
return;
}
}
AccountManager.OpenUser(profile.UserId);
}

View file

@ -1,4 +1,4 @@
using Avalonia.Controls;
using Avalonia.Controls;
using Gommon;
using Ryujinx.Ava.UI.ViewModels;
using System;

View file

@ -1,4 +1,4 @@
using Avalonia;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media.Imaging;
using Ryujinx.Ava.Systems.Configuration;
@ -15,7 +15,7 @@ namespace Ryujinx.Ava.UI.Controls
public static readonly Bitmap Bitmap =
new(Assembly.GetAssembly(typeof(MainWindowViewModel))!
.GetManifestResourceStream("Ryujinx.Assets.UIImages.Logo_Ryujinx_AntiAlias.png")!);
public RyujinxLogo()
{
Margin = new Thickness(7, 7, 7, 0);

View file

@ -59,4 +59,4 @@ namespace Ryujinx.Ava.UI.Helpers
}
}
}
}
}

View file

@ -1,4 +1,4 @@
using CommunityToolkit.Mvvm.Input;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Threading.Tasks;
@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Helpers
=> new(action);
public static RelayCommand CreateConditional(Func<bool> canExecute, Action action)
=> new(action, canExecute);
public static RelayCommand<T> Create<T>(Action<T?> action)
=> new(action);
public static RelayCommand<T> CreateConditional<T>(Predicate<T?> canExecute, Action<T?> action)
@ -23,7 +23,7 @@ namespace Ryujinx.Ava.UI.Helpers
=> new(action, AsyncRelayCommandOptions.AllowConcurrentExecutions);
public static AsyncRelayCommand CreateSilentFail(Func<Task> action)
=> new(action, AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler);
public static AsyncRelayCommand<T> Create<T>(Func<T?, Task> action)
=> new(action, AsyncRelayCommandOptions.None);
public static AsyncRelayCommand<T> CreateConcurrent<T>(Func<T?, Task> action)
@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.Helpers
=> new(action, canExecute, AsyncRelayCommandOptions.AllowConcurrentExecutions);
public static AsyncRelayCommand CreateSilentFailConditional(Func<bool> canExecute, Func<Task> action)
=> new(action, canExecute, AsyncRelayCommandOptions.FlowExceptionsToTaskScheduler);
public static AsyncRelayCommand<T> CreateConditional<T>(Predicate<T?> canExecute, Func<T?, Task> action)
=> new(action, canExecute, AsyncRelayCommandOptions.None);
public static AsyncRelayCommand<T> CreateConcurrentConditional<T>(Predicate<T?> canExecute, Func<T?, Task> action)

View file

@ -23,13 +23,13 @@ namespace Ryujinx.Ava.UI.Helpers
private static ContentDialogOverlayWindow _contentDialogOverlayWindow;
public static ContentDialog ApplyStyles(
this ContentDialog contentDialog,
double closeButtonWidth = 80,
this ContentDialog contentDialog,
double closeButtonWidth = 80,
HorizontalAlignment buttonSpaceAlignment = HorizontalAlignment.Right)
{
Style closeButton = new(x => x.Name("CloseButton"));
closeButton.Setters.Add(new Setter(Layoutable.WidthProperty, closeButtonWidth));
Style closeButtonParent = new(x => x.Name("CommandSpace"));
closeButtonParent.Setters.Add(new Setter(Layoutable.HorizontalAlignmentProperty, buttonSpaceAlignment));
@ -281,7 +281,7 @@ namespace Ryujinx.Ava.UI.Helpers
string.Empty,
LocaleManager.Instance[LocaleKeys.InputDialogOk],
(int)Symbol.Important);
internal static async Task<UserResult> CreateUpdaterUpToDateInfoDialog(string primary, string secondaryText)
=> await ShowTextDialog(
LocaleManager.Instance[LocaleKeys.DialogUpdaterTitle],
@ -339,7 +339,7 @@ namespace Ryujinx.Ava.UI.Helpers
return response == UserResult.Yes;
}
internal static async Task<UserResult> CreateUpdaterChoiceDialog(string title, string primary, string secondaryText)
{
if (_isChoiceDialogOpen)
@ -403,7 +403,7 @@ namespace Ryujinx.Ava.UI.Helpers
Position = parent.PointToScreen(new Point()),
ShowInTaskbar = false,
};
#if DEBUG
_contentDialogOverlayWindow.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control));
#endif
@ -480,7 +480,7 @@ namespace Ryujinx.Ava.UI.Helpers
await dialogWindow.ShowDialog(_contentDialogOverlayWindow ?? mainWindow ?? GetMainWindow());
}
private static Window GetMainWindow()
private static MainWindow GetMainWindow()
{
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime al)
{

View file

@ -37,6 +37,5 @@ namespace Ryujinx.Ava.UI.Helpers
{
throw new NotImplementedException();
}
}
}

View file

@ -150,6 +150,7 @@ namespace Ryujinx.Ava.UI.Helpers
{
keyString = key.ToString();
}
break;
case GamepadInputId gamepadInputId:
if (_gamepadInputIdMap.TryGetValue(gamepadInputId, out localeKey))
@ -160,6 +161,7 @@ namespace Ryujinx.Ava.UI.Helpers
{
keyString = gamepadInputId.ToString();
}
break;
case StickInputId stickInputId:
if (_stickInputIdMap.TryGetValue(stickInputId, out localeKey))
@ -170,6 +172,7 @@ namespace Ryujinx.Ava.UI.Helpers
{
keyString = stickInputId.ToString();
}
break;
}

View file

@ -17,7 +17,7 @@ namespace Ryujinx.Ava.UI.Helpers
{
if (value is not ApplicationData { HasLdnGames: true } applicationData)
return "";
return new StringBuilder()
.AppendLine(
LocaleManager.Instance[LocaleKeys.GameListHeaderHostedGames]

View file

@ -1,4 +1,4 @@
using Avalonia.Data.Converters;
using Avalonia.Data.Converters;
using Avalonia.Media;
using Gommon;
using Ryujinx.Ava.Common.Locale;
@ -15,8 +15,8 @@ namespace Ryujinx.Ava.UI.Helpers
public object Convert(object value, Type _, object __, CultureInfo ___)
=> value.Cast<LocaleKeys>() switch
{
LocaleKeys.CompatibilityListNothing or
LocaleKeys.CompatibilityListBoots or
LocaleKeys.CompatibilityListNothing or
LocaleKeys.CompatibilityListBoots or
LocaleKeys.CompatibilityListMenus => Brushes.Red,
LocaleKeys.CompatibilityListIngame => Brushes.DarkOrange,
_ => Brushes.ForestGreen

View file

@ -31,7 +31,7 @@ namespace Ryujinx.Ava.UI.Helpers
}
return app.PercentageProgress != null ? String.Empty :
app.ProcessingOutcome != OperationOutcome.Successful && app.ProcessingOutcome != OperationOutcome.Undetermined ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusFailedLabel] :
app.ProcessingOutcome is not OperationOutcome.Successful and not OperationOutcome.Undetermined ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusFailedLabel] :
app.Trimmable & app.Untrimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusPartialLabel] :
app.Trimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusTrimmableLabel] :
app.Untrimmable ? LocaleManager.Instance[LocaleKeys.TitleXCIStatusUntrimmableLabel] :

View file

@ -30,7 +30,7 @@ namespace Ryujinx.Ava.UI.Helpers
}
return app.PercentageProgress != null ? null :
app.ProcessingOutcome != OperationOutcome.Successful && app.ProcessingOutcome != OperationOutcome.Undetermined ? app.ProcessingOutcome.ToLocalisedText() :
app.ProcessingOutcome is not OperationOutcome.Successful and not OperationOutcome.Undetermined ? app.ProcessingOutcome.ToLocalisedText() :
null;
}

View file

@ -31,7 +31,6 @@ namespace Ryujinx.Ava.UI.Helpers
{
SKColor color = GetColor(image);
// We don't want colors that are too dark.
// If the color is too dark, make it brighter by reducing the range
// and adding a constant color.

View file

@ -15,19 +15,20 @@ namespace Ryujinx.Ava.UI.Helpers
internal class LoggerAdapter : ILogSink
{
private static bool _avaloniaLogsEnabled = ConfigurationState.Instance.Logger.EnableAvaloniaLog;
private static bool _avaloniaLogsEnabled = ConfigurationState.Instance.Logger.EnableAvaloniaLog;
public static void Register()
{
AvaLogger.Sink = new LoggerAdapter();
ConfigurationState.Instance.Logger.EnableAvaloniaLog.Event
ConfigurationState.Instance.Logger.EnableAvaloniaLog.Event
+= (_, e) => _avaloniaLogsEnabled = e.NewValue;
}
private static RyuLogger.Log? GetLog(AvaLogLevel level, string area)
{
if (!_avaloniaLogsEnabled) return null;
if (!_avaloniaLogsEnabled)
return null;
return level switch
{
AvaLogLevel.Verbose => RyuLogger.Debug,

View file

@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.Helpers
public static void ShowError(string message) =>
ShowError(
LocaleManager.Instance[LocaleKeys.DialogErrorTitle],
LocaleManager.Instance[LocaleKeys.DialogErrorTitle],
$"{LocaleManager.Instance[LocaleKeys.DialogErrorMessage]}\n\n{message}"
);
@ -73,8 +73,8 @@ namespace Ryujinx.Ava.UI.Helpers
title,
text,
NotificationType.Information,
waitingExit,
onClick,
waitingExit,
onClick,
onClose);
public static void ShowSuccess(string title, string text, bool waitingExit = false, Action onClick = null, Action onClose = null) =>
@ -82,8 +82,8 @@ namespace Ryujinx.Ava.UI.Helpers
title,
text,
NotificationType.Success,
waitingExit,
onClick,
waitingExit,
onClick,
onClose);
public static void ShowWarning(string title, string text, bool waitingExit = false, Action onClick = null, Action onClose = null) =>
@ -91,8 +91,8 @@ namespace Ryujinx.Ava.UI.Helpers
title,
text,
NotificationType.Warning,
waitingExit,
onClick,
waitingExit,
onClick,
onClose);
public static void ShowError(string title, string text, bool waitingExit = false, Action onClick = null, Action onClose = null) =>
@ -100,8 +100,8 @@ namespace Ryujinx.Ava.UI.Helpers
title,
text,
NotificationType.Error,
waitingExit,
onClick,
waitingExit,
onClick,
onClose);
}
}

View file

@ -28,7 +28,6 @@ namespace Ryujinx.Ava.UI.Helpers
IdcArrow = 32512,
}
[SuppressMessage("Design", "CA1069: Enums values should not be duplicated")]
public enum WindowsMessages : uint
{
NcHitTest = 0x0084,

View file

@ -33,4 +33,4 @@ namespace Ryujinx.Ava.UI.Helpers
}
}
}
}
}

View file

@ -46,21 +46,21 @@ namespace Ryujinx.Ava.UI.Models.Input
[ObservableProperty] private GamepadInputId _buttonMinus;
[ObservableProperty] private GamepadInputId _buttonPlus;
[ObservableProperty] private GamepadInputId _buttonA;
[ObservableProperty] private GamepadInputId _buttonB;
[ObservableProperty] private GamepadInputId _buttonX;
[ObservableProperty] private GamepadInputId _buttonY;
[ObservableProperty] private GamepadInputId _buttonZl;
[ObservableProperty] private GamepadInputId _buttonZr;
[ObservableProperty] private GamepadInputId _buttonL;
[ObservableProperty] private GamepadInputId _buttonR;
[ObservableProperty] private GamepadInputId _leftButtonSl;
[ObservableProperty] private GamepadInputId _leftButtonSr;
[ObservableProperty] private GamepadInputId _rightButtonSl;
[ObservableProperty] private GamepadInputId _rightButtonSr;
@ -73,17 +73,17 @@ namespace Ryujinx.Ava.UI.Models.Input
[ObservableProperty] private float _triggerThreshold;
[ObservableProperty] private bool _enableMotion;
[ObservableProperty] private bool _enableRumble;
[ObservableProperty] private bool _enableLedChanging;
[ObservableProperty] private Color _ledColor;
public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed;
private bool _turnOffLed;
public bool TurnOffLed
{
get => _turnOffLed;
@ -94,9 +94,9 @@ namespace Ryujinx.Ava.UI.Models.Input
OnPropertyChanged(nameof(ShowLedColorPicker));
}
}
private bool _useRainbowLed;
public bool UseRainbowLed
{
get => _useRainbowLed;
@ -183,7 +183,7 @@ namespace Ryujinx.Ava.UI.Models.Input
WeakRumble = controllerInput.Rumble.WeakRumble;
StrongRumble = controllerInput.Rumble.StrongRumble;
}
if (controllerInput.Led != null)
{
EnableLedChanging = controllerInput.Led.EnableLed;
@ -204,7 +204,7 @@ namespace Ryujinx.Ava.UI.Models.Input
StandardControllerInputConfig config = new()
{
Id = Id,
Name = Name,
Name = Name,
Backend = InputBackendType.GamepadSDL2,
PlayerIndex = PlayerIndex,
ControllerType = ControllerType,

View file

@ -29,24 +29,24 @@ namespace Ryujinx.Ava.UI.Models.Input
[ObservableProperty] private Key _dpadDown;
[ObservableProperty] private Key _dpadLeft;
[ObservableProperty] private Key _dpadRight;
[ObservableProperty] private Key _buttonMinus;
[ObservableProperty] private Key _buttonPlus;
[ObservableProperty] private Key _buttonA;
[ObservableProperty] private Key _buttonB;
[ObservableProperty] private Key _buttonX;
[ObservableProperty] private Key _buttonY;
[ObservableProperty] private Key _buttonL;
[ObservableProperty] private Key _buttonR;
[ObservableProperty] private Key _buttonZl;
[ObservableProperty] private Key _buttonZr;
[ObservableProperty] private Key _leftButtonSl;
[ObservableProperty] private Key _leftButtonSr;
[ObservableProperty] private Key _rightButtonSl;
[ObservableProperty] private Key _rightButtonSr;

View file

@ -96,9 +96,9 @@ namespace Ryujinx.Ava.UI.Models.Input
public float UiStickRightX => ClampVector(UiStickRight).Item1;
public float UiStickRightY => ClampVector(UiStickRight).Item2;
public int UiStickCircumference => DrawStickCircumference;
public int UiCanvasSize => DrawStickCanvasSize;
public int UiStickBorderSize => DrawStickBorderSize;
public static int UiStickCircumference => DrawStickCircumference;
public static int UiCanvasSize => DrawStickCanvasSize;
public static int UiStickBorderSize => DrawStickBorderSize;
public float? UiDeadzoneLeft => _gamepadConfig?.DeadzoneLeft * DrawStickCanvasSize - DrawStickCircumference;
public float? UiDeadzoneRight => _gamepadConfig?.DeadzoneRight * DrawStickCanvasSize - DrawStickCircumference;
@ -158,14 +158,17 @@ namespace Ryujinx.Ava.UI.Models.Input
{
leftBuffer.Item1 += 1;
}
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickLeft))
{
leftBuffer.Item1 -= 1;
}
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickUp))
{
leftBuffer.Item2 += 1;
}
if (snapshot.IsPressed((Key)KeyboardConfig.LeftStickDown))
{
leftBuffer.Item2 -= 1;
@ -175,14 +178,17 @@ namespace Ryujinx.Ava.UI.Models.Input
{
rightBuffer.Item1 += 1;
}
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickLeft))
{
rightBuffer.Item1 -= 1;
}
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickUp))
{
rightBuffer.Item2 += 1;
}
if (snapshot.IsPressed((Key)KeyboardConfig.RightStickDown))
{
rightBuffer.Item2 -= 1;
@ -191,6 +197,7 @@ namespace Ryujinx.Ava.UI.Models.Input
UiStickLeft = leftBuffer;
UiStickRight = rightBuffer;
}
break;
case DeviceType.Controller:
@ -201,6 +208,7 @@ namespace Ryujinx.Ava.UI.Models.Input
leftBuffer = controller.GetStick((StickInputId)GamepadConfig.LeftJoystick);
rightBuffer = controller.GetStick((StickInputId)GamepadConfig.RightJoystick);
}
break;
case DeviceType.None:

View file

@ -12,7 +12,7 @@ namespace Ryujinx.Ava.UI.Models
public string Path { get; }
public string Name { get; }
public string FormattedName =>
public string FormattedName =>
InSd && ulong.TryParse(Name, NumberStyles.HexNumber, null, out ulong applicationId)
? $"Atmosphère: {RyujinxApp.MainWindow.ApplicationLibrary.GetNameForApplicationId(applicationId)}"
: Name;

View file

@ -1,9 +1,9 @@
using Gommon;
using LibHac.Fs;
using LibHac.Ncm;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.HLE.FileSystem;
using System.IO;
using System.Linq;

View file

@ -23,10 +23,10 @@ namespace Ryujinx.Ava.UI.Models
ShaderCount = shaderCount;
}
public override bool Equals(object obj)
{
if (obj is not StatusUpdatedEventArgs suea) return false;
if (obj is not StatusUpdatedEventArgs suea)
return false;
return
VSyncMode == suea.VSyncMode &&
VolumeStatus == suea.VolumeStatus &&
@ -37,7 +37,7 @@ namespace Ryujinx.Ava.UI.Models
ShaderCount == suea.ShaderCount;
}
public override int GetHashCode()
public override int GetHashCode()
=> HashCode.Combine(VSyncMode, VolumeStatus, AspectRatio, DockedMode, FifoStatus, GameStatus, ShaderCount);
}
}

View file

@ -115,7 +115,7 @@ namespace Ryujinx.Ava.UI.Renderer
}
[SupportedOSPlatform("linux")]
private IPlatformHandle CreateLinux(IPlatformHandle control)
private PlatformHandle CreateLinux(IPlatformHandle control)
{
if (ConfigurationState.Instance.Graphics.GraphicsBackend.Value == GraphicsBackend.Vulkan)
{
@ -134,7 +134,7 @@ namespace Ryujinx.Ava.UI.Renderer
}
[SupportedOSPlatform("windows")]
IPlatformHandle CreateWin32(IPlatformHandle control)
PlatformHandle CreateWin32(IPlatformHandle control)
{
_className = "NativeWindow-" + Guid.NewGuid();
@ -171,7 +171,7 @@ namespace Ryujinx.Ava.UI.Renderer
}
[SupportedOSPlatform("macos")]
IPlatformHandle CreateMacOS()
PlatformHandle CreateMacOS()
{
// Create a new CAMetalLayer.
ObjectiveC.Object layerObject = new("CAMetalLayer");
@ -215,11 +215,9 @@ namespace Ryujinx.Ava.UI.Renderer
}
[SupportedOSPlatform("macos")]
#pragma warning disable CA1822 // Mark member as static
void DestroyMacOS()
static void DestroyMacOS()
{
// TODO
}
#pragma warning restore CA1822
}
}

View file

@ -1,4 +1,4 @@
using Avalonia;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
using Ryujinx.Ava.Systems.Configuration;
@ -36,8 +36,8 @@ namespace Ryujinx.Ava.UI.Renderer
EmbeddedWindowOpenGL => GraphicsBackend.OpenGl,
_ => throw new NotImplementedException()
};
private void Initialize()
{
EmbeddedWindow.WindowCreated += CurrentWindow_WindowCreated;

View file

@ -8,11 +8,11 @@ using Avalonia.Threading;
using FluentAvalonia.UI.Windowing;
using Gommon;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Views.Dialog;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Views.Dialog;
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using System;
@ -23,7 +23,7 @@ namespace Ryujinx.Ava
public class RyujinxApp : Application
{
public static event Action ThemeChanged;
internal static string FormatTitle(LocaleKeys? windowTitleKey = null, bool includeVersion = true)
=> windowTitleKey is null
? $"{FullAppName}{(includeVersion ? $" {Program.Version}" : string.Empty)}"
@ -34,7 +34,7 @@ namespace Ryujinx.Ava
public static MainWindow MainWindow => Current!
.ApplicationLifetime.Cast<IClassicDesktopStyleApplicationLifetime>()
.MainWindow.Cast<MainWindow>();
public static IClassicDesktopStyleApplicationLifetime AppLifetime => Current!
.ApplicationLifetime.Cast<IClassicDesktopStyleApplicationLifetime>();
@ -48,7 +48,6 @@ namespace Ryujinx.Ava
public static void SetTaskbarProgressValue(ulong current, ulong total) => MainWindow.PlatformFeatures.SetTaskBarProgressBarValue(current, total);
public static void SetTaskbarProgressValue(long current, long total) => SetTaskbarProgressValue(Convert.ToUInt64(current), Convert.ToUInt64(total));
public override void Initialize()
{
Name = FormatTitle();

View file

@ -14,7 +14,7 @@ namespace Ryujinx.Ava.UI.ViewModels
[ObservableProperty] private Bitmap _gitLabLogo;
[ObservableProperty] private Bitmap _discordLogo;
[ObservableProperty] private string _version;
public string Developers => "GreemDev, LotP";
public string FormerDevelopers => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.AboutPageDeveloperListMore, "gdkchan, Ac_K, marysaka, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, GoffyDude, TSRBerry, IsaacMarovitz");
@ -37,9 +37,9 @@ namespace Ryujinx.Ava.UI.ViewModels
private void UpdateLogoTheme(string theme)
{
bool isDarkTheme = theme == "Dark" || (theme == "Auto" && RyujinxApp.DetectSystemTheme() == ThemeVariant.Dark);
string themeName = isDarkTheme ? "Dark" : "Light";
DiscordLogo = LoadBitmap(LogoPathFormat.Format("Discord", themeName));
GitLabLogo = LoadBitmap(LogoPathFormat.Format("GitLab", themeName));
}
@ -49,10 +49,10 @@ namespace Ryujinx.Ava.UI.ViewModels
public void Dispose()
{
RyujinxApp.ThemeChanged -= Ryujinx_ThemeChanged;
GitLabLogo.Dispose();
DiscordLogo.Dispose();
GC.SuppressFinalize(this);
}
}

View file

@ -1,4 +1,4 @@
using Gommon;
using Gommon;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.Systems.PlayReport;
@ -20,8 +20,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public string FormattedDeveloper => LocaleManager.Instance[LocaleKeys.GameListHeaderDeveloper].Format(AppData.Developer);
public string FormattedFileExtension => LocaleManager.Instance[LocaleKeys.GameListHeaderFileExtension].Format(AppData.FileExtension);
public string FormattedFileSize => LocaleManager.Instance[LocaleKeys.GameListHeaderFileSize].Format(AppData.FileSizeString);
public string FormattedLdnInfo =>
public string FormattedLdnInfo =>
$"{LocaleManager.Instance[LocaleKeys.GameListHeaderHostedGames].Format(AppData.GameCount)}" +
$"\n" +
$"{LocaleManager.Instance[LocaleKeys.GameListHeaderPlayerCount].Format(AppData.PlayerCount)}";

View file

@ -1,4 +1,4 @@
using Gommon;
using Gommon;
using Ryujinx.Ava.Systems;
using Ryujinx.Ava.Systems.AppLibrary;
using System;
@ -19,15 +19,15 @@ namespace Ryujinx.Ava.UI.ViewModels
x.TitleId.Check(tid => _ownedGameTitleIds.ContainsIgnoreCase(tid)))
: _currentEntries;
public CompatibilityViewModel() {}
public CompatibilityViewModel() { }
private void AppCountUpdated(object _, ApplicationCountUpdatedEventArgs __)
=> _ownedGameTitleIds = _appLibrary.Applications.Keys.Select(x => x.ToString("X16")).ToArray();
public CompatibilityViewModel(ApplicationLibrary appLibrary)
{
_appLibrary = appLibrary;
AppCountUpdated(null, null);
_appLibrary.ApplicationCountUpdated += AppCountUpdated;
@ -38,7 +38,7 @@ namespace Ryujinx.Ava.UI.ViewModels
GC.SuppressFinalize(this);
_appLibrary.ApplicationCountUpdated -= AppCountUpdated;
}
private bool _onlyShowOwnedGames = true;
public bool OnlyShowOwnedGames
@ -69,9 +69,7 @@ namespace Ryujinx.Ava.UI.ViewModels
private void SetEntries(IEnumerable<CompatibilityEntry> entries)
{
#pragma warning disable MVVMTK0034
_currentEntries = entries.ToList();
#pragma warning restore MVVMTK0034
OnPropertyChanged(nameof(CurrentEntries));
}
}

View file

@ -1,4 +1,4 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.Systems.AppLibrary;
using System.Linq;
@ -8,10 +8,10 @@ namespace Ryujinx.Ava.UI.ViewModels
public partial class DlcSelectViewModel : BaseModel
{
[ObservableProperty] private DownloadableContentModel[] _dlcs;
#nullable enable
#nullable enable
[ObservableProperty] private DownloadableContentModel? _selectedDlc;
#nullable disable
#nullable disable
public DlcSelectViewModel(ulong titleId, ApplicationLibrary appLibrary)
{
_dlcs = appLibrary.FindDlcsFor(titleId)

View file

@ -6,8 +6,8 @@ using DynamicData;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Helpers;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
@ -103,7 +103,7 @@ namespace Ryujinx.Ava.UI.ViewModels
// NOTE(jpr): this works around a bug where calling _views.Clear also clears SelectedDownloadableContents for
// some reason. so we save the items here and add them back after
DownloadableContentModel[] items = SelectedDownloadableContents.ToArray();
Views.Clear();
Views.AddRange(view);
@ -119,7 +119,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{
if (arg is DownloadableContentModel content)
{
return string.IsNullOrWhiteSpace(_search) || content.FileName.ToLower().Contains(_search.ToLower()) || content.TitleIdStr.ToLower().Contains(_search.ToLower());
return string.IsNullOrWhiteSpace(_search) || content.FileName.Contains(_search, System.StringComparison.OrdinalIgnoreCase) || content.TitleIdStr.Contains(_search, System.StringComparison.OrdinalIgnoreCase);
}
return false;
@ -253,12 +253,12 @@ namespace Ryujinx.Ava.UI.ViewModels
return Dispatcher.UIThread.InvokeAsync(async () =>
{
await ContentDialogHelper.ShowTextDialog(
LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle],
msg,
string.Empty,
string.Empty,
string.Empty,
LocaleManager.Instance[LocaleKeys.InputDialogOk],
LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle],
msg,
string.Empty,
string.Empty,
string.Empty,
LocaleManager.Instance[LocaleKeys.InputDialogOk],
(int)Symbol.Checkmark);
});
}

View file

@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
OnPropertyChanged();
}
}
private bool _isLeft;
public bool IsLeft
{
@ -59,11 +59,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
}
public bool HasSides => IsLeft ^ IsRight;
[ObservableProperty] private SvgImage _image;
public InputViewModel ParentModel { get; }
public ControllerInputViewModel(InputViewModel model, GamepadInputConfig config, StickVisualizer visualizer)
{
ParentModel = model;
@ -79,7 +79,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
else
{
Rainbow.Reset();
if (Config.TurnOffLed)
ParentModel.SelectedGamepad.ClearLed();
else
@ -91,17 +91,17 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
}
public async void ShowMotionConfig()
{
{
await MotionInputView.Show(this);
ParentModel.IsModified = true;
}
public async void ShowRumbleConfig()
{
{
await RumbleInputView.Show(this);
ParentModel.IsModified = true;
}
public async void ShowLedConfig()
{
await LedInputView.Show(this);

View file

@ -6,11 +6,11 @@ using CommunityToolkit.Mvvm.ComponentModel;
using Gommon;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.Models.Input;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Hid;
@ -67,12 +67,12 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
private set
{
Rainbow.Reset();
_selectedGamepad = value;
if (ConfigViewModel is ControllerInputViewModel { Config.UseRainbowLed: true })
Rainbow.Updated += (ref Color color) => _selectedGamepad.SetLed((uint)color.ToArgb());
OnPropertiesChanged(nameof(HasLed), nameof(CanClearLed));
}
}
@ -101,7 +101,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public bool IsModified
{
get => _isModified;
set
set
{
_isModified = value;
OnPropertyChanged();
@ -149,11 +149,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
set
{
if (IsModified)
{
{
_playerIdChoose = value;
return;
}
IsModified = false;
_playerId = value;
_isChangeTrackingActive = false;
@ -163,6 +163,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
_playerId = PlayerIndex.Player1;
}
_isLoaded = false;
LoadConfiguration();
LoadDevice();
@ -216,11 +217,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
IsLeft = false;
break;
}
LoadInputDriver();
LoadProfiles();
}
OnPropertyChanged();
NotifyChanges();
}
@ -287,7 +288,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
}
}
public InputConfig Config { get; set; }
public InputViewModel(UserControl owner) : this()
@ -348,7 +348,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
{
ConfigViewModel = new ControllerInputViewModel(this, new GamepadInputConfig(controllerInputConfig), VisualStick);
}
}
private void FindPairedDeviceInConfigFile()
@ -356,7 +355,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
// This function allows you to output a message about the device configuration found in the file
// NOTE: if the configuration is found, we display the message "Waiting for controller connection",
// 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)
{
@ -369,10 +368,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
NotificationText = $"{LocaleManager.Instance[LocaleKeys.ControllerSettingsWaitingConnectDevice].Format(Config.Name, Config.Id)}";
}
}
}
private void MarkAsChanged()
{
//If tracking is active, then allow changing the modifier
@ -383,7 +380,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
}
}
public void UnlinkDevice()
{
// "Disabled" mode is available after unbinding the device
@ -392,7 +388,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
IsModified = true;
}
public void LoadDevice()
{
if (Config == null || Config.Backend == InputBackendType.Invalid)
@ -479,10 +474,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
LoadDevices();
IsModified = true;
RevertChanges();
RevertChanges();
_isChangeTrackingActive = true;// Enable configuration change tracking
}
private string GetCurrentGamepadId()
@ -557,6 +552,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
{
return $"{GetShortGamepadName(gamepad.Name)} ({controllerNumber})";
}
string GetUniqueGamepadName(IGamepad gamepad, ref int controllerNumber)
{
string name = GetGamepadName(gamepad, controllerNumber);
@ -565,6 +561,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
controllerNumber++;
name = GetGamepadName(gamepad, controllerNumber);
}
return name;
}
@ -790,7 +787,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
}
public void LoadProfileButton()
{
{
LoadProfile();
IsModified = true;
}
@ -824,6 +821,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
{
ProfilesList.RemoveAt(index);
}
return;
}
@ -860,58 +858,57 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public async void SaveProfile()
{
if (Device == 0)
{
return;
}
if (ConfigViewModel == null)
{
return;
}
if (ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault])
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileDefaultProfileOverwriteErrorMessage]);
return;
}
else
{
bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
if (Device == 0)
{
return;
}
if (validFileName)
{
string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
if (ConfigViewModel == null)
{
return;
}
InputConfig config = null;
if (ProfileName == LocaleManager.Instance[LocaleKeys.ControllerSettingsProfileDefault])
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileDefaultProfileOverwriteErrorMessage]);
if (IsKeyboard)
{
config = (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig();
}
else if (IsController)
{
config = (ConfigViewModel as ControllerInputViewModel).Config.GetConfig();
}
return;
}
else
{
bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
config.ControllerType = Controllers[_controller].Type;
if (validFileName)
{
string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig);
InputConfig config = null;
await File.WriteAllTextAsync(path, jsonString);
if (IsKeyboard)
{
config = (ConfigViewModel as KeyboardInputViewModel).Config.GetConfig();
}
else if (IsController)
{
config = (ConfigViewModel as ControllerInputViewModel).Config.GetConfig();
}
LoadProfiles();
config.ControllerType = Controllers[_controller].Type;
ProfileChoose = ProfileName; // Show new profile
}
else
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]);
}
}
string jsonString = JsonHelper.Serialize(config, _serializerContext.InputConfig);
await File.WriteAllTextAsync(path, jsonString);
LoadProfiles();
ProfileChoose = ProfileName; // Show new profile
}
else
{
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogProfileInvalidProfileNameErrorMessage]);
}
}
}
public async void RemoveProfile()
@ -947,7 +944,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
{
LoadConfiguration(); // configuration preload is required if the paired gamepad was disconnected but was changed to another gamepad
Device = Devices.ToList().FindIndex(d => d.Id == RevertDeviceId);
LoadDevice();
LoadConfiguration();
@ -957,7 +954,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public void Save()
{
if (!IsModified)
{
return; //If the input settings were not touched, then do nothing
@ -967,7 +964,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
RevertDeviceId = Devices[Device].Id; // Remember selected device after saving
List <InputConfig> newConfig = [];
List<InputConfig> newConfig = [];
newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value);

View file

@ -1,9 +1,9 @@
using Avalonia.Media;
using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Humanizer;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Helpers;
using System.Globalization;
namespace Ryujinx.Ava.UI.ViewModels.Input
@ -11,22 +11,23 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public partial class LedInputViewModel : BaseModel
{
public required InputViewModel ParentModel { get; init; }
public RelayCommand LedDisabledChanged => Commands.Create(() =>
{
if (!EnableLedChanging) return;
if (!EnableLedChanging)
return;
if (TurnOffLed)
ParentModel.SelectedGamepad.ClearLed();
else
ParentModel.SelectedGamepad.SetLed(LedColor.ToUInt32());
});
[ObservableProperty] private bool _enableLedChanging;
[ObservableProperty] private Color _ledColor;
public string RainbowSpeedText => RainbowSpeed.ToString(CultureInfo.CurrentCulture).Truncate(4, string.Empty);
public float RainbowSpeed
{
get => ConfigurationState.Instance.Hid.RainbowSpeed;
@ -37,11 +38,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
OnPropertyChanged(nameof(RainbowSpeedText));
}
}
public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed;
private bool _turnOffLed;
public bool TurnOffLed
{
get => _turnOffLed;
@ -52,9 +53,9 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
OnPropertyChanged(nameof(ShowLedColorPicker));
}
}
private bool _useRainbowLed;
public bool UseRainbowLed
{
get => _useRainbowLed;

View file

@ -20,15 +20,15 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.Input;
using Ryujinx.Ava.Systems;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.Models.Generic;
using Ryujinx.Ava.UI.Renderer;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Views.Dialog;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
@ -86,9 +86,9 @@ namespace Ryujinx.Ava.UI.ViewModels
[ObservableProperty] private Brush _progressBarForegroundColor;
[ObservableProperty] private Brush _progressBarBackgroundColor;
[ObservableProperty] private Brush _vSyncModeColor;
#nullable enable
#nullable enable
[ObservableProperty] private byte[]? _selectedIcon;
#nullable disable
#nullable disable
[ObservableProperty] private int _statusBarProgressMaximum;
[ObservableProperty] private int _statusBarProgressValue;
[ObservableProperty] private string _statusBarProgressStatusText;
@ -118,7 +118,7 @@ namespace Ryujinx.Ava.UI.ViewModels
if (Updater.CanUpdate(true))
await Updater.BeginUpdateAsync(true);
});
private bool _showTotalTimePlayed;
private bool _showLoadProgress;
private bool _isGameRunning;
@ -140,7 +140,7 @@ namespace Ryujinx.Ava.UI.ViewModels
private int _customVSyncIntervalPercentageProxy;
private ApplicationData _listSelectedApplication;
private ApplicationData _gridSelectedApplication;
// Key is Title ID
public SafeDictionary<string, LdnGameData.Array> LdnData = [];
@ -157,9 +157,7 @@ namespace Ryujinx.Ava.UI.ViewModels
.Sort(GetComparer())
.OnItemAdded(_ => OnPropertyChanged(nameof(AppsObservableList)))
.OnItemRemoved(_ => OnPropertyChanged(nameof(AppsObservableList)))
#pragma warning disable MVVMTK0034 // Event to update is fired below
.Bind(out _appsObservableList);
#pragma warning restore MVVMTK0034
_rendererWaitEvent = new AutoResetEvent(false);
@ -205,7 +203,7 @@ namespace Ryujinx.Ava.UI.ViewModels
#if DEBUG
topLevel.AttachDevTools(new KeyGesture(Avalonia.Input.Key.F12, KeyModifiers.Control));
#endif
Window.ApplicationLibrary.TotalTimePlayedRecalculated += TotalTimePlayed_Recalculated;
}
@ -327,7 +325,7 @@ namespace Ryujinx.Ava.UI.ViewModels
OnPropertyChanged();
}
}
public ApplicationData ListSelectedApplication
{
get => _listSelectedApplication;
@ -335,13 +333,11 @@ namespace Ryujinx.Ava.UI.ViewModels
{
_listSelectedApplication = value;
#pragma warning disable MVVMTK0034
if (_listSelectedApplication != null && _listAppContextMenu == null)
if (_listSelectedApplication != null && ListAppContextMenu == null)
ListAppContextMenu = new ApplicationContextMenu();
else if (_listSelectedApplication == null && _listAppContextMenu != null)
else if (_listSelectedApplication == null && ListAppContextMenu != null)
ListAppContextMenu = null!;
#pragma warning restore MVVMTK0034
OnPropertyChanged();
}
@ -354,13 +350,11 @@ namespace Ryujinx.Ava.UI.ViewModels
{
_gridSelectedApplication = value;
#pragma warning disable MVVMTK0034
if (_gridSelectedApplication != null && _gridAppContextMenu == null)
if (_gridSelectedApplication != null && GridAppContextMenu == null)
GridAppContextMenu = new ApplicationContextMenu();
else if (_gridSelectedApplication == null && _gridAppContextMenu != null)
else if (_gridSelectedApplication == null && GridAppContextMenu != null)
GridAppContextMenu = null!;
#pragma warning restore MVVMTK0034
OnPropertyChanged();
}
}
@ -380,7 +374,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{
ListSelectedApplication = value;
GridSelectedApplication = value;
}
}
}
public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo;
@ -395,7 +389,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool OpenBcatSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0;
public bool ShowCustomVSyncIntervalPicker
public bool ShowCustomVSyncIntervalPicker
=> _isGameRunning && AppHost.Device.VSyncMode == VSyncMode.Custom;
public void UpdateVSyncIntervalPicker()
@ -416,6 +410,7 @@ namespace Ryujinx.Ava.UI.ViewModels
AppHost.Device.CustomVSyncInterval = newInterval;
AppHost.Device.UpdateVSyncInterval();
}
OnPropertyChanged((nameof(CustomVSyncInterval)));
OnPropertyChanged((nameof(CustomVSyncIntervalPercentageText)));
}
@ -447,6 +442,7 @@ namespace Ryujinx.Ava.UI.ViewModels
AppHost.Device.CustomVSyncInterval = value;
AppHost.Device.UpdateVSyncInterval();
}
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageProxy));
OnPropertyChanged(nameof(CustomVSyncIntervalPercentageText));
OnPropertyChanged();
@ -579,7 +575,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool ShowNames
{
get => ConfigurationState.Instance.UI.ShowNames && ConfigurationState.Instance.UI.GridSize > 1;
get => ConfigurationState.Instance.UI.ShowNames && ConfigurationState.Instance.UI.GridSize > 1;
set
{
ConfigurationState.Instance.UI.ShowNames.Value = value;
@ -762,7 +758,7 @@ namespace Ryujinx.Ava.UI.ViewModels
#region PrivateMethods
private static IComparer<ApplicationData> CreateComparer(bool ascending, Func<ApplicationData, IComparable> selector) =>
private static SortExpressionComparer<ApplicationData> CreateComparer(bool ascending, Func<ApplicationData, IComparable> selector) =>
ascending
? SortExpressionComparer<ApplicationData>.Ascending(selector)
: SortExpressionComparer<ApplicationData>.Descending(selector);
@ -791,15 +787,13 @@ namespace Ryujinx.Ava.UI.ViewModels
private void RefreshGrid()
{
Applications.ToObservableChangeSet()
var appsList = Applications.ToObservableChangeSet()
.Filter(Filter)
.Sort(GetComparer())
#pragma warning disable MVVMTK0034
.Bind(out _appsObservableList)
#pragma warning restore MVVMTK0034
.Bind(out var apps)
.AsObservableList();
OnPropertyChanged(nameof(AppsObservableList));
AppsObservableList = apps;
}
private bool Filter(object arg)
@ -874,10 +868,10 @@ namespace Ryujinx.Ava.UI.ViewModels
string message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareInstallSuccessMessage, firmwareVersion.VersionString);
await ContentDialogHelper.CreateInfoDialog(
dialogTitle,
message,
LocaleManager.Instance[LocaleKeys.InputDialogOk],
string.Empty,
dialogTitle,
message,
LocaleManager.Instance[LocaleKeys.InputDialogOk],
string.Empty,
LocaleManager.Instance[LocaleKeys.RyujinxInfo]);
Logger.Info?.Print(LogClass.Application, message);
@ -996,7 +990,7 @@ namespace Ryujinx.Ava.UI.ViewModels
waitingDialog.Close();
string message = ex.Message;
if(ex is FormatException)
if (ex is FormatException)
{
message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysNotFoundErrorMessage, filename);
}
@ -1054,6 +1048,7 @@ namespace Ryujinx.Ava.UI.ViewModels
CacheLoadStatus = string.Empty;
break;
}
break;
case ShaderCacheLoadingState shaderCacheState:
CacheLoadStatus = $"{current} / {total}";
@ -1074,6 +1069,7 @@ namespace Ryujinx.Ava.UI.ViewModels
CacheLoadStatus = string.Empty;
break;
}
break;
default:
throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}");
@ -1110,7 +1106,7 @@ namespace Ryujinx.Ava.UI.ViewModels
_rendererWaitEvent.WaitOne();
AppHost?.Start();
AppHost?.DisposeContext();
}
@ -1190,11 +1186,11 @@ namespace Ryujinx.Ava.UI.ViewModels
{
await ContentDialogHelper.ShowTextDialog(
LocaleManager.Instance[numAdded > 0 || numRemoved > 0 ? LocaleKeys.RyujinxConfirm : LocaleKeys.RyujinxInfo],
msg,
string.Empty,
string.Empty,
string.Empty,
LocaleManager.Instance[LocaleKeys.InputDialogOk],
msg,
string.Empty,
string.Empty,
string.Empty,
LocaleManager.Instance[LocaleKeys.InputDialogOk],
(int)Symbol.Checkmark);
});
}
@ -1388,7 +1384,7 @@ namespace Ryujinx.Ava.UI.ViewModels
return;
}
OpenHelper.OpenFolder(screenshotsDir);
}
@ -1578,15 +1574,11 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool InitializeUserConfig(ApplicationData application)
{
// Code where conditions will be met before loading the user configuration (Global Config)
BackendThreading backendThreadingValue = ConfigurationState.Instance.Graphics.BackendThreading.Value;
// Code where conditions will be met before loading the user configuration (Global Config)
string BackendThreadingInit = Program.BackendThreadingArg;
if (BackendThreadingInit is null)
{
BackendThreadingInit = ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString();
}
BackendThreadingInit ??= ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString();
// If a configuration is found in the "/games/xxxxxxxxxxxxxx" folder, the program will load the user setting.
string idGame = application.IdBaseString;
if (ConfigurationFileFormat.TryLoad(Program.GetDirGameUserConfig(idGame), out ConfigurationFileFormat configurationFileFormat))
@ -1599,13 +1591,13 @@ namespace Ryujinx.Ava.UI.ViewModels
if (ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() != BackendThreadingInit)
{
List<string> Arguments = new List<string>
List<string> Arguments = new()
{
"--bt", ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() // BackendThreading
};
Rebooter.RebootAppWithGame(application.Path, Arguments);
return true;
}
@ -1635,7 +1627,7 @@ namespace Ryujinx.Ava.UI.ViewModels
#if RELEASE
await PerformanceCheck();
#endif
Logger.RestartTime();
SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(application.Path, ConfigurationState.Instance.System.Language, application.Id);
@ -1680,7 +1672,7 @@ namespace Ryujinx.Ava.UI.ViewModels
Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" };
gameThread.Start();
}
public void SwitchToRenderer(bool startFullscreen) =>
@ -1801,7 +1793,6 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
public void ToggleFullscreen()
{
if (Environment.TickCount64 - LastFullscreenToggle < HotKeyPressDelayMs)
@ -1963,7 +1954,7 @@ namespace Ryujinx.Ava.UI.ViewModels
#endregion
#region Context Menu commands
public static AsyncRelayCommand<MainWindowViewModel> RunApplication { get; } =
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
viewModel => viewModel.LoadApplication(viewModel.SelectedApplication));
@ -1982,7 +1973,7 @@ namespace Ryujinx.Ava.UI.ViewModels
viewModel.RefreshView();
}
);
public static RelayCommand<MainWindowViewModel> CreateApplicationShortcut { get; } =
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
viewModel => ShortcutHelper.CreateAppShortcut(
@ -1991,7 +1982,7 @@ namespace Ryujinx.Ava.UI.ViewModels
viewModel.SelectedApplication.IdString,
viewModel.SelectedApplication.Icon
));
public static AsyncRelayCommand<MainWindowViewModel> EditGameConfiguration { get; } =
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
async viewModel =>
@ -2058,7 +2049,7 @@ namespace Ryujinx.Ava.UI.ViewModels
viewModel.SelectedApplication.Path
)
));
public static AsyncRelayCommand<MainWindowViewModel> OpenModManager { get; } =
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
viewModel => ModManagerView.Show(
@ -2086,11 +2077,11 @@ namespace Ryujinx.Ava.UI.ViewModels
OpenHelper.OpenFolder(titleModsPath);
});
public static AsyncRelayCommand<MainWindowViewModel> TrimXci { get; } =
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
viewModel => viewModel.TrimXCIFile(viewModel.SelectedApplication.Path));
public static AsyncRelayCommand<MainWindowViewModel> PurgePtcCache { get; } =
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
async viewModel =>
@ -2280,7 +2271,7 @@ namespace Ryujinx.Ava.UI.ViewModels
OpenHelper.OpenFolder(shaderCacheDir);
});
public static AsyncRelayCommand<MainWindowViewModel> ExtractApplicationExeFs { get; } =
Commands.CreateConditional<MainWindowViewModel>(vm => vm?.SelectedApplication != null,
async viewModel =>
@ -2350,7 +2341,7 @@ namespace Ryujinx.Ava.UI.ViewModels
png.SaveTo(fileStream);
});
#endregion
}
}

View file

@ -5,9 +5,9 @@ using CommunityToolkit.Mvvm.ComponentModel;
using DynamicData;
using Gommon;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities;
@ -131,12 +131,10 @@ namespace Ryujinx.Ava.UI.ViewModels
.Filter(Filter)
.Bind(out ReadOnlyObservableCollection<ModModel> view).AsObservableList();
#pragma warning disable MVVMTK0034 // Event to update is fired below
_views.Clear();
_views.AddRange(view);
#pragma warning restore MVVMTK0034
Views.Clear();
Views.AddRange(view);
SelectedMods = new(Views.Where(x => x.Enabled));
SelectedMods = [.. Views.Where(x => x.Enabled)];
OnPropertyChanged(nameof(ModCount));
OnPropertyChanged(nameof(Views));
@ -147,7 +145,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{
if (arg is ModModel content)
{
return string.IsNullOrWhiteSpace(_search) || content.Name.ToLower().Contains(_search.ToLower());
return string.IsNullOrWhiteSpace(_search) || content.Name.Contains(_search, StringComparison.OrdinalIgnoreCase);
}
return false;
@ -215,6 +213,7 @@ namespace Ryujinx.Ava.UI.ViewModels
Mods.Remove(model);
OnPropertyChanged(nameof(ModCount));
}
Sort();
}
@ -312,7 +311,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public void EnableAll()
{
SelectedMods = new(Mods);
SelectedMods = [.. Mods];
}
public void DisableAll()

View file

@ -1,4 +1,4 @@
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.ComponentModel;
using Gommon;
using Ryujinx.Ava.Systems.Configuration;
@ -8,8 +8,8 @@ namespace Ryujinx.Ava.UI.ViewModels
{
private readonly SettingsViewModel _baseViewModel;
public SettingsHacksViewModel() {}
public SettingsHacksViewModel() { }
public SettingsHacksViewModel(SettingsViewModel settingsVm)
{
_baseViewModel = settingsVm;
@ -17,20 +17,20 @@ namespace Ryujinx.Ava.UI.ViewModels
[ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
[ObservableProperty] private bool _nifmDisableIsAnyInternetRequestAccepted = ConfigurationState.Instance.Hacks.DisableNifmIsAnyInternetRequestAccepted;
public static string Xc2MenuFixTooltip { get; } = Lambda.String(sb =>
{
sb.AppendLine(
"This hack applies a 2ms delay (via 'Thread.Sleep(2)') every time the game tries to read data from the emulated Switch filesystem.")
.AppendLine();
sb.AppendLine("From the issue on GitHub:").AppendLine();
sb.Append(
"When clicking very fast from game main menu to 2nd submenu, " +
"there is a low chance that the game will softlock, " +
"the submenu won't show up, while background music is still there.");
});
public static string NifmDisableIsAnyInternetRequestAcceptedTooltip { get; } = Lambda.String(sb =>
{
sb.AppendLine(

View file

@ -9,12 +9,12 @@ using Ryujinx.Audio.Backends.OpenAL;
using Ryujinx.Audio.Backends.SDL2;
using Ryujinx.Audio.Backends.SoundIo;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models.Input;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.Systems.Configuration.System;
using Ryujinx.Ava.Systems.Configuration.UI;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models.Input;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Configuration.Multiplayer;
using Ryujinx.Common.GraphicsDriver;
@ -72,10 +72,10 @@ namespace Ryujinx.Ava.UI.ViewModels
public SettingsHacksViewModel DirtyHacks { get; }
private readonly bool _isGameRunning;
private Bitmap _gameIcon;
private string _gameTitle;
private string _gamePath;
private string _gameId;
private readonly Bitmap _gameIcon;
private readonly string _gameTitle;
private readonly string _gamePath;
private readonly string _gameId;
public bool IsGameRunning => _isGameRunning;
public Bitmap GameIcon => _gameIcon;
public string GamePath => _gamePath;
@ -142,9 +142,9 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool EnableKeyboard { get; set; }
public bool EnableMouse { get; set; }
public bool DisableInputWhenOutOfFocus { get; set; }
public int FocusLostActionType { get; set; }
public VSyncMode VSyncMode
{
get => _vSyncMode;
@ -188,6 +188,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{
VSyncMode = VSyncMode.Custom;
}
OnPropertyChanged();
}
}
@ -201,15 +202,15 @@ namespace Ryujinx.Ava.UI.ViewModels
int newPercent = (int)((value / 60f) * 100);
_customVSyncIntervalPercentageProxy = newPercent;
OnPropertiesChanged(
nameof(CustomVSyncIntervalPercentageProxy),
nameof(CustomVSyncIntervalPercentageProxy),
nameof(CustomVSyncIntervalPercentageText));
OnPropertyChanged();
}
}
public bool EnablePptc { get; set; }
public bool EnableLowPowerPptc { get; set; }
public long TurboMultiplier
{
get => _turboModeMultiplier;
@ -218,13 +219,13 @@ namespace Ryujinx.Ava.UI.ViewModels
if (_turboModeMultiplier != value)
{
_turboModeMultiplier = value;
OnPropertyChanged();
OnPropertyChanged((nameof(TurboMultiplierPercentageText)));
}
}
}
public string TurboMultiplierPercentageText => $"{TurboMultiplier}%";
public bool EnableInternetAccess { get; set; }
@ -345,7 +346,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public AvaloniaList<string> NetworkInterfaceList
{
get => new(_networkInterfaces.Keys);
get => [.. _networkInterfaces.Keys];
}
public HotkeyConfig KeyboardHotkey { get; set; }
@ -374,39 +375,37 @@ namespace Ryujinx.Ava.UI.ViewModels
{
_virtualFileSystem = virtualFileSystem;
_contentManager = contentManager;
if (Program.PreviewerDetached)
{
Task.Run(LoadTimeZones);
DirtyHacks = new SettingsHacksViewModel(this);
}
}
public SettingsViewModel(
VirtualFileSystem virtualFileSystem,
VirtualFileSystem virtualFileSystem,
ContentManager contentManager,
bool gameRunning,
string gamePath,
string gameName,
string gameId,
byte[] gameIconData,
string gameName,
string gameId,
byte[] gameIconData,
bool enableToLoadCustomConfig) : this(enableToLoadCustomConfig)
{
_virtualFileSystem = virtualFileSystem;
_contentManager = contentManager;
if (gameIconData != null && gameIconData.Length > 0)
{
using (var ms = new MemoryStream(gameIconData))
{
_gameIcon = new Bitmap(ms);
}
using var ms = new MemoryStream(gameIconData);
_gameIcon = new Bitmap(ms);
}
_isGameRunning = gameRunning;
_gamePath = gamePath;
_gameTitle = gameName;
_gameTitle = gameName;
_gameId = gameId;
if (enableToLoadCustomConfig) // During the game. If there is no user config, then load the global config window
@ -414,7 +413,7 @@ namespace Ryujinx.Ava.UI.ViewModels
string gameDir = Program.GetDirGameUserConfig(gameId, false, true);
if (ConfigurationFileFormat.TryLoad(gameDir, out ConfigurationFileFormat configurationFileFormat))
{
ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId);
ConfigurationState.Instance.Load(configurationFileFormat, gameDir, gameId);
}
LoadCurrentConfiguration(); // Needed to load custom configuration
@ -443,8 +442,8 @@ namespace Ryujinx.Ava.UI.ViewModels
{
Task.Run(LoadAvailableGpus);
// if (!noLoadGlobalConfig)// Default is false, but loading custom config avoids double call
LoadCurrentConfiguration();
// if (!noLoadGlobalConfig)// Default is false, but loading custom config avoids double call
LoadCurrentConfiguration();
DirtyHacks = new SettingsHacksViewModel(this);
}
@ -811,7 +810,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public void DeleteConfigGame()
{
string gameDir = Program.GetDirGameUserConfig(GameId,false,false);
string gameDir = Program.GetDirGameUserConfig(GameId, false, false);
if (File.Exists(gameDir))
{
@ -839,8 +838,9 @@ namespace Ryujinx.Ava.UI.ViewModels
public AsyncRelayCommand ResetButton => Commands.Create(async () =>
{
if (!WantsToReset) return;
if (!WantsToReset)
return;
CloseWindow?.Invoke();
ConfigurationState.Instance.LoadDefault();
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);

View file

@ -5,8 +5,8 @@ using CommunityToolkit.Mvvm.ComponentModel;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Helpers;
using System.Collections.Generic;
using System.IO;
using System.Linq;
@ -178,17 +178,17 @@ namespace Ryujinx.Ava.UI.ViewModels
ApplicationLibrary.SaveTitleUpdatesForGame(ApplicationData, updates);
}
private Task ShowNewUpdatesAddedDialog(int numAdded)
private Task<UserResult> ShowNewUpdatesAddedDialog(int numAdded)
{
string msg = string.Format(LocaleManager.Instance[LocaleKeys.UpdateWindowUpdateAddedMessage], numAdded);
return Dispatcher.UIThread.InvokeAsync(async () =>
return Dispatcher.UIThread.InvokeAsync(async () =>
await ContentDialogHelper.ShowTextDialog(
LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle],
msg,
string.Empty,
string.Empty,
string.Empty,
LocaleManager.Instance[LocaleKeys.InputDialogOk],
LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle],
msg,
string.Empty,
string.Empty,
string.Empty,
LocaleManager.Instance[LocaleKeys.InputDialogOk],
(int)Symbol.Checkmark
));
}

View file

@ -128,7 +128,7 @@ namespace Ryujinx.Ava.UI.ViewModels
}
}
private static byte[] DecompressYaz0(Stream stream)
private static byte[] DecompressYaz0(MemoryStream stream)
{
using BinaryReader reader = new(stream);

View file

@ -43,10 +43,8 @@ namespace Ryujinx.Ava.UI.ViewModels
.Sort(GetComparer())
.Bind(out ReadOnlyObservableCollection<SaveModel> view).AsObservableList();
#pragma warning disable MVVMTK0034
_views.Clear();
_views.AddRange(view);
#pragma warning restore MVVMTK0034
Views.Clear();
Views.AddRange(view);
OnPropertyChanged(nameof(Views));
}
@ -54,13 +52,13 @@ namespace Ryujinx.Ava.UI.ViewModels
{
if (arg is SaveModel save)
{
return string.IsNullOrWhiteSpace(Search) || save.Title.ToLower().Contains(Search.ToLower());
return string.IsNullOrWhiteSpace(Search) || save.Title.Contains(Search, System.StringComparison.OrdinalIgnoreCase);
}
return false;
}
private IComparer<SaveModel> GetComparer()
private SortExpressionComparer<SaveModel> GetComparer()
{
return SortIndex switch
{

View file

@ -1,12 +1,12 @@
using Avalonia.Collections;
using Avalonia.Threading;
using DynamicData;
using Gommon;
using Avalonia.Threading;
using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Common.Utilities;
using System.Collections.Generic;
using System.Collections.ObjectModel;
@ -36,10 +36,10 @@ namespace Ryujinx.Ava.UI.ViewModels
private readonly Ryujinx.Common.Logging.XCIFileTrimmerLog _logger;
private ApplicationLibrary ApplicationLibrary => _mainWindowViewModel.ApplicationLibrary;
private Optional<XCITrimmerFileModel> _processingApplication = null;
private AvaloniaList<XCITrimmerFileModel> _allXCIFiles = [];
private readonly AvaloniaList<XCITrimmerFileModel> _allXCIFiles = [];
private AvaloniaList<XCITrimmerFileModel> _selectedXCIFiles = [];
private AvaloniaList<XCITrimmerFileModel> _displayedXCIFiles = [];
private MainWindowViewModel _mainWindowViewModel;
private readonly AvaloniaList<XCITrimmerFileModel> _displayedXCIFiles = [];
private readonly MainWindowViewModel _mainWindowViewModel;
private CancellationTokenSource _cancellationTokenSource;
private string _search;
private ProcessingMode _processingMode;
@ -93,12 +93,12 @@ namespace Ryujinx.Ava.UI.ViewModels
private void SortingChanged()
{
OnPropertiesChanged(
nameof(IsSortedByName),
nameof(IsSortedBySaved),
nameof(SortingAscending),
nameof(SortingField),
nameof(IsSortedByName),
nameof(IsSortedBySaved),
nameof(SortingAscending),
nameof(SortingField),
nameof(SortingFieldName));
SortAndFilter();
}
@ -110,13 +110,13 @@ namespace Ryujinx.Ava.UI.ViewModels
private void ApplicationsChanged()
{
OnPropertiesChanged(
nameof(AllXCIFiles),
nameof(Status),
nameof(PotentialSavings),
nameof(ActualSavings),
nameof(CanTrim),
nameof(AllXCIFiles),
nameof(Status),
nameof(PotentialSavings),
nameof(ActualSavings),
nameof(CanTrim),
nameof(CanUntrim));
DisplayedChanged();
SortAndFilter();
}
@ -124,9 +124,9 @@ namespace Ryujinx.Ava.UI.ViewModels
private void SelectionChanged(bool displayedChanged = true)
{
OnPropertiesChanged(
nameof(Status),
nameof(CanTrim),
nameof(CanUntrim),
nameof(Status),
nameof(CanTrim),
nameof(CanUntrim),
nameof(SelectedXCIFiles));
if (displayedChanged)
@ -136,10 +136,10 @@ namespace Ryujinx.Ava.UI.ViewModels
private void ProcessingChanged()
{
OnPropertiesChanged(
nameof(Processing),
nameof(Cancel),
nameof(Status),
nameof(CanTrim),
nameof(Processing),
nameof(Cancel),
nameof(Status),
nameof(CanTrim),
nameof(CanUntrim));
}
@ -245,8 +245,8 @@ namespace Ryujinx.Ava.UI.ViewModels
if (arg is XCITrimmerFileModel content)
{
return string.IsNullOrWhiteSpace(_search)
|| content.Name.ToLower().Contains(_search.ToLower())
|| content.Path.ToLower().Contains(_search.ToLower());
|| content.Name.Contains(_search, System.StringComparison.OrdinalIgnoreCase)
|| content.Path.Contains(_search, System.StringComparison.OrdinalIgnoreCase);
}
return false;
@ -254,7 +254,7 @@ namespace Ryujinx.Ava.UI.ViewModels
private class CompareXCITrimmerFiles : IComparer<XCITrimmerFileModel>
{
private XciTrimmerViewModel _viewModel;
private readonly XciTrimmerViewModel _viewModel;
public CompareXCITrimmerFiles(XciTrimmerViewModel ViewModel)
{

View file

@ -22,7 +22,7 @@ namespace Ryujinx.Ava.UI.Views.Dialog
public static async Task Show()
{
using AboutWindowViewModel viewModel = new();
ContentDialog contentDialog = new()
{
PrimaryButtonText = string.Empty,

View file

@ -1,14 +1,14 @@
using Avalonia.Controls;
using Avalonia.Controls;
using Avalonia.Input.Platform;
using Avalonia.Interactivity;
using Avalonia.Layout;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Systems.AppLibrary;
using System.Linq;
using System.Threading.Tasks;
@ -30,12 +30,12 @@ namespace Ryujinx.Ava.UI.Views.Dialog
await ContentDialogHelper.ShowAsync(contentDialog.ApplyStyles(160, HorizontalAlignment.Center));
}
public ApplicationDataView()
{
InitializeComponent();
}
private async void PlayabilityStatus_OnClick(object sender, RoutedEventArgs e)
{
if (sender is not Button { Content: TextBlock playabilityLabel })
@ -43,7 +43,7 @@ namespace Ryujinx.Ava.UI.Views.Dialog
if (RyujinxApp.AppLifetime.Windows.TryGetFirst(x => x is ContentDialogOverlayWindow, out Window window))
window.Close(ContentDialogResult.None);
await CompatibilityListWindow.Show((string)playabilityLabel.Tag);
}
@ -54,15 +54,15 @@ namespace Ryujinx.Ava.UI.Views.Dialog
if (!RyujinxApp.IsClipboardAvailable(out IClipboard clipboard))
return;
ApplicationData appData = RyujinxApp.MainWindow.ViewModel.Applications.FirstOrDefault(it => it.IdString == idText.Text);
if (appData is null)
return;
await clipboard.SetTextAsync(appData.IdString);
NotificationHelper.ShowInformation(
"Copied Title ID",
"Copied Title ID",
$"{appData.Name} ({appData.IdString})");
}
}

View file

@ -1,10 +1,10 @@
using FluentAvalonia.UI.Controls;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Systems.AppLibrary;
using System.Threading.Tasks;
namespace Ryujinx.Ava.UI.Views.Dialog

View file

@ -4,9 +4,9 @@ using Avalonia.Styling;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common.Helper;
using System.Threading.Tasks;

View file

@ -3,11 +3,11 @@ using Avalonia.Interactivity;
using Avalonia.Styling;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Common.Helper;
using System.Threading.Tasks;
using Button = Avalonia.Controls.Button;

View file

@ -4,9 +4,9 @@ using Avalonia.Styling;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common.Helper;
using System.Threading.Tasks;

View file

@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.Views.Input
};
if (!float.IsNaN(_changeSlider) && _changeSlider != (float)check.Value)
{
{
FlagInputConfigChanged();
_changeSlider = (float)check.Value;
@ -83,7 +83,6 @@ namespace Ryujinx.Ava.UI.Views.Input
}
}
private void Button_IsCheckedChanged(object sender, RoutedEventArgs e)
{
if (sender is ToggleButton button)
@ -104,7 +103,7 @@ namespace Ryujinx.Ava.UI.Views.Input
this.Focus(NavigationMethod.Pointer);
PointerPressed += MouseClick;
ControllerInputViewModel viewModel = (DataContext as ControllerInputViewModel);
IKeyboard keyboard =
@ -225,8 +224,8 @@ namespace Ryujinx.Ava.UI.Views.Input
PointerPressed -= MouseClick;
}
private IButtonAssigner CreateButtonAssigner(bool forStick) =>
new GamepadButtonAssigner(
private GamepadButtonAssigner CreateButtonAssigner(bool forStick) =>
new(
ViewModel.ParentModel.SelectedGamepad,
(ViewModel.ParentModel.Config as StandardControllerInputConfig).TriggerThreshold,
forStick);
@ -234,11 +233,12 @@ namespace Ryujinx.Ava.UI.Views.Input
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
{
base.OnDetachedFromVisualTree(e);
foreach (IGamepad gamepad in RyujinxApp.MainWindow.InputManager.GamepadDriver.GetGamepads())
{
gamepad?.ClearLed();
}
_currentAssigner?.Cancel();
_currentAssigner = null;
}

View file

@ -46,7 +46,6 @@ namespace Ryujinx.Ava.UI.Views.Input
LocaleManager.Instance[LocaleKeys.Cancel],
LocaleManager.Instance[LocaleKeys.RyujinxConfirm]);
if (result == UserResult.Yes)
{
ViewModel.Save();
@ -61,14 +60,14 @@ namespace Ryujinx.Ava.UI.Views.Input
ViewModel.IsModified = true;
ViewModel.PlayerId = ((PlayerModel)e.AddedItems[0])!.Id;
}
return;
}
ViewModel.IsModified = false;
ViewModel.PlayerId = ViewModel.PlayerIdChoose;
}
}
}
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)

View file

@ -9,8 +9,8 @@ using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels.Input;
using Ryujinx.Input;
using Ryujinx.Input.Assigner;
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Button = Ryujinx.Input.Button;
using Key = Ryujinx.Common.Configuration.Hid.Key;
@ -45,9 +45,9 @@ namespace Ryujinx.Ava.UI.Views.Input
private void Button_IsCheckedChanged(object sender, RoutedEventArgs e)
{
if (sender is not ToggleButton button)
if (sender is not ToggleButton button)
return;
if (button.IsChecked is true)
{
if (_currentAssigner != null && button == _currentAssigner.ToggledButton)
@ -65,7 +65,7 @@ namespace Ryujinx.Ava.UI.Views.Input
IKeyboard keyboard =
(IKeyboard)ViewModel.ParentModel.AvaloniaKeyboardDriver.GetGamepad("0"); // Open Avalonia keyboard for cancel operations.
IButtonAssigner assigner =
IButtonAssigner assigner =
new KeyboardKeyAssigner((IKeyboard)ViewModel.ParentModel.SelectedGamepad);
_currentAssigner.ButtonAssigned += (_, be) =>
@ -205,7 +205,7 @@ namespace Ryujinx.Ava.UI.Views.Input
if (_currentAssigner != null)
{
Dictionary<string, Action> buttonActions = new Dictionary<string, Action>
Dictionary<string, Action> buttonActions = new()
{
{ "ButtonZl", () => ViewModel.Config.ButtonZl = Key.Unbound },
{ "ButtonL", () => ViewModel.Config.ButtonL = Key.Unbound },

View file

@ -1,4 +1,4 @@
using Avalonia;
using Avalonia;
using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Controls;
@ -20,27 +20,32 @@ namespace Ryujinx.UI.Views.Input
LedColor = viewModel.Config.LedColor,
UseRainbowLed = viewModel.Config.UseRainbowLed,
};
InitializeComponent();
}
private void ColorPickerButton_OnColorChanged(ColorPickerButton sender, ColorButtonColorChangedEventArgs args)
{
if (!args.NewColor.HasValue) return;
if (!ViewModel.EnableLedChanging) return;
if (ViewModel.TurnOffLed) return;
if (!args.NewColor.HasValue)
return;
if (!ViewModel.EnableLedChanging)
return;
if (ViewModel.TurnOffLed)
return;
ViewModel.ParentModel.SelectedGamepad.SetLed(args.NewColor.Value.ToUInt32());
}
private void ColorPickerButton_OnAttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
{
if (!ViewModel.EnableLedChanging) return;
if (ViewModel.TurnOffLed) return;
if (!ViewModel.EnableLedChanging)
return;
if (ViewModel.TurnOffLed)
return;
ViewModel.ParentModel.SelectedGamepad.SetLed(ViewModel.LedColor.ToUInt32());
}
public static async Task Show(ControllerInputViewModel viewModel)
{
LedInputView content = new(viewModel);

View file

@ -6,14 +6,14 @@ using Gommon;
using LibHac.Common;
using LibHac.Ns;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Views.Dialog;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Views.Dialog;
using Ryujinx.Common;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Utilities;
@ -52,13 +52,13 @@ namespace Ryujinx.Ava.UI.Views.Main
UpdateMenuItem.Command = MainWindowViewModel.UpdateCommand;
FaqMenuItem.Command =
SetupGuideMenuItem.Command =
FaqMenuItem.Command =
SetupGuideMenuItem.Command =
LdnGuideMenuItem.Command = Commands.Create<string>(OpenHelper.OpenUrl);
WindowSize720PMenuItem.Command =
WindowSize1080PMenuItem.Command =
WindowSize1440PMenuItem.Command =
WindowSize720PMenuItem.Command =
WindowSize1080PMenuItem.Command =
WindowSize1440PMenuItem.Command =
WindowSize2160PMenuItem.Command = Commands.Create<string>(ChangeWindowSize);
}
@ -95,7 +95,7 @@ namespace Ryujinx.Ava.UI.Views.Main
{
string tr = locales.Locales[index].Translations[language];
languageName = string.IsNullOrEmpty(tr)
? language
? language
: tr;
}
@ -134,7 +134,7 @@ namespace Ryujinx.Ava.UI.Views.Main
await StyleableAppWindow.ShowAsync(Window.SettingsWindow);
}
else
{
{
bool customConfigExists = File.Exists(Program.GetDirGameUserConfig(ViewModel.SelectedApplication.IdString));
if (!ViewModel.IsGameRunning || !customConfigExists)
@ -157,12 +157,12 @@ namespace Ryujinx.Ava.UI.Views.Main
}
public AppletMetadata MiiApplet => new(ViewModel.ContentManager, "miiEdit", 0x0100000000001009);
public async Task OpenMiiApplet()
{
if (!MiiApplet.CanStart(out ApplicationData appData, out BlitStruct<ApplicationControlProperty> nacpData))
if (!MiiApplet.CanStart(out ApplicationData appData, out BlitStruct<ApplicationControlProperty> nacpData))
return;
await ViewModel.LoadApplication(appData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen, nacpData);
}
@ -217,7 +217,7 @@ namespace Ryujinx.Ava.UI.Views.Main
private void ChangeWindowSize(string resolution)
{
(int resolutionWidth, int resolutionHeight) = resolution.Split(' ', 2)
.Into(parts =>
.Into(parts =>
(int.Parse(parts[0]), int.Parse(parts[1]))
);
@ -237,6 +237,6 @@ namespace Ryujinx.Ava.UI.Views.Main
}
public void CloseWindow() => Window.Close();
}
}

View file

@ -3,10 +3,10 @@ using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Threading;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Common;
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;

View file

@ -1,10 +1,10 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Systems.AppLibrary;
using System;
namespace Ryujinx.Ava.UI.Views.Misc

View file

@ -2,10 +2,10 @@ using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Interactivity;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.UI.Windows;
using System;
using System.Linq;
@ -30,7 +30,7 @@ namespace Ryujinx.Ava.UI.Views.Misc
if (sender is ListBox { SelectedItem: ApplicationData selected })
RaiseEvent(new ApplicationOpenedEventArgs(selected, ApplicationOpenedEvent));
}
private async void PlayabilityStatus_OnClick(object sender, RoutedEventArgs e)
{
if (sender is not Button { Content: TextBlock playabilityLabel })
@ -46,15 +46,15 @@ namespace Ryujinx.Ava.UI.Views.Misc
if (!RyujinxApp.IsClipboardAvailable(out IClipboard clipboard))
return;
ApplicationData appData = ViewModel.Applications.FirstOrDefault(it => it.IdString == idText.Text);
if (appData is null)
return;
await clipboard.SetTextAsync(appData.IdString);
NotificationHelper.ShowInformation(
"Copied Title ID",
"Copied Title ID",
$"{appData.Name} ({appData.IdString})");
}
}

View file

@ -10,8 +10,8 @@ using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Input;
using Ryujinx.Input.Assigner;
using System.Collections.Generic;
using System;
using System.Collections.Generic;
using Button = Ryujinx.Input.Button;
using Key = Ryujinx.Common.Configuration.Hid.Key;
@ -20,7 +20,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
public partial class SettingsHotkeysView : RyujinxControl<SettingsViewModel>
{
private ButtonKeyAssigner _currentAssigner;
private readonly IGamepadDriver _avaloniaKeyboardDriver;
private readonly AvaloniaKeyboardDriver _avaloniaKeyboardDriver;
public SettingsHotkeysView()
{
@ -56,7 +56,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
{
DeleteBind();
}
_currentAssigner?.Cancel(shouldUnbind);
PointerPressed -= MouseClick;
@ -69,7 +69,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
if (_currentAssigner != null)
{
Dictionary<string, Action> buttonActions = new Dictionary<string, Action>
Dictionary<string, Action> buttonActions = new()
{
{ "ToggleVSyncMode", () => viewModel.KeyboardHotkey.ToggleVSyncMode = Key.Unbound },
{ "Screenshot", () => viewModel.KeyboardHotkey.Screenshot = Key.Unbound },

View file

@ -32,7 +32,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !directories.Contains(path))
{
directories.Add(path);
addDirBox.Clear();
ViewModel.GameListNeedsRefresh = true;
@ -44,7 +44,7 @@ namespace Ryujinx.Ava.UI.Views.Settings
if (folder.HasValue)
{
directories.Add(folder.Value.Path.LocalPath);
ViewModel.GameListNeedsRefresh = true;
}
}

View file

@ -17,7 +17,7 @@ namespace Ryujinx.Ava.UI.Views.User
private NavigationDialogHost _parent;
private UserProfile _profile;
private bool _isNewUser;
public static uint MaxProfileNameLength => 0x20;
public bool IsDeletable => _profile.UserId != AccountManager.DefaultUserId;

View file

@ -54,6 +54,7 @@ namespace Ryujinx.Ava.UI.Views.User
{
_parent.GoBack();
}
break;
}
}

View file

@ -130,7 +130,7 @@ namespace Ryujinx.Ava.UI.Views.User
UserResult result = await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance[LocaleKeys.DeleteUserSave],
LocaleManager.Instance[LocaleKeys.IrreversibleActionNote],
LocaleManager.Instance[LocaleKeys.InputDialogYes],
LocaleManager.Instance[LocaleKeys.InputDialogNo],
LocaleManager.Instance[LocaleKeys.InputDialogNo],
string.Empty);
if (result == UserResult.Yes)

View file

@ -1,8 +1,8 @@
using Avalonia.Collections;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Models;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.Models;
using Ryujinx.HLE.FileSystem;
using Ryujinx.HLE.HOS;
using System.Collections.Generic;
@ -35,7 +35,7 @@ namespace Ryujinx.Ava.UI.Windows
{
MinWidth = 500;
MinHeight = 650;
LoadedCheats = [];
Heading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.CheatWindowHeading, titleName, titleId.ToUpper());

View file

@ -1,4 +1,4 @@
using Avalonia.Controls;
using Avalonia.Controls;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.UI.ViewModels;
@ -11,7 +11,7 @@ namespace Ryujinx.Ava.UI.Windows
public static async Task Show(string titleId = null)
{
using CompatibilityViewModel compatWindow = new(RyujinxApp.MainWindow.ViewModel.ApplicationLibrary);
await ShowAsync(new CompatibilityListWindow
{
DataContext = compatWindow,
@ -23,9 +23,9 @@ namespace Ryujinx.Ava.UI.Windows
public CompatibilityListWindow() : base(useCustomTitleBar: true, 37)
{
Title = RyujinxApp.FormatTitle(LocaleKeys.CompatibilityListTitle);
InitializeComponent();
FlushControls.IsVisible = !ConfigurationState.Instance.ShowOldUI;
NormalControls.IsVisible = ConfigurationState.Instance.ShowOldUI;
}
@ -39,7 +39,7 @@ namespace Ryujinx.Ava.UI.Windows
if (sender is not TextBox searchBox)
return;
cvm.Search(searchBox.Text);
}
}

View file

@ -5,7 +5,6 @@ using Ryujinx.Ava.UI.ViewModels;
using System;
using System.Linq;
namespace Ryujinx.Ava.UI.Windows
{
public partial class GameSpecificSettingsWindow : StyleableAppWindow
@ -17,7 +16,7 @@ namespace Ryujinx.Ava.UI.Windows
Title = string.Format(LocaleManager.Instance[LocaleKeys.SettingsWithInfo], viewModel.SelectedApplication.Name, viewModel.SelectedApplication.IdString);
DataContext = ViewModel = new SettingsViewModel(
viewModel.VirtualFileSystem,
viewModel.VirtualFileSystem,
viewModel.ContentManager,
viewModel.IsGameRunning,
viewModel.SelectedApplication.Path,
@ -38,7 +37,6 @@ namespace Ryujinx.Ava.UI.Windows
InputPage.InputView?.SaveCurrentProfile();
}
private void Load()
{
Pages.Children.Clear();
@ -48,7 +46,7 @@ namespace Ryujinx.Ava.UI.Windows
private void NavPanelOnSelectionChanged(object sender, NavigationViewSelectionChangedEventArgs e)
{
if (e.SelectedItem is NavigationViewItem navItem && navItem.Tag is not null)
{
switch (navItem.Tag.ToString())
@ -87,7 +85,7 @@ namespace Ryujinx.Ava.UI.Windows
default:
throw new NotImplementedException();
}
}
}
}
protected override void OnClosing(WindowClosingEventArgs e)

View file

@ -13,13 +13,13 @@ using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input;
using Ryujinx.Ava.Systems;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.Systems.Configuration.UI;
using Ryujinx.Ava.UI.Applet;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.Utilities;
using Ryujinx.Ava.Systems.AppLibrary;
using Ryujinx.Ava.Systems.Configuration;
using Ryujinx.Ava.Systems.Configuration.UI;
using Ryujinx.Common;
using Ryujinx.Common.Helper;
using Ryujinx.Common.Logging;
@ -92,9 +92,9 @@ namespace Ryujinx.Ava.UI.Windows
// NOTE: Height of MenuBar and StatusBar is not usable here, since it would still be 0 at this point.
StatusBarHeight = StatusBarView.StatusBar.MinHeight;
MenuBarHeight = MenuBar.MinHeight;
TitleBar.Height = MenuBarHeight;
// Correctly size window when 'TitleBar' is enabled (Nov. 14, 2024)
TitleBarHeight = (ConfigurationState.Instance.ShowOldUI ? TitleBar.Height : 0);
@ -135,7 +135,7 @@ namespace Ryujinx.Ava.UI.Windows
base.OnApplyTemplate(e);
NotificationHelper.SetNotificationManager(this);
Executor.ExecuteBackgroundAsync(async () =>
{
await ShowIntelMacWarningAsync();
@ -145,7 +145,7 @@ namespace Ryujinx.Ava.UI.Windows
if ((firmwarePath.ExistsAsFile && firmwarePath.Extension is "xci" or "zip") ||
firmwarePath.ExistsAsDirectory)
{
await Dispatcher.UIThread.InvokeAsync(() =>
await Dispatcher.UIThread.InvokeAsync(() =>
ViewModel.HandleFirmwareInstallation(firmwarePath));
CommandLineState.FirmwareToInstallPathArg = null;
}
@ -191,10 +191,10 @@ namespace Ryujinx.Ava.UI.Windows
ref ApplicationControlProperty controlHolder = ref application.ControlHolder.Value;
ViewModel.LdnData[application.IdString] = e.LdnData.Where(ref controlHolder);
UpdateApplicationWithLdnData(application);
}
ViewModel.RefreshView();
});
}
@ -230,7 +230,7 @@ namespace Ryujinx.Ava.UI.Windows
_deferLoad = true;
_launchPath = launchPathArg;
_launchApplicationId = launchApplicationId;
_startFullscreen = startFullscreenArg;
_startFullscreen = startFullscreenArg;
}
public void SwitchToGameControl(bool startFullscreen = false)
@ -330,6 +330,7 @@ namespace Ryujinx.Ava.UI.Windows
{
Logger.Error?.Print(LogClass.Application, $"Unable to change vm.max_map_count. Process exited with code: {rc}");
}
break;
case UserResult.No:
rc = LinuxHelper.RunPkExec($"echo \"vm.max_map_count = {LinuxHelper.RecommendedVmMaxMapCount}\" > {LinuxHelper.SysCtlConfigPath} && sysctl -p {LinuxHelper.SysCtlConfigPath}");
@ -341,6 +342,7 @@ namespace Ryujinx.Ava.UI.Windows
{
Logger.Error?.Print(LogClass.Application, $"Unable to write new value for vm.max_map_count to config. Process exited with code: {rc}");
}
break;
}
}
@ -421,6 +423,7 @@ namespace Ryujinx.Ava.UI.Windows
{
Dispatcher.UIThread.Post(() => RyujinxApp.MainWindow.ViewModel.UpdateAvailable = versions.Current < versions.Incoming);
}
break;
}
}
@ -430,7 +433,7 @@ namespace Ryujinx.Ava.UI.Windows
StatusBarView.VolumeStatus.Click += VolumeStatus_CheckedChanged;
ApplicationGrid.DataContext = ApplicationList.DataContext = ViewModel;
ApplicationGrid.ApplicationOpened += Application_Opened;
ApplicationList.ApplicationOpened += Application_Opened;
}
@ -717,7 +720,7 @@ namespace Ryujinx.Ava.UI.Windows
ShowNewContentAddedDialog(dlcLoaded, dlcRemoved, updatesLoaded, updatesRemoved);
}
Executor.ExecuteBackgroundAsync(ApplicationLibrary.RefreshTotalTimePlayedAsync);
_isLoading = false;
@ -729,7 +732,7 @@ namespace Ryujinx.Ava.UI.Windows
applicationLibraryThread.Start();
}
private void ShowNewContentAddedDialog(int numDlcAdded, int numDlcRemoved, int numUpdatesAdded, int numUpdatesRemoved)
private static void ShowNewContentAddedDialog(int numDlcAdded, int numDlcRemoved, int numUpdatesAdded, int numUpdatesRemoved)
{
string[] messages =
[
@ -749,10 +752,10 @@ namespace Ryujinx.Ava.UI.Windows
await ContentDialogHelper.ShowTextDialog(
LocaleManager.Instance[LocaleKeys.DialogConfirmationTitle],
msg,
string.Empty,
string.Empty,
string.Empty,
LocaleManager.Instance[LocaleKeys.InputDialogOk],
string.Empty,
string.Empty,
string.Empty,
LocaleManager.Instance[LocaleKeys.InputDialogOk],
(int)Symbol.Checkmark);
});
}
@ -761,20 +764,22 @@ namespace Ryujinx.Ava.UI.Windows
public static async Task ShowIntelMacWarningAsync()
{
if (_intelMacWarningShown) return;
if (_intelMacWarningShown)
return;
await Dispatcher.UIThread.InvokeAsync(async () => await ContentDialogHelper.CreateWarningDialog(
"Intel Mac Warning",
"Intel Macs are not supported and will not work properly.\nIf you continue, do not come to our Discord asking for support;\nand do not report bugs on the GitHub. They will be closed."));
_intelMacWarningShown = true;
}
private void InputElement_OnGotFocus(object sender, GotFocusEventArgs e)
{
if (ViewModel.AppHost is null) return;
if (!_focusLoss.Active)
if (ViewModel.AppHost is null)
return;
if (!_focusLoss.Active)
return;
switch (_focusLoss.Type)
@ -798,9 +803,9 @@ namespace Ryujinx.Ava.UI.Windows
_focusLoss = default;
return;
}
ViewModel.AppHost.Device.SetVolume(ViewModel.VolumeBeforeMute);
_focusLoss = default;
break;
}
@ -808,10 +813,10 @@ namespace Ryujinx.Ava.UI.Windows
{
if (!ViewModel.AppHost.Device.IsAudioMuted())
goto case FocusLostType.BlockInput;
ViewModel.AppHost.Device.SetVolume(ViewModel.VolumeBeforeMute);
ViewModel.AppHost.NpadManager.UnblockInputUpdates();
_focusLoss = default;
break;
}
@ -822,15 +827,15 @@ namespace Ryujinx.Ava.UI.Windows
_focusLoss = default;
return;
}
ViewModel.AppHost.Resume();
_focusLoss = default;
break;
}
}
}
private (FocusLostType Type, bool Active) _focusLoss;
private void InputElement_OnLostFocus(object sender, RoutedEventArgs e)
@ -838,7 +843,8 @@ namespace Ryujinx.Ava.UI.Windows
if (ConfigurationState.Instance.FocusLostActionType.Value is FocusLostType.DoNothing)
return;
if (ViewModel.AppHost is null) return;
if (ViewModel.AppHost is null)
return;
switch (ConfigurationState.Instance.FocusLostActionType.Value)
{
@ -846,7 +852,7 @@ namespace Ryujinx.Ava.UI.Windows
{
if (ViewModel.AppHost.NpadManager.InputUpdatesBlocked)
return;
ViewModel.AppHost.NpadManager.BlockInputUpdates();
_focusLoss = (FocusLostType.BlockInput, ViewModel.AppHost.NpadManager.InputUpdatesBlocked);
break;
@ -876,7 +882,7 @@ namespace Ryujinx.Ava.UI.Windows
{
if (ViewModel.AppHost.Device.System.IsPaused)
return;
ViewModel.AppHost.Pause();
_focusLoss = (FocusLostType.PauseEmulation, ViewModel.AppHost.Device.System.IsPaused);
break;

View file

@ -33,7 +33,7 @@ namespace Ryujinx.Ava.UI.Windows
Height = ConfigurationState.Instance.ShowOldUI
? 906
: 954; // nav panel is put on top with custom title bar so account for new height
Load();
}
@ -111,12 +111,12 @@ namespace Ryujinx.Ava.UI.Windows
protected override void OnClosing(WindowClosingEventArgs e)
{
HotkeysPage.Dispose();
foreach (IGamepad gamepad in RyujinxApp.MainWindow.InputManager.GamepadDriver.GetGamepads())
{
gamepad?.ClearLed();
}
InputPage.Dispose();
base.OnClosing(e);
}

View file

@ -17,11 +17,11 @@ namespace Ryujinx.Ava.UI.Windows
public static async Task ShowAsync(StyleableAppWindow appWindow, Window owner = null)
{
#if DEBUG
appWindow.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control));
appWindow.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control));
#endif
await appWindow.ShowDialog(owner ?? RyujinxApp.MainWindow);
}
protected StyleableAppWindow(bool useCustomTitleBar = false, double? titleBarHeight = null)
{
WindowStartupLocation = WindowStartupLocation.CenterOwner;
@ -34,7 +34,7 @@ namespace Ryujinx.Ava.UI.Windows
{
TitleBar.ExtendsContentIntoTitleBar = !ConfigurationState.Instance.ShowOldUI;
TitleBar.TitleBarHitTestType = ConfigurationState.Instance.ShowOldUI ? TitleBarHitTestType.Simple : TitleBarHitTestType.Complex;
if (TitleBar.ExtendsContentIntoTitleBar && titleBarHeight != null)
TitleBar.Height = titleBarHeight.Value;
}
@ -60,7 +60,7 @@ namespace Ryujinx.Ava.UI.Windows
public static async Task ShowAsync(StyleableWindow window, Window owner = null)
{
#if DEBUG
window.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control));
window.AttachDevTools(new KeyGesture(Key.F12, KeyModifiers.Control));
#endif
await window.ShowDialog(owner ?? RyujinxApp.MainWindow);
}