infra: Make Avalonia the default UI (#6375)

* misc: Move Ryujinx project to Ryujinx.Gtk3

This breaks release CI for now but that's fine.

Signed-off-by: Mary Guillemard <mary@mary.zone>

* misc: Move Ryujinx.Ava project to Ryujinx

This breaks CI for now, but it's fine.

Signed-off-by: Mary Guillemard <mary@mary.zone>

* infra: Make Avalonia the default UI

Should fix CI after the previous changes.

GTK3 isn't build by the release job anymore, only by PR CI.

This also ensure that the test-ava update package is still generated to
allow update from the old testing channel.

Signed-off-by: Mary Guillemard <mary@mary.zone>

* Fix missing copy in create_app_bundle.sh

Signed-off-by: Mary Guillemard <mary@mary.zone>

* Fix syntax error

Signed-off-by: Mary Guillemard <mary@mary.zone>

---------

Signed-off-by: Mary Guillemard <mary@mary.zone>
This commit is contained in:
Mary Guillemard 2024-03-02 12:51:05 +01:00 committed by GitHub
parent 53b5985da6
commit ec6cb0abb4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
239 changed files with 1235 additions and 1232 deletions

View file

@ -0,0 +1,57 @@
using Ryujinx.Ava.UI.ViewModels;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.Linq;
namespace Ryujinx.Ava.UI.Models
{
public class CheatNode : BaseModel
{
private bool _isEnabled = false;
public ObservableCollection<CheatNode> SubNodes { get; } = new();
public string CleanName => Name[1..^7];
public string BuildIdKey => $"{BuildId}-{Name}";
public bool IsRootNode { get; }
public string Name { get; }
public string BuildId { get; }
public string Path { get; }
public bool IsEnabled
{
get
{
if (SubNodes.Count > 0)
{
return SubNodes.ToList().TrueForAll(x => x.IsEnabled);
}
return _isEnabled;
}
set
{
foreach (var cheat in SubNodes)
{
cheat.IsEnabled = value;
cheat.OnPropertyChanged();
}
_isEnabled = value;
}
}
public CheatNode(string name, string buildId, string path, bool isRootNode, bool isEnabled = false)
{
Name = name;
BuildId = buildId;
Path = path;
IsEnabled = isEnabled;
IsRootNode = isRootNode;
SubNodes.CollectionChanged += CheatsList_CollectionChanged;
}
private void CheatsList_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
OnPropertyChanged(nameof(IsEnabled));
}
}
}

View file

@ -0,0 +1,6 @@
using Ryujinx.Common.Configuration.Hid;
namespace Ryujinx.Ava.UI.Models
{
internal record ControllerModel(ControllerType Type, string Name);
}

View file

@ -0,0 +1,9 @@
namespace Ryujinx.Ava.UI.Models
{
public enum DeviceType
{
None,
Keyboard,
Controller,
}
}

View file

@ -0,0 +1,35 @@
using Ryujinx.Ava.UI.ViewModels;
using System.IO;
namespace Ryujinx.Ava.UI.Models
{
public class DownloadableContentModel : BaseModel
{
private bool _enabled;
public bool Enabled
{
get => _enabled;
set
{
_enabled = value;
OnPropertyChanged();
}
}
public string TitleId { get; }
public string ContainerPath { get; }
public string FullPath { get; }
public string FileName => Path.GetFileName(ContainerPath);
public DownloadableContentModel(string titleId, string containerPath, string fullPath, bool enabled)
{
TitleId = titleId;
ContainerPath = containerPath;
FullPath = fullPath;
Enabled = enabled;
}
}
}

View file

@ -0,0 +1,31 @@
using Ryujinx.UI.App.Common;
using System;
using System.Collections.Generic;
namespace Ryujinx.Ava.UI.Models.Generic
{
internal class LastPlayedSortComparer : IComparer<ApplicationData>
{
public LastPlayedSortComparer() { }
public LastPlayedSortComparer(bool isAscending) { IsAscending = isAscending; }
public bool IsAscending { get; }
public int Compare(ApplicationData x, ApplicationData y)
{
DateTime aValue = DateTime.UnixEpoch, bValue = DateTime.UnixEpoch;
if (x?.LastPlayed != null)
{
aValue = x.LastPlayed.Value;
}
if (y?.LastPlayed != null)
{
bValue = y.LastPlayed.Value;
}
return (IsAscending ? 1 : -1) * DateTime.Compare(aValue, bValue);
}
}
}

View file

@ -0,0 +1,31 @@
using Ryujinx.UI.App.Common;
using System;
using System.Collections.Generic;
namespace Ryujinx.Ava.UI.Models.Generic
{
internal class TimePlayedSortComparer : IComparer<ApplicationData>
{
public TimePlayedSortComparer() { }
public TimePlayedSortComparer(bool isAscending) { IsAscending = isAscending; }
public bool IsAscending { get; }
public int Compare(ApplicationData x, ApplicationData y)
{
TimeSpan aValue = TimeSpan.Zero, bValue = TimeSpan.Zero;
if (x?.TimePlayed != null)
{
aValue = x.TimePlayed;
}
if (y?.TimePlayed != null)
{
bValue = y.TimePlayed;
}
return (IsAscending ? 1 : -1) * TimeSpan.Compare(aValue, bValue);
}
}
}

View file

@ -0,0 +1,456 @@
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Configuration.Hid.Controller.Motion;
using Ryujinx.Common.Configuration.Hid.Keyboard;
using System;
namespace Ryujinx.Ava.UI.Models
{
internal class InputConfiguration<TKey, TStick> : BaseModel
{
private float _deadzoneRight;
private float _triggerThreshold;
private float _deadzoneLeft;
private double _gyroDeadzone;
private int _sensitivity;
private bool _enableMotion;
private float _weakRumble;
private float _strongRumble;
private float _rangeLeft;
private float _rangeRight;
public InputBackendType Backend { get; set; }
/// <summary>
/// Controller id
/// </summary>
public string Id { get; set; }
/// <summary>
/// Controller's Type
/// </summary>
public ControllerType ControllerType { get; set; }
/// <summary>
/// Player's Index for the controller
/// </summary>
public PlayerIndex PlayerIndex { get; set; }
public TStick LeftJoystick { get; set; }
public bool LeftInvertStickX { get; set; }
public bool LeftInvertStickY { get; set; }
public bool RightRotate90 { get; set; }
public TKey LeftControllerStickButton { get; set; }
public TStick RightJoystick { get; set; }
public bool RightInvertStickX { get; set; }
public bool RightInvertStickY { get; set; }
public bool LeftRotate90 { get; set; }
public TKey RightControllerStickButton { get; set; }
public float DeadzoneLeft
{
get => _deadzoneLeft;
set
{
_deadzoneLeft = MathF.Round(value, 3);
OnPropertyChanged();
}
}
public float RangeLeft
{
get => _rangeLeft;
set
{
_rangeLeft = MathF.Round(value, 3);
OnPropertyChanged();
}
}
public float DeadzoneRight
{
get => _deadzoneRight;
set
{
_deadzoneRight = MathF.Round(value, 3);
OnPropertyChanged();
}
}
public float RangeRight
{
get => _rangeRight;
set
{
_rangeRight = MathF.Round(value, 3);
OnPropertyChanged();
}
}
public float TriggerThreshold
{
get => _triggerThreshold;
set
{
_triggerThreshold = MathF.Round(value, 3);
OnPropertyChanged();
}
}
public MotionInputBackendType MotionBackend { get; set; }
public TKey ButtonMinus { get; set; }
public TKey ButtonL { get; set; }
public TKey ButtonZl { get; set; }
public TKey LeftButtonSl { get; set; }
public TKey LeftButtonSr { get; set; }
public TKey DpadUp { get; set; }
public TKey DpadDown { get; set; }
public TKey DpadLeft { get; set; }
public TKey DpadRight { get; set; }
public TKey ButtonPlus { get; set; }
public TKey ButtonR { get; set; }
public TKey ButtonZr { get; set; }
public TKey RightButtonSl { get; set; }
public TKey RightButtonSr { get; set; }
public TKey ButtonX { get; set; }
public TKey ButtonB { get; set; }
public TKey ButtonY { get; set; }
public TKey ButtonA { get; set; }
public TKey LeftStickUp { get; set; }
public TKey LeftStickDown { get; set; }
public TKey LeftStickLeft { get; set; }
public TKey LeftStickRight { get; set; }
public TKey LeftKeyboardStickButton { get; set; }
public TKey RightStickUp { get; set; }
public TKey RightStickDown { get; set; }
public TKey RightStickLeft { get; set; }
public TKey RightStickRight { get; set; }
public TKey RightKeyboardStickButton { get; set; }
public int Sensitivity
{
get => _sensitivity;
set
{
_sensitivity = value;
OnPropertyChanged();
}
}
public double GyroDeadzone
{
get => _gyroDeadzone;
set
{
_gyroDeadzone = Math.Round(value, 3);
OnPropertyChanged();
}
}
public bool EnableMotion
{
get => _enableMotion; set
{
_enableMotion = value;
OnPropertyChanged();
}
}
public bool EnableCemuHookMotion { get; set; }
public int Slot { get; set; }
public int AltSlot { get; set; }
public bool MirrorInput { get; set; }
public string DsuServerHost { get; set; }
public int DsuServerPort { get; set; }
public bool EnableRumble { get; set; }
public float WeakRumble
{
get => _weakRumble; set
{
_weakRumble = value;
OnPropertyChanged();
}
}
public float StrongRumble
{
get => _strongRumble; set
{
_strongRumble = value;
OnPropertyChanged();
}
}
public InputConfiguration(InputConfig config)
{
if (config != null)
{
Backend = config.Backend;
Id = config.Id;
ControllerType = config.ControllerType;
PlayerIndex = config.PlayerIndex;
if (config is StandardKeyboardInputConfig keyboardConfig)
{
LeftStickUp = (TKey)(object)keyboardConfig.LeftJoyconStick.StickUp;
LeftStickDown = (TKey)(object)keyboardConfig.LeftJoyconStick.StickDown;
LeftStickLeft = (TKey)(object)keyboardConfig.LeftJoyconStick.StickLeft;
LeftStickRight = (TKey)(object)keyboardConfig.LeftJoyconStick.StickRight;
LeftKeyboardStickButton = (TKey)(object)keyboardConfig.LeftJoyconStick.StickButton;
RightStickUp = (TKey)(object)keyboardConfig.RightJoyconStick.StickUp;
RightStickDown = (TKey)(object)keyboardConfig.RightJoyconStick.StickDown;
RightStickLeft = (TKey)(object)keyboardConfig.RightJoyconStick.StickLeft;
RightStickRight = (TKey)(object)keyboardConfig.RightJoyconStick.StickRight;
RightKeyboardStickButton = (TKey)(object)keyboardConfig.RightJoyconStick.StickButton;
ButtonA = (TKey)(object)keyboardConfig.RightJoycon.ButtonA;
ButtonB = (TKey)(object)keyboardConfig.RightJoycon.ButtonB;
ButtonX = (TKey)(object)keyboardConfig.RightJoycon.ButtonX;
ButtonY = (TKey)(object)keyboardConfig.RightJoycon.ButtonY;
ButtonR = (TKey)(object)keyboardConfig.RightJoycon.ButtonR;
RightButtonSl = (TKey)(object)keyboardConfig.RightJoycon.ButtonSl;
RightButtonSr = (TKey)(object)keyboardConfig.RightJoycon.ButtonSr;
ButtonZr = (TKey)(object)keyboardConfig.RightJoycon.ButtonZr;
ButtonPlus = (TKey)(object)keyboardConfig.RightJoycon.ButtonPlus;
DpadUp = (TKey)(object)keyboardConfig.LeftJoycon.DpadUp;
DpadDown = (TKey)(object)keyboardConfig.LeftJoycon.DpadDown;
DpadLeft = (TKey)(object)keyboardConfig.LeftJoycon.DpadLeft;
DpadRight = (TKey)(object)keyboardConfig.LeftJoycon.DpadRight;
ButtonMinus = (TKey)(object)keyboardConfig.LeftJoycon.ButtonMinus;
LeftButtonSl = (TKey)(object)keyboardConfig.LeftJoycon.ButtonSl;
LeftButtonSr = (TKey)(object)keyboardConfig.LeftJoycon.ButtonSr;
ButtonZl = (TKey)(object)keyboardConfig.LeftJoycon.ButtonZl;
ButtonL = (TKey)(object)keyboardConfig.LeftJoycon.ButtonL;
}
else if (config is StandardControllerInputConfig controllerConfig)
{
LeftJoystick = (TStick)(object)controllerConfig.LeftJoyconStick.Joystick;
LeftInvertStickX = controllerConfig.LeftJoyconStick.InvertStickX;
LeftInvertStickY = controllerConfig.LeftJoyconStick.InvertStickY;
LeftRotate90 = controllerConfig.LeftJoyconStick.Rotate90CW;
LeftControllerStickButton = (TKey)(object)controllerConfig.LeftJoyconStick.StickButton;
RightJoystick = (TStick)(object)controllerConfig.RightJoyconStick.Joystick;
RightInvertStickX = controllerConfig.RightJoyconStick.InvertStickX;
RightInvertStickY = controllerConfig.RightJoyconStick.InvertStickY;
RightRotate90 = controllerConfig.RightJoyconStick.Rotate90CW;
RightControllerStickButton = (TKey)(object)controllerConfig.RightJoyconStick.StickButton;
ButtonA = (TKey)(object)controllerConfig.RightJoycon.ButtonA;
ButtonB = (TKey)(object)controllerConfig.RightJoycon.ButtonB;
ButtonX = (TKey)(object)controllerConfig.RightJoycon.ButtonX;
ButtonY = (TKey)(object)controllerConfig.RightJoycon.ButtonY;
ButtonR = (TKey)(object)controllerConfig.RightJoycon.ButtonR;
RightButtonSl = (TKey)(object)controllerConfig.RightJoycon.ButtonSl;
RightButtonSr = (TKey)(object)controllerConfig.RightJoycon.ButtonSr;
ButtonZr = (TKey)(object)controllerConfig.RightJoycon.ButtonZr;
ButtonPlus = (TKey)(object)controllerConfig.RightJoycon.ButtonPlus;
DpadUp = (TKey)(object)controllerConfig.LeftJoycon.DpadUp;
DpadDown = (TKey)(object)controllerConfig.LeftJoycon.DpadDown;
DpadLeft = (TKey)(object)controllerConfig.LeftJoycon.DpadLeft;
DpadRight = (TKey)(object)controllerConfig.LeftJoycon.DpadRight;
ButtonMinus = (TKey)(object)controllerConfig.LeftJoycon.ButtonMinus;
LeftButtonSl = (TKey)(object)controllerConfig.LeftJoycon.ButtonSl;
LeftButtonSr = (TKey)(object)controllerConfig.LeftJoycon.ButtonSr;
ButtonZl = (TKey)(object)controllerConfig.LeftJoycon.ButtonZl;
ButtonL = (TKey)(object)controllerConfig.LeftJoycon.ButtonL;
DeadzoneLeft = controllerConfig.DeadzoneLeft;
DeadzoneRight = controllerConfig.DeadzoneRight;
RangeLeft = controllerConfig.RangeLeft;
RangeRight = controllerConfig.RangeRight;
TriggerThreshold = controllerConfig.TriggerThreshold;
if (controllerConfig.Motion != null)
{
EnableMotion = controllerConfig.Motion.EnableMotion;
MotionBackend = controllerConfig.Motion.MotionBackend;
GyroDeadzone = controllerConfig.Motion.GyroDeadzone;
Sensitivity = controllerConfig.Motion.Sensitivity;
if (controllerConfig.Motion is CemuHookMotionConfigController cemuHook)
{
EnableCemuHookMotion = true;
DsuServerHost = cemuHook.DsuServerHost;
DsuServerPort = cemuHook.DsuServerPort;
Slot = cemuHook.Slot;
AltSlot = cemuHook.AltSlot;
MirrorInput = cemuHook.MirrorInput;
}
if (controllerConfig.Rumble != null)
{
EnableRumble = controllerConfig.Rumble.EnableRumble;
WeakRumble = controllerConfig.Rumble.WeakRumble;
StrongRumble = controllerConfig.Rumble.StrongRumble;
}
}
}
}
}
public InputConfiguration()
{
}
public InputConfig GetConfig()
{
if (Backend == InputBackendType.WindowKeyboard)
{
return new StandardKeyboardInputConfig
{
Id = Id,
Backend = Backend,
PlayerIndex = PlayerIndex,
ControllerType = ControllerType,
LeftJoycon = new LeftJoyconCommonConfig<Key>
{
DpadUp = (Key)(object)DpadUp,
DpadDown = (Key)(object)DpadDown,
DpadLeft = (Key)(object)DpadLeft,
DpadRight = (Key)(object)DpadRight,
ButtonL = (Key)(object)ButtonL,
ButtonZl = (Key)(object)ButtonZl,
ButtonSl = (Key)(object)LeftButtonSl,
ButtonSr = (Key)(object)LeftButtonSr,
ButtonMinus = (Key)(object)ButtonMinus,
},
RightJoycon = new RightJoyconCommonConfig<Key>
{
ButtonA = (Key)(object)ButtonA,
ButtonB = (Key)(object)ButtonB,
ButtonX = (Key)(object)ButtonX,
ButtonY = (Key)(object)ButtonY,
ButtonPlus = (Key)(object)ButtonPlus,
ButtonSl = (Key)(object)RightButtonSl,
ButtonSr = (Key)(object)RightButtonSr,
ButtonR = (Key)(object)ButtonR,
ButtonZr = (Key)(object)ButtonZr,
},
LeftJoyconStick = new JoyconConfigKeyboardStick<Key>
{
StickUp = (Key)(object)LeftStickUp,
StickDown = (Key)(object)LeftStickDown,
StickRight = (Key)(object)LeftStickRight,
StickLeft = (Key)(object)LeftStickLeft,
StickButton = (Key)(object)LeftKeyboardStickButton,
},
RightJoyconStick = new JoyconConfigKeyboardStick<Key>
{
StickUp = (Key)(object)RightStickUp,
StickDown = (Key)(object)RightStickDown,
StickLeft = (Key)(object)RightStickLeft,
StickRight = (Key)(object)RightStickRight,
StickButton = (Key)(object)RightKeyboardStickButton,
},
Version = InputConfig.CurrentVersion,
};
}
if (Backend == InputBackendType.GamepadSDL2)
{
var config = new StandardControllerInputConfig
{
Id = Id,
Backend = Backend,
PlayerIndex = PlayerIndex,
ControllerType = ControllerType,
LeftJoycon = new LeftJoyconCommonConfig<GamepadInputId>
{
DpadUp = (GamepadInputId)(object)DpadUp,
DpadDown = (GamepadInputId)(object)DpadDown,
DpadLeft = (GamepadInputId)(object)DpadLeft,
DpadRight = (GamepadInputId)(object)DpadRight,
ButtonL = (GamepadInputId)(object)ButtonL,
ButtonZl = (GamepadInputId)(object)ButtonZl,
ButtonSl = (GamepadInputId)(object)LeftButtonSl,
ButtonSr = (GamepadInputId)(object)LeftButtonSr,
ButtonMinus = (GamepadInputId)(object)ButtonMinus,
},
RightJoycon = new RightJoyconCommonConfig<GamepadInputId>
{
ButtonA = (GamepadInputId)(object)ButtonA,
ButtonB = (GamepadInputId)(object)ButtonB,
ButtonX = (GamepadInputId)(object)ButtonX,
ButtonY = (GamepadInputId)(object)ButtonY,
ButtonPlus = (GamepadInputId)(object)ButtonPlus,
ButtonSl = (GamepadInputId)(object)RightButtonSl,
ButtonSr = (GamepadInputId)(object)RightButtonSr,
ButtonR = (GamepadInputId)(object)ButtonR,
ButtonZr = (GamepadInputId)(object)ButtonZr,
},
LeftJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
{
Joystick = (StickInputId)(object)LeftJoystick,
InvertStickX = LeftInvertStickX,
InvertStickY = LeftInvertStickY,
Rotate90CW = LeftRotate90,
StickButton = (GamepadInputId)(object)LeftControllerStickButton,
},
RightJoyconStick = new JoyconConfigControllerStick<GamepadInputId, StickInputId>
{
Joystick = (StickInputId)(object)RightJoystick,
InvertStickX = RightInvertStickX,
InvertStickY = RightInvertStickY,
Rotate90CW = RightRotate90,
StickButton = (GamepadInputId)(object)RightControllerStickButton,
},
Rumble = new RumbleConfigController
{
EnableRumble = EnableRumble,
WeakRumble = WeakRumble,
StrongRumble = StrongRumble,
},
Version = InputConfig.CurrentVersion,
DeadzoneLeft = DeadzoneLeft,
DeadzoneRight = DeadzoneRight,
RangeLeft = RangeLeft,
RangeRight = RangeRight,
TriggerThreshold = TriggerThreshold,
Motion = EnableCemuHookMotion
? new CemuHookMotionConfigController
{
DsuServerHost = DsuServerHost,
DsuServerPort = DsuServerPort,
Slot = Slot,
AltSlot = AltSlot,
MirrorInput = MirrorInput,
MotionBackend = MotionInputBackendType.CemuHook,
}
: new StandardMotionConfigController
{
MotionBackend = MotionInputBackendType.GamepadDriver,
},
};
config.Motion.Sensitivity = Sensitivity;
config.Motion.EnableMotion = EnableMotion;
config.Motion.GyroDeadzone = GyroDeadzone;
return config;
}
return null;
}
}
}

View file

@ -0,0 +1,32 @@
using Ryujinx.Ava.UI.ViewModels;
using System.IO;
namespace Ryujinx.Ava.UI.Models
{
public class ModModel : BaseModel
{
private bool _enabled;
public bool Enabled
{
get => _enabled;
set
{
_enabled = value;
OnPropertyChanged();
}
}
public bool InSd { get; }
public string Path { get; }
public string Name { get; }
public ModModel(string path, string name, bool enabled, bool inSd)
{
Path = path;
Name = name;
Enabled = enabled;
InSd = inSd;
}
}
}

View file

@ -0,0 +1,6 @@
using Ryujinx.Common.Configuration.Hid;
namespace Ryujinx.Ava.UI.Models
{
public record PlayerModel(PlayerIndex Id, string Name);
}

View file

@ -0,0 +1,32 @@
using Avalonia.Media;
using Ryujinx.Ava.UI.ViewModels;
namespace Ryujinx.Ava.UI.Models
{
public class ProfileImageModel : BaseModel
{
public ProfileImageModel(string name, byte[] data)
{
Name = name;
Data = data;
}
public string Name { get; set; }
public byte[] Data { get; set; }
private SolidColorBrush _backgroundColor = new(Colors.White);
public SolidColorBrush BackgroundColor
{
get
{
return _backgroundColor;
}
set
{
_backgroundColor = value;
OnPropertyChanged();
}
}
}
}

View file

@ -0,0 +1,96 @@
using LibHac.Fs;
using LibHac.Ncm;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Windows;
using Ryujinx.HLE.FileSystem;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common.Helper;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Path = System.IO.Path;
namespace Ryujinx.Ava.UI.Models
{
public class SaveModel : BaseModel
{
private long _size;
public ulong SaveId { get; }
public ProgramId TitleId { get; }
public string TitleIdString => $"{TitleId.Value:X16}";
public UserId UserId { get; }
public bool InGameList { get; }
public string Title { get; }
public byte[] Icon { get; }
public long Size
{
get => _size; set
{
_size = value;
SizeAvailable = true;
OnPropertyChanged();
OnPropertyChanged(nameof(SizeString));
OnPropertyChanged(nameof(SizeAvailable));
}
}
public bool SizeAvailable { get; set; }
public string SizeString => ValueFormatUtils.FormatFileSize(Size);
public SaveModel(SaveDataInfo info)
{
SaveId = info.SaveDataId;
TitleId = info.ProgramId;
UserId = info.UserId;
var appData = MainWindow.MainWindowViewModel.Applications.FirstOrDefault(x => x.TitleId.ToUpper() == TitleIdString);
InGameList = appData != null;
if (InGameList)
{
Icon = appData.Icon;
Title = appData.TitleName;
}
else
{
var appMetadata = ApplicationLibrary.LoadAndSaveMetaData(TitleIdString);
Title = appMetadata.Title ?? TitleIdString;
}
Task.Run(() =>
{
var saveRoot = Path.Combine(VirtualFileSystem.GetNandPath(), $"user/save/{info.SaveDataId:x16}");
long totalSize = GetDirectorySize(saveRoot);
static long GetDirectorySize(string path)
{
long size = 0;
if (Directory.Exists(path))
{
var directories = Directory.GetDirectories(path);
foreach (var directory in directories)
{
size += GetDirectorySize(directory);
}
var files = Directory.GetFiles(path);
foreach (var file in files)
{
size += new FileInfo(file).Length;
}
}
return size;
}
Size = totalSize;
});
}
}
}

View file

@ -0,0 +1,28 @@
using System;
namespace Ryujinx.Ava.UI.Models
{
internal class StatusUpdatedEventArgs : EventArgs
{
public bool VSyncEnabled { get; }
public string VolumeStatus { get; }
public string GpuBackend { get; }
public string AspectRatio { get; }
public string DockedMode { get; }
public string FifoStatus { get; }
public string GameStatus { get; }
public string GpuName { get; }
public StatusUpdatedEventArgs(bool vSyncEnabled, string volumeStatus, string gpuBackend, string dockedMode, string aspectRatio, string gameStatus, string fifoStatus, string gpuName)
{
VSyncEnabled = vSyncEnabled;
VolumeStatus = volumeStatus;
GpuBackend = gpuBackend;
DockedMode = dockedMode;
AspectRatio = aspectRatio;
GameStatus = gameStatus;
FifoStatus = fifoStatus;
GpuName = gpuName;
}
}
}

View file

@ -0,0 +1,61 @@
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using System;
namespace Ryujinx.Ava.UI.Models
{
public class TempProfile : BaseModel
{
private readonly UserProfile _profile;
private byte[] _image;
private string _name = String.Empty;
private UserId _userId;
public static uint MaxProfileNameLength => 0x20;
public byte[] Image
{
get => _image;
set
{
_image = value;
OnPropertyChanged();
}
}
public UserId UserId
{
get => _userId;
set
{
_userId = value;
OnPropertyChanged();
OnPropertyChanged(nameof(UserIdString));
}
}
public string UserIdString => _userId.ToString();
public string Name
{
get => _name;
set
{
_name = value;
OnPropertyChanged();
}
}
public TempProfile(UserProfile profile)
{
_profile = profile;
if (_profile != null)
{
Image = profile.Image;
Name = profile.Name;
UserId = profile.UserId;
}
}
}
}

View file

@ -0,0 +1,16 @@
namespace Ryujinx.Ava.UI.Models
{
internal class TimeZone
{
public TimeZone(string utcDifference, string location, string abbreviation)
{
UtcDifference = utcDifference;
Location = location;
Abbreviation = abbreviation;
}
public string UtcDifference { get; set; }
public string Location { get; set; }
public string Abbreviation { get; set; }
}
}

View file

@ -0,0 +1,19 @@
using LibHac.Ns;
using Ryujinx.Ava.Common.Locale;
namespace Ryujinx.Ava.UI.Models
{
public class TitleUpdateModel
{
public ApplicationControlProperty Control { get; }
public string Path { get; }
public string Label => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.TitleUpdateVersionLabel, Control.DisplayVersionString.ToString());
public TitleUpdateModel(ApplicationControlProperty control, string path)
{
Control = control;
Path = path;
}
}
}

View file

@ -0,0 +1,104 @@
using Avalonia.Media;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Ava.UI.Views.User;
using Ryujinx.HLE.HOS.Services.Account.Acc;
using Profile = Ryujinx.HLE.HOS.Services.Account.Acc.UserProfile;
namespace Ryujinx.Ava.UI.Models
{
public class UserProfile : BaseModel
{
private readonly Profile _profile;
private readonly NavigationDialogHost _owner;
private byte[] _image;
private string _name;
private UserId _userId;
private bool _isPointerOver;
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)
{
_profile = profile;
_owner = owner;
UpdateBackground();
Image = profile.Image;
Name = profile.Name;
UserId = profile.UserId;
}
public void UpdateState()
{
UpdateBackground();
OnPropertyChanged(nameof(Name));
}
private void UpdateBackground()
{
var currentApplication = Avalonia.Application.Current;
currentApplication.Styles.TryGetResource("ControlFillColorSecondary", currentApplication.ActualThemeVariant, out object color);
if (color is not null)
{
BackgroundColor = _profile.AccountState == AccountState.Open ? new SolidColorBrush((Color)color) : Brushes.Transparent;
}
}
public void Recover(UserProfile userProfile)
{
_owner.Navigate(typeof(UserEditorView), (_owner, userProfile, true));
}
}
}