Add CommunityToolkit.Mvvm

Use [ObservableProperty] attribute, which greatly reduces or eliminates boilerplate code needed to generate observable properties

Co-authored-by: GreemDev <greemdev@ryujinx.app>
This commit is contained in:
KeatonTheBot
2026-01-14 16:58:45 -06:00
co-authored by GreemDev
parent 0d29b77a14
commit 7d0947cac6
25 changed files with 433 additions and 1883 deletions
+2 -1
View File
@@ -11,6 +11,7 @@
<PackageVersion Include="Svg.Controls.Avalonia" Version="11.3.9.1" /> <PackageVersion Include="Svg.Controls.Avalonia" Version="11.3.9.1" />
<PackageVersion Include="Svg.Controls.Skia.Avalonia" Version="11.3.9.1" /> <PackageVersion Include="Svg.Controls.Skia.Avalonia" Version="11.3.9.1" />
<PackageVersion Include="CommandLineParser" Version="2.9.1" /> <PackageVersion Include="CommandLineParser" Version="2.9.1" />
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.4.0" />
<PackageVersion Include="Concentus" Version="2.2.2" /> <PackageVersion Include="Concentus" Version="2.2.2" />
<PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" /> <PackageVersion Include="DiscordRichPresence" Version="1.6.1.70" />
<PackageVersion Include="DynamicData" Version="9.4.1" /> <PackageVersion Include="DynamicData" Version="9.4.1" />
@@ -52,4 +53,4 @@
<PackageVersion Include="System.Management" Version="10.0.1" /> <PackageVersion Include="System.Management" Version="10.0.1" />
<PackageVersion Include="UnicornEngine.Unicorn" Version="2.1.4-a40db6c" /> <PackageVersion Include="UnicornEngine.Unicorn" Version="2.1.4-a40db6c" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+1
View File
@@ -32,6 +32,7 @@
<PackageReference Include="Svg.Controls.Avalonia" /> <PackageReference Include="Svg.Controls.Avalonia" />
<PackageReference Include="Svg.Controls.Skia.Avalonia" /> <PackageReference Include="Svg.Controls.Skia.Avalonia" />
<PackageReference Include="CommandLineParser" /> <PackageReference Include="CommandLineParser" />
<PackageReference Include="CommunityToolkit.Mvvm" />
<PackageReference Include="DynamicData" /> <PackageReference Include="DynamicData" />
<PackageReference Include="FluentAvaloniaUI" /> <PackageReference Include="FluentAvaloniaUI" />
+55 -335
View File
@@ -1,12 +1,12 @@
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.Controller; using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Configuration.Hid.Controller.Motion; using Ryujinx.Common.Configuration.Hid.Controller.Motion;
using System;
namespace Ryujinx.Ava.UI.Models.Input namespace Ryujinx.Ava.UI.Models.Input
{ {
public class GamepadInputConfig : BaseModel public partial class GamepadInputConfig : BaseModel
{ {
public bool EnableCemuHookMotion { get; set; } public bool EnableCemuHookMotion { get; set; }
public string DsuServerHost { get; set; } public string DsuServerHost { get; set; }
@@ -24,390 +24,110 @@ namespace Ryujinx.Ava.UI.Models.Input
public ControllerType ControllerType { get; set; } public ControllerType ControllerType { get; set; }
public PlayerIndex PlayerIndex { get; set; } public PlayerIndex PlayerIndex { get; set; }
[ObservableProperty]
private StickInputId _leftJoystick; private StickInputId _leftJoystick;
public StickInputId LeftJoystick
{
get => _leftJoystick;
set
{
_leftJoystick = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private bool _leftInvertStickX; private bool _leftInvertStickX;
public bool LeftInvertStickX
{
get => _leftInvertStickX;
set
{
_leftInvertStickX = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private bool _leftInvertStickY; private bool _leftInvertStickY;
public bool LeftInvertStickY
{
get => _leftInvertStickY;
set
{
_leftInvertStickY = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private bool _leftRotate90; private bool _leftRotate90;
public bool LeftRotate90
{
get => _leftRotate90;
set
{
_leftRotate90 = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private GamepadInputId _leftStickButton; private GamepadInputId _leftStickButton;
public GamepadInputId LeftStickButton
{
get => _leftStickButton;
set
{
_leftStickButton = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private StickInputId _rightJoystick; private StickInputId _rightJoystick;
public StickInputId RightJoystick
{
get => _rightJoystick;
set
{
_rightJoystick = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private bool _rightInvertStickX; private bool _rightInvertStickX;
public bool RightInvertStickX
{
get => _rightInvertStickX;
set
{
_rightInvertStickX = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private bool _rightInvertStickY; private bool _rightInvertStickY;
public bool RightInvertStickY
{
get => _rightInvertStickY;
set
{
_rightInvertStickY = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private bool _rightRotate90; private bool _rightRotate90;
public bool RightRotate90
{
get => _rightRotate90;
set
{
_rightRotate90 = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private GamepadInputId _rightStickButton; private GamepadInputId _rightStickButton;
public GamepadInputId RightStickButton
{
get => _rightStickButton;
set
{
_rightStickButton = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private GamepadInputId _dpadUp; private GamepadInputId _dpadUp;
public GamepadInputId DpadUp
{
get => _dpadUp;
set
{
_dpadUp = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private GamepadInputId _dpadDown; private GamepadInputId _dpadDown;
public GamepadInputId DpadDown
{
get => _dpadDown;
set
{
_dpadDown = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private GamepadInputId _dpadLeft; private GamepadInputId _dpadLeft;
public GamepadInputId DpadLeft
{
get => _dpadLeft;
set
{
_dpadLeft = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private GamepadInputId _dpadRight; private GamepadInputId _dpadRight;
public GamepadInputId DpadRight
{
get => _dpadRight;
set
{
_dpadRight = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private GamepadInputId _buttonL; private GamepadInputId _buttonL;
public GamepadInputId ButtonL
{
get => _buttonL;
set
{
_buttonL = value;
OnPropertyChanged();
}
}
private GamepadInputId _buttonMinus;
public GamepadInputId ButtonMinus
{
get => _buttonMinus;
set
{
_buttonMinus = value;
OnPropertyChanged();
}
}
private GamepadInputId _leftButtonSl;
public GamepadInputId LeftButtonSl
{
get => _leftButtonSl;
set
{
_leftButtonSl = value;
OnPropertyChanged();
}
}
private GamepadInputId _leftButtonSr;
public GamepadInputId LeftButtonSr
{
get => _leftButtonSr;
set
{
_leftButtonSr = value;
OnPropertyChanged();
}
}
private GamepadInputId _buttonZl;
public GamepadInputId ButtonZl
{
get => _buttonZl;
set
{
_buttonZl = value;
OnPropertyChanged();
}
}
private GamepadInputId _buttonA;
public GamepadInputId ButtonA
{
get => _buttonA;
set
{
_buttonA = value;
OnPropertyChanged();
}
}
private GamepadInputId _buttonB;
public GamepadInputId ButtonB
{
get => _buttonB;
set
{
_buttonB = value;
OnPropertyChanged();
}
}
private GamepadInputId _buttonX;
public GamepadInputId ButtonX
{
get => _buttonX;
set
{
_buttonX = value;
OnPropertyChanged();
}
}
private GamepadInputId _buttonY;
public GamepadInputId ButtonY
{
get => _buttonY;
set
{
_buttonY = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private GamepadInputId _buttonR; private GamepadInputId _buttonR;
public GamepadInputId ButtonR
{
get => _buttonR;
set
{
_buttonR = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private GamepadInputId _buttonMinus;
[ObservableProperty]
private GamepadInputId _buttonPlus; private GamepadInputId _buttonPlus;
public GamepadInputId ButtonPlus
{
get => _buttonPlus;
set
{
_buttonPlus = value;
OnPropertyChanged();
}
}
private GamepadInputId _rightButtonSl; [ObservableProperty]
public GamepadInputId RightButtonSl private GamepadInputId _leftButtonSl;
{
get => _rightButtonSl;
set
{
_rightButtonSl = value;
OnPropertyChanged();
}
}
private GamepadInputId _rightButtonSr; [ObservableProperty]
public GamepadInputId RightButtonSr private GamepadInputId _leftButtonSr;
{
get => _rightButtonSr;
set
{
_rightButtonSr = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private GamepadInputId _buttonZl;
[ObservableProperty]
private GamepadInputId _buttonZr; private GamepadInputId _buttonZr;
public GamepadInputId ButtonZr
{
get => _buttonZr;
set
{
_buttonZr = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private GamepadInputId _buttonA;
[ObservableProperty]
private GamepadInputId _buttonB;
[ObservableProperty]
private GamepadInputId _buttonX;
[ObservableProperty]
private GamepadInputId _buttonY;
[ObservableProperty]
private GamepadInputId _rightButtonSl;
[ObservableProperty]
private GamepadInputId _rightButtonSr;
[ObservableProperty]
private float _deadzoneLeft; private float _deadzoneLeft;
public float DeadzoneLeft
{
get => _deadzoneLeft;
set
{
_deadzoneLeft = MathF.Round(value, 3);
OnPropertyChanged();
}
}
[ObservableProperty]
private float _deadzoneRight; private float _deadzoneRight;
public float DeadzoneRight
{
get => _deadzoneRight;
set
{
_deadzoneRight = MathF.Round(value, 3);
OnPropertyChanged();
}
}
[ObservableProperty]
private float _rangeLeft; private float _rangeLeft;
public float RangeLeft
{
get => _rangeLeft;
set
{
_rangeLeft = MathF.Round(value, 3);
OnPropertyChanged();
}
}
[ObservableProperty]
private float _rangeRight; private float _rangeRight;
public float RangeRight
{
get => _rangeRight;
set
{
_rangeRight = MathF.Round(value, 3);
OnPropertyChanged();
}
}
[ObservableProperty]
private float _triggerThreshold; private float _triggerThreshold;
public float TriggerThreshold
{
get => _triggerThreshold;
set
{
_triggerThreshold = MathF.Round(value, 3);
OnPropertyChanged();
}
}
[ObservableProperty]
private bool _enableMotion; private bool _enableMotion;
public bool EnableMotion
{
get => _enableMotion;
set
{
_enableMotion = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private bool _enableRumble; private bool _enableRumble;
public bool EnableRumble
{
get => _enableRumble;
set
{
_enableRumble = value;
OnPropertyChanged();
}
}
public GamepadInputConfig(InputConfig config) public GamepadInputConfig(InputConfig config)
{ {
+16 -120
View File
@@ -1,152 +1,48 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common.Configuration.Hid; using Ryujinx.Common.Configuration.Hid;
namespace Ryujinx.Ava.UI.Models.Input namespace Ryujinx.Ava.UI.Models.Input
{ {
public class HotkeyConfig : BaseModel public partial class HotkeyConfig : BaseModel
{ {
[ObservableProperty]
private Key _toggleVSyncMode; private Key _toggleVSyncMode;
public Key ToggleVSyncMode
{
get => _toggleVSyncMode;
set
{
_toggleVSyncMode = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _screenshot; private Key _screenshot;
public Key Screenshot
{
get => _screenshot;
set
{
_screenshot = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _showUI; private Key _showUI;
public Key ShowUI
{
get => _showUI;
set
{
_showUI = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _pause; private Key _pause;
public Key Pause
{
get => _pause;
set
{
_pause = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _toggleMute; private Key _toggleMute;
public Key ToggleMute
{
get => _toggleMute;
set
{
_toggleMute = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _resScaleUp; private Key _resScaleUp;
public Key ResScaleUp
{
get => _resScaleUp;
set
{
_resScaleUp = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _resScaleDown; private Key _resScaleDown;
public Key ResScaleDown
{
get => _resScaleDown;
set
{
_resScaleDown = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _volumeUp; private Key _volumeUp;
public Key VolumeUp
{
get => _volumeUp;
set
{
_volumeUp = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _volumeDown; private Key _volumeDown;
public Key VolumeDown
{
get => _volumeDown;
set
{
_volumeDown = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _customVSyncIntervalIncrement; private Key _customVSyncIntervalIncrement;
public Key CustomVSyncIntervalIncrement
{
get => _customVSyncIntervalIncrement;
set
{
_customVSyncIntervalIncrement = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _customVSyncIntervalDecrement; private Key _customVSyncIntervalDecrement;
public Key CustomVSyncIntervalDecrement
{
get => _customVSyncIntervalDecrement;
set
{
_customVSyncIntervalDecrement = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _turboMode; private Key _turboMode;
public Key TurboMode
{ [ObservableProperty] private bool _turboModeWhileHeld;
get => _turboMode;
set
{
_turboMode = value;
OnPropertyChanged();
}
}
private bool _turboModeWhileHeld;
public bool TurboModeWhileHeld
{
get => _turboModeWhileHeld;
set
{
_turboModeWhileHeld = value;
OnPropertyChanged();
}
}
public HotkeyConfig(KeyboardHotkeys config) public HotkeyConfig(KeyboardHotkeys config)
{ {
@@ -1,322 +1,99 @@
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;
namespace Ryujinx.Ava.UI.Models.Input namespace Ryujinx.Ava.UI.Models.Input
{ {
public class KeyboardInputConfig : BaseModel public partial class KeyboardInputConfig : BaseModel
{ {
public string Id { get; set; } public string Id { get; set; }
public ControllerType ControllerType { get; set; } public ControllerType ControllerType { get; set; }
public PlayerIndex PlayerIndex { get; set; } public PlayerIndex PlayerIndex { get; set; }
[ObservableProperty]
private Key _leftStickUp; private Key _leftStickUp;
public Key LeftStickUp
{
get => _leftStickUp;
set
{
_leftStickUp = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _leftStickDown; private Key _leftStickDown;
public Key LeftStickDown
{
get => _leftStickDown;
set
{
_leftStickDown = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _leftStickLeft; private Key _leftStickLeft;
public Key LeftStickLeft
{
get => _leftStickLeft;
set
{
_leftStickLeft = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _leftStickRight; private Key _leftStickRight;
public Key LeftStickRight
{
get => _leftStickRight;
set
{
_leftStickRight = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _leftStickButton; private Key _leftStickButton;
public Key LeftStickButton
{
get => _leftStickButton;
set
{
_leftStickButton = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _rightStickUp; private Key _rightStickUp;
public Key RightStickUp
{
get => _rightStickUp;
set
{
_rightStickUp = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _rightStickDown; private Key _rightStickDown;
public Key RightStickDown
{
get => _rightStickDown;
set
{
_rightStickDown = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _rightStickLeft; private Key _rightStickLeft;
public Key RightStickLeft
{
get => _rightStickLeft;
set
{
_rightStickLeft = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _rightStickRight; private Key _rightStickRight;
public Key RightStickRight
{
get => _rightStickRight;
set
{
_rightStickRight = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _rightStickButton; private Key _rightStickButton;
public Key RightStickButton
{
get => _rightStickButton;
set
{
_rightStickButton = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _dpadUp; private Key _dpadUp;
public Key DpadUp
{
get => _dpadUp;
set
{
_dpadUp = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _dpadDown; private Key _dpadDown;
public Key DpadDown
{
get => _dpadDown;
set
{
_dpadDown = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _dpadLeft; private Key _dpadLeft;
public Key DpadLeft
{
get => _dpadLeft;
set
{
_dpadLeft = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _dpadRight; private Key _dpadRight;
public Key DpadRight
{
get => _dpadRight;
set
{
_dpadRight = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _buttonL; private Key _buttonL;
public Key ButtonL
{
get => _buttonL;
set
{
_buttonL = value;
OnPropertyChanged();
}
}
private Key _buttonMinus;
public Key ButtonMinus
{
get => _buttonMinus;
set
{
_buttonMinus = value;
OnPropertyChanged();
}
}
private Key _leftButtonSl;
public Key LeftButtonSl
{
get => _leftButtonSl;
set
{
_leftButtonSl = value;
OnPropertyChanged();
}
}
private Key _leftButtonSr;
public Key LeftButtonSr
{
get => _leftButtonSr;
set
{
_leftButtonSr = value;
OnPropertyChanged();
}
}
private Key _buttonZl;
public Key ButtonZl
{
get => _buttonZl;
set
{
_buttonZl = value;
OnPropertyChanged();
}
}
private Key _buttonA;
public Key ButtonA
{
get => _buttonA;
set
{
_buttonA = value;
OnPropertyChanged();
}
}
private Key _buttonB;
public Key ButtonB
{
get => _buttonB;
set
{
_buttonB = value;
OnPropertyChanged();
}
}
private Key _buttonX;
public Key ButtonX
{
get => _buttonX;
set
{
_buttonX = value;
OnPropertyChanged();
}
}
private Key _buttonY;
public Key ButtonY
{
get => _buttonY;
set
{
_buttonY = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _buttonR; private Key _buttonR;
public Key ButtonR
{
get => _buttonR;
set
{
_buttonR = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _buttonMinus;
[ObservableProperty]
private Key _buttonPlus; private Key _buttonPlus;
public Key ButtonPlus
{
get => _buttonPlus;
set
{
_buttonPlus = value;
OnPropertyChanged();
}
}
private Key _rightButtonSl; [ObservableProperty]
public Key RightButtonSl private Key _leftButtonSl;
{
get => _rightButtonSl;
set
{
_rightButtonSl = value;
OnPropertyChanged();
}
}
private Key _rightButtonSr; [ObservableProperty]
public Key RightButtonSr private Key _leftButtonSr;
{
get => _rightButtonSr;
set
{
_rightButtonSr = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private Key _buttonZl;
[ObservableProperty]
private Key _buttonZr; private Key _buttonZr;
public Key ButtonZr
{ [ObservableProperty]
get => _buttonZr; private Key _buttonA;
set
{ [ObservableProperty]
_buttonZr = value; private Key _buttonB;
OnPropertyChanged();
} [ObservableProperty]
} private Key _buttonX;
[ObservableProperty]
private Key _buttonY;
[ObservableProperty]
private Key _rightButtonSl;
[ObservableProperty]
private Key _rightButtonSr;
public KeyboardInputConfig(InputConfig config) public KeyboardInputConfig(InputConfig config)
{ {
+3 -11
View File
@@ -1,21 +1,13 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
namespace Ryujinx.Ava.UI.Models namespace Ryujinx.Ava.UI.Models
{ {
public class ModModel : BaseModel public partial class ModModel : BaseModel
{ {
[ObservableProperty]
private bool _enabled; private bool _enabled;
public bool Enabled
{
get => _enabled;
set
{
_enabled = value;
OnPropertyChanged();
}
}
public bool InSd { get; } public bool InSd { get; }
public string Path { get; } public string Path { get; }
public string Name { get; } public string Name { get; }
+5 -22
View File
@@ -1,32 +1,15 @@
using Avalonia.Media; using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
namespace Ryujinx.Ava.UI.Models namespace Ryujinx.Ava.UI.Models
{ {
public class ProfileImageModel : BaseModel public partial class ProfileImageModel(string name, byte[] data) : BaseModel
{ {
public ProfileImageModel(string name, byte[] data) public string Name { get; set; } = name;
{ public byte[] Data { get; set; } = data;
Name = name;
Data = data;
}
public string Name { get; set; }
public byte[] Data { get; set; }
[ObservableProperty]
private SolidColorBrush _backgroundColor = new(Colors.White); private SolidColorBrush _backgroundColor = new(Colors.White);
public SolidColorBrush BackgroundColor
{
get
{
return _backgroundColor;
}
set
{
_backgroundColor = value;
OnPropertyChanged();
}
}
} }
} }
+9 -29
View File
@@ -1,56 +1,36 @@
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.HLE.HOS.Services.Account.Acc; using Ryujinx.HLE.HOS.Services.Account.Acc;
using System; using System;
namespace Ryujinx.Ava.UI.Models namespace Ryujinx.Ava.UI.Models
{ {
public class TempProfile : BaseModel public partial class TempProfile : BaseModel
{ {
private readonly UserProfile _profile; [ObservableProperty]
private byte[] _image; private byte[] _image;
[ObservableProperty]
private string _name = String.Empty; private string _name = String.Empty;
private UserId _userId;
public static uint MaxProfileNameLength => 0x20; public static uint MaxProfileNameLength => 0x20;
public byte[] Image
{
get => _image;
set
{
_image = value;
OnPropertyChanged();
}
}
public UserId UserId public UserId UserId
{ {
get => _userId; get;
set set
{ {
_userId = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(UserIdString)); OnPropertyChanged(nameof(UserIdString));
} }
} }
public string UserIdString => _userId.ToString(); public string UserIdString => UserId.ToString();
public string Name
{
get => _name;
set
{
_name = value;
OnPropertyChanged();
}
}
public TempProfile(UserProfile profile) public TempProfile(UserProfile profile)
{ {
_profile = profile; if (profile != null)
if (_profile != null)
{ {
Image = profile.Image; Image = profile.Image;
Name = profile.Name; Name = profile.Name;
+12 -51
View File
@@ -1,4 +1,5 @@
using Avalonia.Media; using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Views.User; using Ryujinx.Ava.UI.Views.User;
@@ -7,66 +8,26 @@ using Profile = Ryujinx.HLE.HOS.Services.Account.Acc.UserProfile;
namespace Ryujinx.Ava.UI.Models namespace Ryujinx.Ava.UI.Models
{ {
public class UserProfile : BaseModel public partial class UserProfile : BaseModel
{ {
private readonly Profile _profile; private readonly Profile _profile;
private readonly NavigationDialogHost _owner; private readonly NavigationDialogHost _owner;
[ObservableProperty]
private byte[] _image; private byte[] _image;
[ObservableProperty]
private string _name; private string _name;
[ObservableProperty]
private UserId _userId; private UserId _userId;
[ObservableProperty]
private bool _isPointerOver; private bool _isPointerOver;
[ObservableProperty]
private IBrush _backgroundColor; private IBrush _backgroundColor;
public byte[] Image
{
get => _image;
set
{
_image = value;
OnPropertyChanged();
}
}
public UserId UserId
{
get => _userId;
set
{
_userId = value;
OnPropertyChanged();
}
}
public string Name
{
get => _name;
set
{
_name = value;
OnPropertyChanged();
}
}
public bool IsPointerOver
{
get => _isPointerOver;
set
{
_isPointerOver = value;
OnPropertyChanged();
}
}
public IBrush BackgroundColor
{
get => _backgroundColor;
set
{
_backgroundColor = value;
OnPropertyChanged();
}
}
public UserProfile(Profile profile, NavigationDialogHost owner) public UserProfile(Profile profile, NavigationDialogHost owner)
{ {
_profile = profile; _profile = profile;
@@ -1,6 +1,7 @@
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Styling; using Avalonia.Styling;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.UI.Common.Configuration; using Ryujinx.UI.Common.Configuration;
@@ -8,43 +9,17 @@ using System;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class AboutWindowViewModel : BaseModel, IDisposable public partial class AboutWindowViewModel : BaseModel, IDisposable
{ {
private Bitmap _gitlabLogo; [ObservableProperty]
private Bitmap _gitLabLogo;
[ObservableProperty]
private Bitmap _discordLogo; private Bitmap _discordLogo;
[ObservableProperty]
private string _version; private string _version;
public Bitmap GitLabLogo
{
get => _gitlabLogo;
set
{
_gitlabLogo = value;
OnPropertyChanged();
}
}
public Bitmap DiscordLogo
{
get => _discordLogo;
set
{
_discordLogo = value;
OnPropertyChanged();
}
}
public string Version
{
get => _version;
set
{
_version = value;
OnPropertyChanged();
}
}
public string FormerDevelopers => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.AboutPageDeveloperListMore, "gdkchan, Ac_K, marysaka, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, GoffyDude, TSRBerry, IsaacMarovitz"); public string FormerDevelopers => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.AboutPageDeveloperListMore, "gdkchan, Ac_K, marysaka, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, GoffyDude, TSRBerry, IsaacMarovitz");
public string Developers => "KeatonTheBot"; public string Developers => "KeatonTheBot";
+9 -7
View File
@@ -1,15 +1,17 @@
using System.ComponentModel; using CommunityToolkit.Mvvm.ComponentModel;
using System.Runtime.CompilerServices; using System;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class BaseModel : INotifyPropertyChanged public class BaseModel : ObservableObject
{ {
public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertiesChanged(string firstPropertyName, params ReadOnlySpan<string> propertyNames)
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{ {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); OnPropertyChanged(firstPropertyName);
foreach (var propertyName in propertyNames)
{
OnPropertyChanged(propertyName);
}
} }
} }
} }
@@ -1,4 +1,5 @@
using Ryujinx.UI.App.Common; using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common.Models; using Ryujinx.UI.Common.Models;
using System.Linq; using System.Linq;
@@ -6,30 +7,12 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
public partial class DlcSelectViewModel : BaseModel public partial class DlcSelectViewModel : BaseModel
{ {
[ObservableProperty]
private DownloadableContentModel[] _dlcs; private DownloadableContentModel[] _dlcs;
private DownloadableContentModel _selectedDlc;
public DownloadableContentModel[] Dlcs
{
get => _dlcs;
set
{
_dlcs = value;
OnPropertyChanged();
}
}
#nullable enable #nullable enable
public DownloadableContentModel? SelectedDlc [ObservableProperty]
{ private DownloadableContentModel? _selectedDlc;
get => _selectedDlc;
set
{
_selectedDlc = value;
OnPropertyChanged();
}
}
#nullable disable #nullable disable
public DlcSelectViewModel(ulong titleId, ApplicationLibrary appLibrary) public DlcSelectViewModel(ulong titleId, ApplicationLibrary appLibrary)
@@ -2,6 +2,7 @@ using Avalonia.Collections;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using DynamicData; using DynamicData;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
@@ -16,13 +17,18 @@ using Application = Avalonia.Application;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class DownloadableContentManagerViewModel : BaseModel public partial class DownloadableContentManagerViewModel : BaseModel
{ {
private readonly ApplicationLibrary _applicationLibrary; private readonly ApplicationLibrary _applicationLibrary;
private AvaloniaList<DownloadableContentModel> _downloadableContents = [];
[ObservableProperty]
private AvaloniaList<DownloadableContentModel> _selectedDownloadableContents = []; private AvaloniaList<DownloadableContentModel> _selectedDownloadableContents = [];
[ObservableProperty]
private AvaloniaList<DownloadableContentModel> _views = []; private AvaloniaList<DownloadableContentModel> _views = [];
private bool _showBundledContentNotice = false;
[ObservableProperty]
private bool _showBundledContentNotice;
private string _search; private string _search;
private readonly ApplicationData _applicationData; private readonly ApplicationData _applicationData;
@@ -30,35 +36,15 @@ namespace Ryujinx.Ava.UI.ViewModels
public AvaloniaList<DownloadableContentModel> DownloadableContents public AvaloniaList<DownloadableContentModel> DownloadableContents
{ {
get => _downloadableContents; get;
set set
{ {
_downloadableContents = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(UpdateCount)); OnPropertyChanged(nameof(UpdateCount));
Sort(); Sort();
} }
} } = [];
public AvaloniaList<DownloadableContentModel> Views
{
get => _views;
set
{
_views = value;
OnPropertyChanged();
}
}
public AvaloniaList<DownloadableContentModel> SelectedDownloadableContents
{
get => _selectedDownloadableContents;
set
{
_selectedDownloadableContents = value;
OnPropertyChanged();
}
}
public string Search public string Search
{ {
@@ -76,16 +62,6 @@ namespace Ryujinx.Ava.UI.ViewModels
get => string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowHeading], DownloadableContents.Count); get => string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowHeading], DownloadableContents.Count);
} }
public bool ShowBundledContentNotice
{
get => _showBundledContentNotice;
set
{
_showBundledContentNotice = value;
OnPropertyChanged();
}
}
public DownloadableContentManagerViewModel(ApplicationLibrary applicationLibrary, ApplicationData applicationData) public DownloadableContentManagerViewModel(ApplicationLibrary applicationLibrary, ApplicationData applicationData)
{ {
_applicationLibrary = applicationLibrary; _applicationLibrary = applicationLibrary;
@@ -138,8 +114,8 @@ namespace Ryujinx.Ava.UI.ViewModels
// some reason. so we save the items here and add them back after // some reason. so we save the items here and add them back after
var items = SelectedDownloadableContents.ToArray(); var items = SelectedDownloadableContents.ToArray();
_views.Clear(); Views.Clear();
_views.AddRange(view); Views.AddRange(view);
foreach (DownloadableContentModel item in items) foreach (DownloadableContentModel item in items)
{ {
@@ -1,54 +1,51 @@
using Avalonia.Svg.Skia; using Avalonia.Svg.Skia;
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.UI.Models.Input; using Ryujinx.Ava.UI.Models.Input;
using Ryujinx.Ava.UI.Views.Input; using Ryujinx.Ava.UI.Views.Input;
namespace Ryujinx.Ava.UI.ViewModels.Input namespace Ryujinx.Ava.UI.ViewModels.Input
{ {
public class ControllerInputViewModel : BaseModel public partial class ControllerInputViewModel : BaseModel
{ {
private GamepadInputConfig _config;
public GamepadInputConfig Config public GamepadInputConfig Config
{ {
get => _config; get;
set set
{ {
_config = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
private StickVisualizer _visualizer;
public StickVisualizer Visualizer public StickVisualizer Visualizer
{ {
get => _visualizer; get;
set set
{ {
_visualizer = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
private bool _isLeft;
public bool IsLeft public bool IsLeft
{ {
get => _isLeft; get;
set set
{ {
_isLeft = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(HasSides)); OnPropertyChanged(nameof(HasSides));
} }
} }
private bool _isRight;
public bool IsRight public bool IsRight
{ {
get => _isRight; get;
set set
{ {
_isRight = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(HasSides)); OnPropertyChanged(nameof(HasSides));
} }
@@ -56,16 +53,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public bool HasSides => IsLeft ^ IsRight; public bool HasSides => IsLeft ^ IsRight;
[ObservableProperty]
private SvgImage _image; private SvgImage _image;
public SvgImage Image
{
get => _image;
set
{
_image = value;
OnPropertyChanged();
}
}
public readonly InputViewModel ParentModel; public readonly InputViewModel ParentModel;
@@ -4,6 +4,7 @@ using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Svg.Skia; using Avalonia.Svg.Skia;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Input; using Ryujinx.Ava.Input;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
@@ -32,7 +33,7 @@ using Key = Ryujinx.Common.Configuration.Hid.Key;
namespace Ryujinx.Ava.UI.ViewModels.Input namespace Ryujinx.Ava.UI.ViewModels.Input
{ {
public class InputViewModel : BaseModel, IDisposable public partial class InputViewModel : BaseModel, IDisposable
{ {
private const string Disabled = "disabled"; private const string Disabled = "disabled";
private const string ProControllerResource = "Ryujinx.UI.Common/Resources/Controller_ProCon.svg"; private const string ProControllerResource = "Ryujinx.UI.Common/Resources/Controller_ProCon.svg";
@@ -48,8 +49,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
private int _controller; private int _controller;
private string _controllerImage; private string _controllerImage;
private int _device; private int _device;
private object _configViewModel;
[ObservableProperty]
private string _profileName; private string _profileName;
private bool _isLoaded; private bool _isLoaded;
private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
@@ -76,10 +79,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public object ConfigViewModel public object ConfigViewModel
{ {
get => _configViewModel; get;
set set
{ {
_configViewModel = value; field = value;
VisualStick.UpdateConfig(value); VisualStick.UpdateConfig(value);
@@ -203,16 +206,6 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
} }
} }
public string ProfileName
{
get => _profileName; set
{
_profileName = value;
OnPropertyChanged();
}
}
public int Device public int Device
{ {
get => _device; get => _device;
@@ -451,7 +444,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
const string Hyphen = "-"; const string Hyphen = "-";
const int Offset = 1; const int Offset = 1;
return str[(str.IndexOf(Hyphen) + Offset)..]; return str[(str.IndexOf(Hyphen, StringComparison.Ordinal) + Offset)..];
} }
public void LoadDevices() public void LoadDevices()
@@ -1,53 +1,50 @@
using Avalonia.Svg.Skia; using Avalonia.Svg.Skia;
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.UI.Models.Input; using Ryujinx.Ava.UI.Models.Input;
namespace Ryujinx.Ava.UI.ViewModels.Input namespace Ryujinx.Ava.UI.ViewModels.Input
{ {
public class KeyboardInputViewModel : BaseModel public partial class KeyboardInputViewModel : BaseModel
{ {
private KeyboardInputConfig _config;
public KeyboardInputConfig Config public KeyboardInputConfig Config
{ {
get => _config; get;
set set
{ {
_config = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
private StickVisualizer _visualizer;
public StickVisualizer Visualizer public StickVisualizer Visualizer
{ {
get => _visualizer; get;
set set
{ {
_visualizer = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
private bool _isLeft;
public bool IsLeft public bool IsLeft
{ {
get => _isLeft; get;
set set
{ {
_isLeft = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(HasSides)); OnPropertyChanged(nameof(HasSides));
} }
} }
private bool _isRight;
public bool IsRight public bool IsRight
{ {
get => _isRight; get;
set set
{ {
_isRight = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(HasSides)); OnPropertyChanged(nameof(HasSides));
} }
@@ -55,16 +52,8 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
public bool HasSides => IsLeft ^ IsRight; public bool HasSides => IsLeft ^ IsRight;
[ObservableProperty]
private SvgImage _image; private SvgImage _image;
public SvgImage Image
{
get => _image;
set
{
_image = value;
OnPropertyChanged();
}
}
public readonly InputViewModel ParentModel; public readonly InputViewModel ParentModel;
@@ -1,93 +1,31 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace Ryujinx.Ava.UI.ViewModels.Input namespace Ryujinx.Ava.UI.ViewModels.Input
{ {
public class MotionInputViewModel : BaseModel public partial class MotionInputViewModel : BaseModel
{ {
[ObservableProperty]
private int _slot; private int _slot;
public int Slot
{
get => _slot;
set
{
_slot = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private int _altSlot; private int _altSlot;
public int AltSlot
{
get => _altSlot;
set
{
_altSlot = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private string _dsuServerHost; private string _dsuServerHost;
public string DsuServerHost
{
get => _dsuServerHost;
set
{
_dsuServerHost = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private int _dsuServerPort; private int _dsuServerPort;
public int DsuServerPort
{
get => _dsuServerPort;
set
{
_dsuServerPort = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private bool _mirrorInput; private bool _mirrorInput;
public bool MirrorInput
{
get => _mirrorInput;
set
{
_mirrorInput = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private int _sensitivity; private int _sensitivity;
public int Sensitivity
{
get => _sensitivity;
set
{
_sensitivity = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private double _gyroDeadzone; private double _gyroDeadzone;
public double GyroDeadzone
{
get => _gyroDeadzone;
set
{
_gyroDeadzone = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private bool _enableCemuHookMotion; private bool _enableCemuHookMotion;
public bool EnableCemuHookMotion
{
get => _enableCemuHookMotion;
set
{
_enableCemuHookMotion = value;
OnPropertyChanged();
}
}
} }
} }
@@ -1,27 +1,13 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace Ryujinx.Ava.UI.ViewModels.Input namespace Ryujinx.Ava.UI.ViewModels.Input
{ {
public class RumbleInputViewModel : BaseModel public partial class RumbleInputViewModel : BaseModel
{ {
[ObservableProperty]
private float _strongRumble; private float _strongRumble;
public float StrongRumble
{
get => _strongRumble;
set
{
_strongRumble = value;
OnPropertyChanged();
}
}
[ObservableProperty]
private float _weakRumble; private float _weakRumble;
public float WeakRumble
{
get => _weakRumble;
set
{
_weakRumble = value;
OnPropertyChanged();
}
}
} }
} }
+88 -545
View File
@@ -5,6 +5,7 @@ using Avalonia.Input;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using DynamicData; using DynamicData;
using DynamicData.Binding; using DynamicData.Binding;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
@@ -50,90 +51,84 @@ using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class MainWindowViewModel : BaseModel public partial class MainWindowViewModel : BaseModel
{ {
private const int HotKeyPressDelayMs = 500; private const int HotKeyPressDelayMs = 500;
private delegate int LoadContentFromFolderDelegate(List<string> dirs, out int numRemoved); private delegate int LoadContentFromFolderDelegate(List<string> dirs, out int numRemoved);
private ObservableCollectionExtended<ApplicationData> _applications; [ObservableProperty] private ObservableCollectionExtended<ApplicationData> _applications;
private string _aspectStatusText; [ObservableProperty] private string _aspectRatioStatusText;
private string _loadHeading; [ObservableProperty] private string _loadHeading;
private string _cacheLoadStatus; [ObservableProperty] private string _cacheLoadStatus;
[ObservableProperty] private string _dockedStatusText;
[ObservableProperty] private string _fifoStatusText;
[ObservableProperty] private string _gameStatusText;
[ObservableProperty] private string _volumeStatusText;
[ObservableProperty] private string _gpuNameText;
[ObservableProperty] private string _shaderCountText;
[ObservableProperty] private bool _showRightmostSeparator;
[ObservableProperty] private bool _isFullScreen;
[ObservableProperty] private int _progressMaximum;
[ObservableProperty] private int _progressValue;
[ObservableProperty] private long _lastFullscreenToggle = Environment.TickCount64;
[ObservableProperty] private bool _showMenuAndStatusBar = true;
[ObservableProperty] private bool _showStatusSeparator;
[ObservableProperty] private Brush _progressBarForegroundColor;
[ObservableProperty] private Brush _progressBarBackgroundColor;
[ObservableProperty] private Brush _vSyncModeColor;
#nullable enable
[ObservableProperty] private byte[]? _selectedIcon;
#nullable disable
[ObservableProperty] private int _statusBarProgressMaximum;
[ObservableProperty] private int _statusBarProgressValue;
[ObservableProperty] private string _statusBarProgressStatusText;
[ObservableProperty] private bool _statusBarProgressStatusVisible;
[ObservableProperty] private bool _isPaused;
[ObservableProperty] private bool _showContent = true;
[ObservableProperty] private bool _isLoadingIndeterminate = true;
[ObservableProperty] private bool _showAll;
[ObservableProperty] private string _lastScannedAmiiboId;
[ObservableProperty] private ReadOnlyObservableCollection<ApplicationData> _appsObservableList;
[ObservableProperty] private float _volumeBeforeMute;
[ObservableProperty] private string _backendText;
[ObservableProperty] private bool _areMimeTypesRegistered = FileAssociationHelper.AreMimeTypesRegistered;
[ObservableProperty] private Cursor _cursor;
[ObservableProperty] private string _title;
[ObservableProperty] private WindowState _windowState;
[ObservableProperty] private double _windowWidth;
[ObservableProperty] private double _windowHeight;
[ObservableProperty] private bool _isActive;
[ObservableProperty] private bool _isSubMenuOpen;
private ApplicationContextMenu _listAppContextMenu;
private ApplicationContextMenu _gridAppContextMenu;
private bool _isGameRunning;
private string _searchText; private string _searchText;
private Timer _searchTimer; private Timer _searchTimer;
private string _dockedStatusText;
private string _vSyncModeText;
private string _fifoStatusText;
private string _gameStatusText;
private string _volumeStatusText;
private string _gpuStatusText;
private string _shaderCountText;
private bool _isAmiiboRequested;
private bool _showRightmostSeparator;
private bool _isAmiiboBinRequested;
private bool _isGameRunning;
private bool _isFullScreen;
private int _progressMaximum;
private int _progressValue;
private long _lastFullscreenToggle = Environment.TickCount64;
private bool _showLoadProgress;
private bool _showMenuAndStatusBar = true;
private bool _showStatusSeparator;
private Brush _progressBarForegroundColor;
private Brush _progressBarBackgroundColor;
private Brush _vSyncModeColor;
private byte[] _selectedIcon;
private bool _isAppletMenuActive;
private int _statusBarProgressMaximum;
private int _statusBarProgressValue;
private string _statusBarProgressStatusText;
private bool _statusBarProgressStatusVisible;
private bool _isPaused;
private bool _showContent = true;
private bool _isLoadingIndeterminate = true;
private bool _showAll;
private string _lastScannedAmiiboId;
private bool _statusBarVisible;
private ReadOnlyObservableCollection<ApplicationData> _appsObservableList;
private string _showUiKey = "F4"; private string _showUiKey = "F4";
private string _pauseKey = "F5"; private string _pauseKey = "F5";
private string _screenshotKey = "F8"; private string _screenshotKey = "F8";
private float _volume; private float _volume;
private float _volumeBeforeMute;
private string _backendText;
private bool _areMimeTypesRegistered = FileAssociationHelper.AreMimeTypesRegistered;
private bool _canUpdate = true;
private Cursor _cursor;
private string _title;
private ApplicationData _currentApplicationData; private ApplicationData _currentApplicationData;
private readonly AutoResetEvent _rendererWaitEvent; private readonly AutoResetEvent _rendererWaitEvent;
private WindowState _windowState;
private double _windowWidth;
private double _windowHeight;
private int _customVSyncInterval; private int _customVSyncInterval;
private int _customVSyncIntervalPercentageProxy; private int _customVSyncIntervalPercentageProxy;
private bool _isActive;
private bool _isSubMenuOpen;
private ApplicationData _listSelectedApplication;
private ApplicationData _gridSelectedApplication;
private ApplicationContextMenu _listAppContextMenu;
private ApplicationContextMenu _gridAppContextMenu;
public ApplicationData ListSelectedApplication public ApplicationData ListSelectedApplication
{ {
get => _listSelectedApplication; get;
set set
{ {
_listSelectedApplication = value; field = value;
if (_listSelectedApplication != null && _listAppContextMenu == null) if (field != null && _listAppContextMenu == null)
ListAppContextMenu = new ApplicationContextMenu(); ListAppContextMenu = new ApplicationContextMenu();
else if (_listSelectedApplication == null && _listAppContextMenu != null) else if (field == null && _listAppContextMenu != null)
ListAppContextMenu = null; ListAppContextMenu = null;
OnPropertyChanged(); OnPropertyChanged();
@@ -142,20 +137,20 @@ namespace Ryujinx.Ava.UI.ViewModels
public ApplicationData GridSelectedApplication public ApplicationData GridSelectedApplication
{ {
get => _gridSelectedApplication; get;
set set
{ {
_gridSelectedApplication = value; field = value;
if (_gridSelectedApplication != null && _gridAppContextMenu == null) if (field != null && _gridAppContextMenu == null)
GridAppContextMenu = new ApplicationContextMenu(); GridAppContextMenu = new ApplicationContextMenu();
else if (_gridSelectedApplication == null && _gridAppContextMenu != null) else if (field == null && _gridAppContextMenu != null)
GridAppContextMenu = null; GridAppContextMenu = null;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
public IEnumerable<LdnGameData> LastLdnGameData; public IEnumerable<LdnGameData> LastLdnGameData;
public MainWindow Window { get; init; } public MainWindow Window { get; init; }
@@ -169,6 +164,8 @@ namespace Ryujinx.Ava.UI.ViewModels
Applications.ToObservableChangeSet() Applications.ToObservableChangeSet()
.Filter(Filter) .Filter(Filter)
.Sort(GetComparer()) .Sort(GetComparer())
.OnItemAdded(_ => OnPropertyChanged(nameof(AppsObservableList)))
.OnItemRemoved(_ => OnPropertyChanged(nameof(AppsObservableList)))
.Bind(out _appsObservableList) .Bind(out _appsObservableList)
.Subscribe(); .Subscribe();
@@ -239,31 +236,10 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool CanUpdate public bool CanUpdate
{ {
get => _canUpdate && EnableNonGameRunningControls && Updater.CanUpdate(false); get => field && EnableNonGameRunningControls && Updater.CanUpdate(false);
set set
{ {
_canUpdate = value; field = value;
OnPropertyChanged();
}
}
public Cursor Cursor
{
get => _cursor;
set
{
_cursor = value;
OnPropertyChanged();
}
}
public ReadOnlyObservableCollection<ApplicationData> AppsObservableList
{
get => _appsObservableList;
set
{
_appsObservableList = value;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
@@ -290,34 +266,12 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public bool IsPaused
{
get => _isPaused;
set
{
_isPaused = value;
OnPropertyChanged();
}
}
public long LastFullscreenToggle
{
get => _lastFullscreenToggle;
set
{
_lastFullscreenToggle = value;
OnPropertyChanged();
}
}
public bool StatusBarVisible public bool StatusBarVisible
{ {
get => _statusBarVisible && EnableNonGameRunningControls; get => field && EnableNonGameRunningControls;
set set
{ {
_statusBarVisible = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
} }
@@ -327,17 +281,6 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool ShowFirmwareStatus => !ShowLoadProgress; public bool ShowFirmwareStatus => !ShowLoadProgress;
public bool ShowRightmostSeparator
{
get => _showRightmostSeparator;
set
{
_showRightmostSeparator = value;
OnPropertyChanged();
}
}
public bool IsGameRunning public bool IsGameRunning
{ {
get => _isGameRunning; get => _isGameRunning;
@@ -360,20 +303,20 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool IsAmiiboRequested public bool IsAmiiboRequested
{ {
get => _isAmiiboRequested && _isGameRunning; get => field && _isGameRunning;
set set
{ {
_isAmiiboRequested = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
} }
} }
public bool IsAmiiboBinRequested public bool IsAmiiboBinRequested
{ {
get => _isAmiiboBinRequested && _isGameRunning; get => field && _isGameRunning;
set set
{ {
_isAmiiboBinRequested = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
} }
@@ -383,71 +326,16 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool ShowLoadProgress public bool ShowLoadProgress
{ {
get => _showLoadProgress; get;
set set
{ {
_showLoadProgress = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(ShowFirmwareStatus)); OnPropertyChanged(nameof(ShowFirmwareStatus));
} }
} }
public string GameStatusText
{
get => _gameStatusText;
set
{
_gameStatusText = value;
OnPropertyChanged();
}
}
public bool IsFullScreen
{
get => _isFullScreen;
set
{
_isFullScreen = value;
OnPropertyChanged();
}
}
public bool IsSubMenuOpen
{
get => _isSubMenuOpen;
set
{
_isSubMenuOpen = value;
OnPropertyChanged();
}
}
public bool ShowAll
{
get => _showAll;
set
{
_showAll = value;
OnPropertyChanged();
}
}
public string LastScannedAmiiboId
{
get => _lastScannedAmiiboId;
set
{
_lastScannedAmiiboId = value;
OnPropertyChanged();
}
}
public ApplicationData SelectedApplication public ApplicationData SelectedApplication
{ {
get get
@@ -471,63 +359,8 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool CreateShortcutEnabled => !ReleaseInformation.IsFlatHubBuild; public bool CreateShortcutEnabled => !ReleaseInformation.IsFlatHubBuild;
public string LoadHeading
{
get => _loadHeading;
set
{
_loadHeading = value;
OnPropertyChanged();
}
}
public bool HasDlc => ApplicationLibrary.HasDlcs(SelectedApplication.Id); public bool HasDlc => ApplicationLibrary.HasDlcs(SelectedApplication.Id);
public string CacheLoadStatus
{
get => _cacheLoadStatus;
set
{
_cacheLoadStatus = value;
OnPropertyChanged();
}
}
public Brush ProgressBarBackgroundColor
{
get => _progressBarBackgroundColor;
set
{
_progressBarBackgroundColor = value;
OnPropertyChanged();
}
}
public Brush ProgressBarForegroundColor
{
get => _progressBarForegroundColor;
set
{
_progressBarForegroundColor = value;
OnPropertyChanged();
}
}
public Brush VSyncModeColor
{
get => _vSyncModeColor;
set
{
_vSyncModeColor = value;
OnPropertyChanged();
}
}
public bool ShowCustomVSyncIntervalPicker public bool ShowCustomVSyncIntervalPicker
{ {
get get
@@ -537,10 +370,8 @@ namespace Ryujinx.Ava.UI.ViewModels
return AppHost.Device.VSyncMode == return AppHost.Device.VSyncMode ==
VSyncMode.Custom; VSyncMode.Custom;
} }
else
{ return false;
return false;
}
} }
set set
{ {
@@ -598,165 +429,12 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public byte[] SelectedIcon
{
get => _selectedIcon;
set
{
_selectedIcon = value;
OnPropertyChanged();
}
}
public int ProgressMaximum
{
get => _progressMaximum;
set
{
_progressMaximum = value;
OnPropertyChanged();
}
}
public int ProgressValue
{
get => _progressValue;
set
{
_progressValue = value;
OnPropertyChanged();
}
}
public int StatusBarProgressMaximum
{
get => _statusBarProgressMaximum;
set
{
_statusBarProgressMaximum = value;
OnPropertyChanged();
}
}
public int StatusBarProgressValue
{
get => _statusBarProgressValue;
set
{
_statusBarProgressValue = value;
OnPropertyChanged();
}
}
public bool StatusBarProgressStatusVisible
{
get => _statusBarProgressStatusVisible;
set
{
_statusBarProgressStatusVisible = value;
OnPropertyChanged();
}
}
public string StatusBarProgressStatusText
{
get => _statusBarProgressStatusText;
set
{
_statusBarProgressStatusText = value;
OnPropertyChanged();
}
}
public string FifoStatusText
{
get => _fifoStatusText;
set
{
_fifoStatusText = value;
OnPropertyChanged();
}
}
public string GpuNameText
{
get => _gpuStatusText;
set
{
_gpuStatusText = value;
OnPropertyChanged();
}
}
public string ShaderCountText
{
get => _shaderCountText;
set
{
_shaderCountText = value;
OnPropertyChanged();
}
}
public string BackendText
{
get => _backendText;
set
{
_backendText = value;
OnPropertyChanged();
}
}
public string VSyncModeText public string VSyncModeText
{ {
get => _vSyncModeText; get;
set set
{ {
_vSyncModeText = value; field = value;
OnPropertyChanged();
}
}
public string DockedStatusText
{
get => _dockedStatusText;
set
{
_dockedStatusText = value;
OnPropertyChanged();
}
}
public string AspectRatioStatusText
{
get => _aspectStatusText;
set
{
_aspectStatusText = value;
OnPropertyChanged();
}
}
public string VolumeStatusText
{
get => _volumeStatusText;
set
{
_volumeStatusText = value;
OnPropertyChanged(); OnPropertyChanged();
} }
@@ -782,112 +460,12 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public float VolumeBeforeMute
{
get => _volumeBeforeMute;
set
{
_volumeBeforeMute = value;
OnPropertyChanged();
}
}
public bool ShowStatusSeparator
{
get => _showStatusSeparator;
set
{
_showStatusSeparator = value;
OnPropertyChanged();
}
}
public bool ShowMenuAndStatusBar
{
get => _showMenuAndStatusBar;
set
{
_showMenuAndStatusBar = value;
OnPropertyChanged();
}
}
public bool IsLoadingIndeterminate
{
get => _isLoadingIndeterminate;
set
{
_isLoadingIndeterminate = value;
OnPropertyChanged();
}
}
public bool IsActive
{
get => _isActive;
set
{
_isActive = value;
OnPropertyChanged();
}
}
public bool ShowContent
{
get => _showContent;
set
{
_showContent = value;
OnPropertyChanged();
}
}
public bool IsAppletMenuActive public bool IsAppletMenuActive
{ {
get => _isAppletMenuActive && EnableNonGameRunningControls; get => field && EnableNonGameRunningControls;
set set
{ {
_isAppletMenuActive = value; field = value;
OnPropertyChanged();
}
}
public WindowState WindowState
{
get => _windowState;
internal set
{
_windowState = value;
OnPropertyChanged();
}
}
public double WindowWidth
{
get => _windowWidth;
set
{
_windowWidth = value;
OnPropertyChanged();
}
}
public double WindowHeight
{
get => _windowHeight;
set
{
_windowHeight = value;
OnPropertyChanged(); OnPropertyChanged();
} }
@@ -949,17 +527,6 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public string Title
{
get => _title;
set
{
_title = value;
OnPropertyChanged();
}
}
public bool ShowConsoleVisible public bool ShowConsoleVisible
{ {
get => ConsoleHelper.SetConsoleWindowStateSupported; get => ConsoleHelper.SetConsoleWindowStateSupported;
@@ -970,27 +537,6 @@ namespace Ryujinx.Ava.UI.ViewModels
get => FileAssociationHelper.IsTypeAssociationSupported; get => FileAssociationHelper.IsTypeAssociationSupported;
} }
public bool AreMimeTypesRegistered
{
get => _areMimeTypesRegistered;
set {
_areMimeTypesRegistered = value;
OnPropertyChanged();
}
}
public ObservableCollectionExtended<ApplicationData> Applications
{
get => _applications;
set
{
_applications = value;
OnPropertyChanged();
}
}
public Glyph Glyph public Glyph Glyph
{ {
get => (Glyph)ConfigurationState.Instance.UI.GameListViewMode.Value; get => (Glyph)ConfigurationState.Instance.UI.GameListViewMode.Value;
@@ -1225,9 +771,10 @@ namespace Ryujinx.Ava.UI.ViewModels
Applications.ToObservableChangeSet() Applications.ToObservableChangeSet()
.Filter(Filter) .Filter(Filter)
.Sort(GetComparer()) .Sort(GetComparer())
.Bind(out _appsObservableList).AsObservableList(); .Bind(out ReadOnlyObservableCollection<ApplicationData> apps)
.AsObservableList();
OnPropertyChanged(nameof(AppsObservableList)); AppsObservableList = apps;
} }
private bool Filter(object arg) private bool Filter(object arg)
@@ -1338,7 +885,7 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
catch (MissingKeyException ex) catch (MissingKeyException ex)
{ {
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime)
{ {
Logger.Error?.Print(LogClass.Application, ex.ToString()); Logger.Error?.Print(LogClass.Application, ex.ToString());
@@ -1570,7 +1117,7 @@ namespace Ryujinx.Ava.UI.ViewModels
VSyncModeText = args.VSyncMode == "Custom" ? "Custom" : "VSync"; VSyncModeText = args.VSyncMode == "Custom" ? "Custom" : "VSync";
ShowCustomVSyncIntervalPicker = ShowCustomVSyncIntervalPicker =
args.VSyncMode == VSyncMode.Custom.ToString(); args.VSyncMode == nameof(VSyncMode.Custom);
DockedStatusText = args.DockedMode; DockedStatusText = args.DockedMode;
AspectRatioStatusText = args.AspectRatio; AspectRatioStatusText = args.AspectRatio;
GameStatusText = args.GameStatus; GameStatusText = args.GameStatus;
@@ -1604,7 +1151,7 @@ namespace Ryujinx.Ava.UI.ViewModels
var dirs = result.Select(it => it.Path.LocalPath).ToList(); var dirs = result.Select(it => it.Path.LocalPath).ToList();
var numAdded = onDirsSelected(dirs, out int numRemoved); var numAdded = onDirsSelected(dirs, out int numRemoved);
var msg = String.Join("\r\n", new string[] { var msg = String.Join("\r\n", new[] {
string.Format(LocaleManager.Instance[localeMessageRemovedKey], numRemoved), string.Format(LocaleManager.Instance[localeMessageRemovedKey], numRemoved),
string.Format(LocaleManager.Instance[localeMessageAddedKey], numAdded) string.Format(LocaleManager.Instance[localeMessageAddedKey], numAdded)
}); });
@@ -2288,11 +1835,7 @@ namespace Ryujinx.Ava.UI.ViewModels
switch (operationOutcome) switch (operationOutcome)
{ {
case XCIFileTrimmer.OperationOutcome.Successful: case XCIFileTrimmer.OperationOutcome.Successful:
if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) App.MainWindow.LoadApplications();
{
if (desktop.MainWindow is MainWindow mainWindow)
mainWindow.LoadApplications();
}
break; break;
} }
} }
@@ -3,6 +3,7 @@ using Avalonia.Collections;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using DynamicData; using DynamicData;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
@@ -18,12 +19,14 @@ using System.Linq;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class ModManagerViewModel : BaseModel public partial class ModManagerViewModel : BaseModel
{ {
private readonly string _modJsonPath; private readonly string _modJsonPath;
private AvaloniaList<ModModel> _mods = []; [ObservableProperty]
private AvaloniaList<ModModel> _views = []; private AvaloniaList<ModModel> _views = [];
[ObservableProperty]
private AvaloniaList<ModModel> _selectedMods = []; private AvaloniaList<ModModel> _selectedMods = [];
private string _search; private string _search;
@@ -35,35 +38,15 @@ namespace Ryujinx.Ava.UI.ViewModels
public AvaloniaList<ModModel> Mods public AvaloniaList<ModModel> Mods
{ {
get => _mods; get;
set set
{ {
_mods = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(ModCount)); OnPropertyChanged(nameof(ModCount));
Sort(); Sort();
} }
} } = [];
public AvaloniaList<ModModel> Views
{
get => _views;
set
{
_views = value;
OnPropertyChanged();
}
}
public AvaloniaList<ModModel> SelectedMods
{
get => _selectedMods;
set
{
_selectedMods = value;
OnPropertyChanged();
}
}
public string Search public string Search
{ {
@@ -112,7 +95,7 @@ namespace Ryujinx.Ava.UI.ViewModels
var inSd = path == ModLoader.GetSdModsBasePath(); var inSd = path == ModLoader.GetSdModsBasePath();
var modCache = new ModLoader.ModCache(); var modCache = new ModLoader.ModCache();
ModLoader.QueryContentsDir(modCache, new DirectoryInfo(Path.Combine(path, "contents")), applicationId, _installedDlcIds); ModLoader.QueryContentsDir(modCache, new DirectoryInfo(Path.Combine(path, "contents")), applicationId, installedDlcIds);
foreach (var mod in modCache.RomfsDirs) foreach (var mod in modCache.RomfsDirs)
{ {
@@ -161,8 +144,8 @@ namespace Ryujinx.Ava.UI.ViewModels
.Filter(Filter) .Filter(Filter)
.Bind(out var view).AsObservableList(); .Bind(out var view).AsObservableList();
_views.Clear(); Views.Clear();
_views.AddRange(view); Views.AddRange(view);
SelectedMods = new(Views.Where(x => x.Enabled)); SelectedMods = new(Views.Where(x => x.Enabled));
+47 -74
View File
@@ -1,6 +1,7 @@
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem;
using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.OpenAL;
using Ryujinx.Audio.Backends.SDL2; using Ryujinx.Audio.Backends.SDL2;
@@ -41,34 +42,27 @@ namespace Ryujinx.Ava.UI.ViewModels
private readonly Dictionary<string, string> _networkInterfaces; private readonly Dictionary<string, string> _networkInterfaces;
private float _customResolutionScale;
private int _resolutionScale; private int _resolutionScale;
private int _graphicsBackendMultithreadingIndex;
private float _volume; [ObservableProperty]
private bool _isVulkanAvailable = true; private bool _isVulkanAvailable = true;
private bool _gameDirectoryChanged; private bool _gameDirectoryChanged;
private bool _autoloadDirectoryChanged; private bool _autoloadDirectoryChanged;
private readonly List<string> _gpuIds = new(); private readonly List<string> _gpuIds = [];
private int _graphicsBackendIndex;
private int _scalingFilter; private int _scalingFilter;
private int _scalingFilterLevel;
private int _customVSyncInterval; private int _customVSyncInterval;
private bool _enableCustomVSyncInterval;
private int _customVSyncIntervalPercentageProxy; private int _customVSyncIntervalPercentageProxy;
private VSyncMode _vSyncMode; private VSyncMode _vSyncMode;
private long _turboModeMultiplier;
public event Action CloseWindow; public event Action CloseWindow;
public event Action SaveSettingsEvent; public event Action SaveSettingsEvent;
private int _networkInterfaceIndex;
private int _multiplayerModeIndex;
private string _ldnPassphrase;
private string _LdnServer; private string _LdnServer;
[ObservableProperty]
private bool _matchSystemTime; private bool _matchSystemTime;
private bool _enableGDBStub; private bool _enableGDBStub;
private ushort _gdbStubPort;
private bool _debuggerSuspendOnStart;
public int ResolutionScale public int ResolutionScale
{ {
@@ -84,15 +78,15 @@ namespace Ryujinx.Ava.UI.ViewModels
public int GraphicsBackendMultithreadingIndex public int GraphicsBackendMultithreadingIndex
{ {
get => _graphicsBackendMultithreadingIndex; get;
set set
{ {
_graphicsBackendMultithreadingIndex = value; field = value;
if (_graphicsBackendMultithreadingIndex != (int)ConfigurationState.Instance.Graphics.BackendThreading.Value) if (field != (int)ConfigurationState.Instance.Graphics.BackendThreading.Value)
{ {
Dispatcher.UIThread.InvokeAsync(() => Dispatcher.UIThread.InvokeAsync(() =>
ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningMessage], ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningMessage],
"", "",
"", "",
LocaleManager.Instance[LocaleKeys.InputDialogOk], LocaleManager.Instance[LocaleKeys.InputDialogOk],
@@ -106,21 +100,10 @@ namespace Ryujinx.Ava.UI.ViewModels
public float CustomResolutionScale public float CustomResolutionScale
{ {
get => _customResolutionScale; get;
set set
{ {
_customResolutionScale = value; field = value;
OnPropertyChanged();
}
}
public bool IsVulkanAvailable
{
get => _isVulkanAvailable;
set
{
_isVulkanAvailable = value;
OnPropertyChanged(); OnPropertyChanged();
} }
@@ -201,10 +184,10 @@ namespace Ryujinx.Ava.UI.ViewModels
public bool EnableCustomVSyncInterval public bool EnableCustomVSyncInterval
{ {
get => _enableCustomVSyncInterval; get;
set set
{ {
_enableCustomVSyncInterval = value; field = value;
if (_vSyncMode == VSyncMode.Custom && !value) if (_vSyncMode == VSyncMode.Custom && !value)
{ {
VSyncMode = VSyncMode.Switch; VSyncMode = VSyncMode.Switch;
@@ -213,6 +196,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
VSyncMode = VSyncMode.Custom; VSyncMode = VSyncMode.Custom;
} }
OnPropertyChanged(); OnPropertyChanged();
} }
} }
@@ -232,23 +216,22 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
public bool EnablePptc { get; set; } public bool EnablePptc { get; set; }
public bool EnableLowPowerPptc { get; set; } public bool EnableLowPowerPptc { get; set; }
public long TurboMultiplier public long TurboMultiplier
{ {
get => _turboModeMultiplier; get;
set set
{ {
if (_turboModeMultiplier != value) if (field != value)
{ {
_turboModeMultiplier = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged((nameof(TurboMultiplierPercentageText))); OnPropertyChanged((nameof(TurboMultiplierPercentageText)));
} }
} }
} }
public string TurboMultiplierPercentageText => $"{TurboMultiplier}%"; public string TurboMultiplierPercentageText => $"{TurboMultiplier}%";
public bool EnableInternetAccess { get; set; } public bool EnableInternetAccess { get; set; }
@@ -284,10 +267,10 @@ namespace Ryujinx.Ava.UI.ViewModels
public string LdnPassphrase public string LdnPassphrase
{ {
get => _ldnPassphrase; get;
set set
{ {
_ldnPassphrase = value; field = value;
IsInvalidLdnPassphraseVisible = !ValidateLdnPassphrase(value); IsInvalidLdnPassphraseVisible = !ValidateLdnPassphrase(value);
OnPropertyChanged(); OnPropertyChanged();
@@ -308,29 +291,33 @@ namespace Ryujinx.Ava.UI.ViewModels
public int AspectRatio { get; set; } public int AspectRatio { get; set; }
public int AntiAliasingEffect { get; set; } public int AntiAliasingEffect { get; set; }
public string ScalingFilterLevelText => ScalingFilterLevel.ToString("0"); public string ScalingFilterLevelText => ScalingFilterLevel.ToString("0");
public int ScalingFilterLevel public int ScalingFilterLevel
{ {
get => _scalingFilterLevel; get;
set set
{ {
_scalingFilterLevel = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(ScalingFilterLevelText)); OnPropertyChanged(nameof(ScalingFilterLevelText));
} }
} }
public int OpenglDebugLevel { get; set; } public int OpenglDebugLevel { get; set; }
public int MemoryMode { get; set; } public int MemoryMode { get; set; }
public int BaseStyleIndex { get; set; } public int BaseStyleIndex { get; set; }
public int GraphicsBackendIndex public int GraphicsBackendIndex
{ {
get => _graphicsBackendIndex; get;
set set
{ {
_graphicsBackendIndex = value; field = value;
OnPropertyChanged(); OnPropertyChanged();
OnPropertyChanged(nameof(IsVulkanSelected)); OnPropertyChanged(nameof(IsVulkanSelected));
} }
} }
public int ScalingFilter public int ScalingFilter
{ {
get => _scalingFilter; get => _scalingFilter;
@@ -346,26 +333,12 @@ namespace Ryujinx.Ava.UI.ViewModels
public float Volume public float Volume
{ {
get => _volume; get;
set set
{ {
_volume = value; field = value;
ConfigurationState.Instance.System.AudioVolume.Value = _volume / 100; ConfigurationState.Instance.System.AudioVolume.Value = field / 100;
OnPropertyChanged();
}
}
//private DateTimeOffset _currentDate;
//private TimeSpan _currentTime;
public bool MatchSystemTime
{
get => _matchSystemTime;
set
{
_matchSystemTime = value;
OnPropertyChanged(); OnPropertyChanged();
} }
@@ -389,21 +362,21 @@ namespace Ryujinx.Ava.UI.ViewModels
public int NetworkInterfaceIndex public int NetworkInterfaceIndex
{ {
get => _networkInterfaceIndex; get;
set set
{ {
_networkInterfaceIndex = value != -1 ? value : 0; field = value != -1 ? value : 0;
ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value = _networkInterfaces[NetworkInterfaceList[_networkInterfaceIndex]]; ConfigurationState.Instance.Multiplayer.LanInterfaceId.Value = _networkInterfaces[NetworkInterfaceList[field]];
} }
} }
public int MultiplayerModeIndex public int MultiplayerModeIndex
{ {
get => _multiplayerModeIndex; get;
set set
{ {
_multiplayerModeIndex = value; field = value;
ConfigurationState.Instance.Multiplayer.Mode.Value = (MultiplayerMode)_multiplayerModeIndex; ConfigurationState.Instance.Multiplayer.Mode.Value = (MultiplayerMode)field;
} }
} }
@@ -434,21 +407,21 @@ namespace Ryujinx.Ava.UI.ViewModels
public ushort GDBStubPort public ushort GDBStubPort
{ {
get => _gdbStubPort; get;
set set
{ {
_gdbStubPort = value; field = value;
ConfigurationState.Instance.Debug.GdbStubPort.Value = _gdbStubPort; ConfigurationState.Instance.Debug.GdbStubPort.Value = field;
} }
} }
public bool DebuggerSuspendOnStart public bool DebuggerSuspendOnStart
{ {
get => _debuggerSuspendOnStart; get;
set set
{ {
_debuggerSuspendOnStart = value; field = value;
ConfigurationState.Instance.Debug.DebuggerSuspendOnStart.Value = _debuggerSuspendOnStart; ConfigurationState.Instance.Debug.DebuggerSuspendOnStart.Value = field;
} }
} }
@@ -2,6 +2,7 @@ using Avalonia.Collections;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
@@ -15,57 +16,24 @@ using Application = Avalonia.Application;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public record TitleUpdateViewNoUpdateSentinal(); public record TitleUpdateViewNoUpdateSentinal;
public class TitleUpdateViewModel : BaseModel public partial class TitleUpdateViewModel : BaseModel
{ {
private ApplicationLibrary ApplicationLibrary { get; } private ApplicationLibrary ApplicationLibrary { get; }
private ApplicationData ApplicationData { get; } private ApplicationData ApplicationData { get; }
[ObservableProperty]
private AvaloniaList<TitleUpdateModel> _titleUpdates = []; private AvaloniaList<TitleUpdateModel> _titleUpdates = [];
[ObservableProperty]
private AvaloniaList<object> _views = []; private AvaloniaList<object> _views = [];
[ObservableProperty]
private object _selectedUpdate = new TitleUpdateViewNoUpdateSentinal(); private object _selectedUpdate = new TitleUpdateViewNoUpdateSentinal();
private bool _showBundledContentNotice = false;
public AvaloniaList<TitleUpdateModel> TitleUpdates [ObservableProperty]
{ private bool _showBundledContentNotice;
get => _titleUpdates;
set
{
_titleUpdates = value;
OnPropertyChanged();
}
}
public AvaloniaList<object> Views
{
get => _views;
set
{
_views = value;
OnPropertyChanged();
}
}
public object SelectedUpdate
{
get => _selectedUpdate;
set
{
_selectedUpdate = value;
OnPropertyChanged();
}
}
public bool ShowBundledContentNotice
{
get => _showBundledContentNotice;
set
{
_showBundledContentNotice = value;
OnPropertyChanged();
}
}
public IStorageProvider StorageProvider; public IStorageProvider StorageProvider;
@@ -1,4 +1,5 @@
using Avalonia.Media; using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using LibHac.Common; using LibHac.Common;
using LibHac.Fs; using LibHac.Fs;
using LibHac.Fs.Fsa; using LibHac.Fs.Fsa;
@@ -20,58 +21,38 @@ using Image = SkiaSharp.SKImage;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
internal class UserFirmwareAvatarSelectorViewModel : BaseModel internal partial class UserFirmwareAvatarSelectorViewModel : BaseModel
{ {
private static readonly Dictionary<string, byte[]> _avatarStore = new(); private static readonly Dictionary<string, byte[]> _avatarStore = new();
[ObservableProperty]
private ObservableCollection<ProfileImageModel> _images; private ObservableCollection<ProfileImageModel> _images;
private Color _backgroundColor = Colors.White;
private int _selectedIndex; [ObservableProperty]
private Color _backgroundColor = Colors.White;
public UserFirmwareAvatarSelectorViewModel() public UserFirmwareAvatarSelectorViewModel()
{ {
_images = []; _images = [];
LoadImagesFromStore(); LoadImagesFromStore();
} PropertyChanged += (_, args) =>
public Color BackgroundColor
{
get => _backgroundColor;
set
{ {
_backgroundColor = value; if (args.PropertyName == nameof(BackgroundColor))
OnPropertyChanged(); ChangeImageBackground();
ChangeImageBackground(); };
}
}
public ObservableCollection<ProfileImageModel> Images
{
get => _images;
set
{
_images = value;
OnPropertyChanged();
}
} }
public int SelectedIndex public int SelectedIndex
{ {
get => _selectedIndex; get;
set set
{ {
_selectedIndex = value; field = value;
if (_selectedIndex == -1) SelectedImage = field == -1
{ ? null
SelectedImage = null; : Images[field].Data;
}
else
{
SelectedImage = _images[_selectedIndex].Data;
}
OnPropertyChanged(); OnPropertyChanged();
} }
@@ -1,18 +1,10 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
internal class UserProfileImageSelectorViewModel : BaseModel internal partial class UserProfileImageSelectorViewModel : BaseModel
{ {
[ObservableProperty]
private bool _firmwareFound; private bool _firmwareFound;
public bool FirmwareFound
{
get => _firmwareFound;
set
{
_firmwareFound = value;
OnPropertyChanged();
}
}
} }
} }
@@ -1,3 +1,4 @@
using CommunityToolkit.Mvvm.ComponentModel;
using DynamicData; using DynamicData;
using DynamicData.Binding; using DynamicData.Binding;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
@@ -8,74 +9,41 @@ using System.Collections.ObjectModel;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class UserSaveManagerViewModel : BaseModel public partial class UserSaveManagerViewModel : BaseModel
{ {
[ObservableProperty]
private int _sortIndex; private int _sortIndex;
[ObservableProperty]
private int _orderIndex; private int _orderIndex;
[ObservableProperty]
private string _search; private string _search;
[ObservableProperty]
private ObservableCollection<SaveModel> _saves = []; private ObservableCollection<SaveModel> _saves = [];
[ObservableProperty]
private ObservableCollection<SaveModel> _views = []; private ObservableCollection<SaveModel> _views = [];
private readonly AccountManager _accountManager; private readonly AccountManager _accountManager;
public string SaveManagerHeading => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SaveManagerHeading, _accountManager.LastOpenedUser.Name, _accountManager.LastOpenedUser.UserId); public string SaveManagerHeading => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SaveManagerHeading, _accountManager.LastOpenedUser.Name, _accountManager.LastOpenedUser.UserId);
public int SortIndex
{
get => _sortIndex;
set
{
_sortIndex = value;
OnPropertyChanged();
Sort();
}
}
public int OrderIndex
{
get => _orderIndex;
set
{
_orderIndex = value;
OnPropertyChanged();
Sort();
}
}
public string Search
{
get => _search;
set
{
_search = value;
OnPropertyChanged();
Sort();
}
}
public ObservableCollection<SaveModel> Saves
{
get => _saves;
set
{
_saves = value;
OnPropertyChanged();
Sort();
}
}
public ObservableCollection<SaveModel> Views
{
get => _views;
set
{
_views = value;
OnPropertyChanged();
}
}
public UserSaveManagerViewModel(AccountManager accountManager) public UserSaveManagerViewModel(AccountManager accountManager)
{ {
_accountManager = accountManager; _accountManager = accountManager;
PropertyChanged += (_, evt) =>
{
if (evt.PropertyName is
nameof(SortIndex) or
nameof(OrderIndex) or
nameof(Search) or
nameof(Saves))
{
Sort();
}
};
} }
public void Sort() public void Sort()
@@ -85,8 +53,8 @@ namespace Ryujinx.Ava.UI.ViewModels
.Sort(GetComparer()) .Sort(GetComparer())
.Bind(out var view).AsObservableList(); .Bind(out var view).AsObservableList();
_views.Clear(); Views.Clear();
_views.AddRange(view); Views.AddRange(view);
OnPropertyChanged(nameof(Views)); OnPropertyChanged(nameof(Views));
} }
@@ -94,7 +62,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
if (arg is SaveModel save) if (arg is SaveModel save)
{ {
return string.IsNullOrWhiteSpace(_search) || save.Title.ToLower().Contains(_search.ToLower()); return string.IsNullOrWhiteSpace(Search) || save.Title.ToLower().Contains(Search.ToLower());
} }
return false; return false;