merge with upstream
This commit is contained in:
@@ -2,6 +2,7 @@ using Avalonia.Media.Imaging;
|
||||
using Avalonia.Styling;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Common;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Utilities.Configuration;
|
||||
@@ -24,30 +25,35 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
Version = RyujinxApp.FullAppName + "\n" + Program.Version;
|
||||
UpdateLogoTheme(ConfigurationState.Instance.UI.BaseStyle.Value);
|
||||
|
||||
ThemeManager.ThemeChanged += ThemeManager_ThemeChanged;
|
||||
RyujinxApp.ThemeChanged += Ryujinx_ThemeChanged;
|
||||
}
|
||||
|
||||
private void ThemeManager_ThemeChanged()
|
||||
private void Ryujinx_ThemeChanged()
|
||||
{
|
||||
Dispatcher.UIThread.Post(() => UpdateLogoTheme(ConfigurationState.Instance.UI.BaseStyle.Value));
|
||||
}
|
||||
|
||||
private const string LogoPathFormat = "resm:Ryujinx.Assets.UIImages.Logo_{0}_{1}.png?assembly=Ryujinx";
|
||||
|
||||
private void UpdateLogoTheme(string theme)
|
||||
{
|
||||
bool isDarkTheme = theme == "Dark" || (theme == "Auto" && RyujinxApp.DetectSystemTheme() == ThemeVariant.Dark);
|
||||
|
||||
string themeName = isDarkTheme ? "Dark" : "Light";
|
||||
|
||||
string basePath = "resm:Ryujinx.Assets.UIImages.";
|
||||
string themeSuffix = isDarkTheme ? "Dark.png" : "Light.png";
|
||||
|
||||
GithubLogo = LoadBitmap($"{basePath}Logo_GitHub_{themeSuffix}?assembly=Ryujinx");
|
||||
DiscordLogo = LoadBitmap($"{basePath}Logo_Discord_{themeSuffix}?assembly=Ryujinx");
|
||||
GithubLogo = LoadBitmap(LogoPathFormat.Format("GitHub", themeName));
|
||||
DiscordLogo = LoadBitmap(LogoPathFormat.Format("Discord", themeName));
|
||||
}
|
||||
|
||||
private static Bitmap LoadBitmap(string uri) => new(Avalonia.Platform.AssetLoader.Open(new Uri(uri)));
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ThemeManager.ThemeChanged -= ThemeManager_ThemeChanged;
|
||||
RyujinxApp.ThemeChanged -= Ryujinx_ThemeChanged;
|
||||
|
||||
GithubLogo.Dispose();
|
||||
DiscordLogo.Dispose();
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,9 +64,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
Directory.CreateDirectory(Path.Join(AppDataManager.BaseDirPath, "system", "amiibo"));
|
||||
|
||||
_amiiboJsonPath = Path.Join(AppDataManager.BaseDirPath, "system", "amiibo", "Amiibo.json");
|
||||
_amiiboList = new List<AmiiboApi>();
|
||||
_amiiboSeries = new ObservableCollection<string>();
|
||||
_amiibos = new AvaloniaList<AmiiboApi>();
|
||||
_amiiboList = [];
|
||||
_amiiboSeries = [];
|
||||
_amiibos = [];
|
||||
|
||||
_amiiboLogoBytes = EmbeddedResources.Read("Ryujinx/Assets/UIImages/Logo_Amiibo.png");
|
||||
|
||||
@@ -264,7 +264,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
Logger.Error?.Print(LogClass.Application, $"Couldn't get valid amiibo data: {exception}");
|
||||
|
||||
// Neither local or remote files are valid JSON, close window.
|
||||
ShowInfoDialog();
|
||||
await ShowInfoDialog();
|
||||
Close();
|
||||
}
|
||||
else if (!remoteIsValid)
|
||||
@@ -273,7 +273,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
// Only the local file is valid, the local one should be used
|
||||
// but the user should be warned.
|
||||
ShowInfoDialog();
|
||||
await ShowInfoDialog();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -525,7 +525,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
AmiiboImage = bitmap;
|
||||
}
|
||||
|
||||
private static async void ShowInfoDialog()
|
||||
private static async Task ShowInfoDialog()
|
||||
{
|
||||
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogAmiiboApiTitle],
|
||||
LocaleManager.Instance[LocaleKeys.DialogAmiiboApiConnectErrorMessage],
|
||||
|
||||
29
src/Ryujinx/UI/ViewModels/ApplicationDataViewModel.cs
Normal file
29
src/Ryujinx/UI/ViewModels/ApplicationDataViewModel.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.Ava.Utilities.PlayReport;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
public class ApplicationDataViewModel : BaseModel
|
||||
{
|
||||
public ApplicationData AppData { get; }
|
||||
|
||||
public ApplicationDataViewModel(ApplicationData appData) => AppData = appData;
|
||||
|
||||
public string DynamicRichPresenceDescription =>
|
||||
AppData.HasDynamicRichPresenceSupport
|
||||
? AppData.RichPresenceSpec.Value.Description
|
||||
: GameSpec.DefaultDescription;
|
||||
|
||||
public string FormattedVersion => LocaleManager.Instance[LocaleKeys.GameListHeaderVersion].Format(AppData.Version);
|
||||
public string FormattedDeveloper => LocaleManager.Instance[LocaleKeys.GameListHeaderDeveloper].Format(AppData.Developer);
|
||||
public string FormattedFileExtension => LocaleManager.Instance[LocaleKeys.GameListHeaderFileExtension].Format(AppData.FileExtension);
|
||||
public string FormattedFileSize => LocaleManager.Instance[LocaleKeys.GameListHeaderFileSize].Format(AppData.FileSizeString);
|
||||
|
||||
public string FormattedLdnInfo =>
|
||||
$"{LocaleManager.Instance[LocaleKeys.GameListHeaderHostedGames].Format(AppData.GameCount)}" +
|
||||
$"\n" +
|
||||
$"{LocaleManager.Instance[LocaleKeys.GameListHeaderPlayerCount].Format(AppData.PlayerCount)}";
|
||||
}
|
||||
}
|
||||
@@ -14,9 +14,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public DlcSelectViewModel(ulong titleId, ApplicationLibrary appLibrary)
|
||||
{
|
||||
_dlcs = appLibrary.DownloadableContents.Items
|
||||
.Where(x => x.Dlc.TitleIdBase == titleId)
|
||||
.Select(x => x.Dlc)
|
||||
_dlcs = appLibrary.FindDlcsFor(titleId)
|
||||
.OrderBy(it => it.IsBundled ? 0 : 1)
|
||||
.ThenBy(it => it.TitleId)
|
||||
.ToArray();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Avalonia.Collections;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
@@ -9,22 +8,20 @@ using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.Common.Models;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.HLE.FileSystem;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Application = Avalonia.Application;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
public partial class DownloadableContentManagerViewModel : BaseModel
|
||||
{
|
||||
private readonly ApplicationLibrary _applicationLibrary;
|
||||
private AvaloniaList<DownloadableContentModel> _downloadableContents = new();
|
||||
[ObservableProperty] private AvaloniaList<DownloadableContentModel> _selectedDownloadableContents = new();
|
||||
[ObservableProperty] private AvaloniaList<DownloadableContentModel> _views = new();
|
||||
private AvaloniaList<DownloadableContentModel> _downloadableContents = [];
|
||||
[ObservableProperty] private AvaloniaList<DownloadableContentModel> _selectedDownloadableContents = [];
|
||||
[ObservableProperty] private AvaloniaList<DownloadableContentModel> _views = [];
|
||||
[ObservableProperty] private bool _showBundledContentNotice = false;
|
||||
|
||||
private string _search;
|
||||
@@ -72,8 +69,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private void LoadDownloadableContents()
|
||||
{
|
||||
IEnumerable<(DownloadableContentModel Dlc, bool IsEnabled)> dlcs = _applicationLibrary.DownloadableContents.Items
|
||||
.Where(it => it.Dlc.TitleIdBase == _applicationData.IdBase);
|
||||
(DownloadableContentModel Dlc, bool IsEnabled)[] dlcs = _applicationLibrary.FindDlcConfigurationFor(_applicationData.Id);
|
||||
|
||||
bool hasBundledContent = false;
|
||||
foreach ((DownloadableContentModel dlc, bool isEnabled) in dlcs)
|
||||
@@ -139,9 +135,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
new("NSP")
|
||||
{
|
||||
Patterns = new[] { "*.nsp" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" },
|
||||
MimeTypes = new[] { "application/x-nx-nsp" },
|
||||
Patterns = ["*.nsp"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.nsp"],
|
||||
MimeTypes = ["application/x-nx-nsp"],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using Avalonia.Svg.Skia;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Views.Input;
|
||||
using Ryujinx.Common.Utilities;
|
||||
using Ryujinx.UI.Views.Input;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
@@ -47,6 +47,23 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
ParentModel = model;
|
||||
model.NotifyChangesEvent += OnParentModelChanged;
|
||||
OnParentModelChanged();
|
||||
config.PropertyChanged += (_, args) =>
|
||||
{
|
||||
if (args.PropertyName is nameof(Config.UseRainbowLed))
|
||||
{
|
||||
if (Config is { UseRainbowLed: true, TurnOffLed: false, EnableLedChanging: true })
|
||||
Rainbow.Updated += (ref Color color) => ParentModel.SelectedGamepad.SetLed((uint)color.ToArgb());
|
||||
else
|
||||
{
|
||||
Rainbow.Reset();
|
||||
|
||||
if (Config.TurnOffLed)
|
||||
ParentModel.SelectedGamepad.ClearLed();
|
||||
else
|
||||
ParentModel.SelectedGamepad.SetLed(Config.LedColor.ToUInt32());
|
||||
}
|
||||
}
|
||||
};
|
||||
Config = config;
|
||||
}
|
||||
|
||||
@@ -59,16 +76,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
await RumbleInputView.Show(this);
|
||||
}
|
||||
|
||||
public RelayCommand LedDisabledChanged => Commands.Create(() =>
|
||||
|
||||
public async void ShowLedConfig()
|
||||
{
|
||||
if (!Config.EnableLedChanging) return;
|
||||
|
||||
if (Config.TurnOffLed)
|
||||
ParentModel.SelectedGamepad.ClearLed();
|
||||
else
|
||||
ParentModel.SelectedGamepad.SetLed(Config.LedColor.ToUInt32());
|
||||
});
|
||||
await LedInputView.Show(this);
|
||||
}
|
||||
|
||||
public void OnParentModelChanged()
|
||||
{
|
||||
|
||||
@@ -23,6 +23,7 @@ using Ryujinx.Input;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
@@ -63,7 +64,13 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
get => _selectedGamepad;
|
||||
private set
|
||||
{
|
||||
Rainbow.Reset();
|
||||
|
||||
_selectedGamepad = value;
|
||||
|
||||
if (ConfigViewModel is ControllerInputViewModel { Config.UseRainbowLed: true })
|
||||
Rainbow.Updated += (ref Color color) => _selectedGamepad.SetLed((uint)color.ToArgb());
|
||||
|
||||
OnPropertiesChanged(nameof(HasLed), nameof(CanClearLed));
|
||||
}
|
||||
}
|
||||
@@ -259,11 +266,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
|
||||
public InputViewModel()
|
||||
{
|
||||
PlayerIndexes = new ObservableCollection<PlayerModel>();
|
||||
Controllers = new ObservableCollection<ControllerModel>();
|
||||
Devices = new ObservableCollection<(DeviceType Type, string Id, string Name)>();
|
||||
ProfilesList = new AvaloniaList<string>();
|
||||
DeviceList = new AvaloniaList<string>();
|
||||
PlayerIndexes = [];
|
||||
Controllers = [];
|
||||
Devices = [];
|
||||
ProfilesList = [];
|
||||
DeviceList = [];
|
||||
|
||||
ControllerImage = ProControllerResource;
|
||||
|
||||
|
||||
69
src/Ryujinx/UI/ViewModels/Input/LedInputViewModel.cs
Normal file
69
src/Ryujinx/UI/ViewModels/Input/LedInputViewModel.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using Avalonia.Media;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Humanizer;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Utilities.Configuration;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
public partial class LedInputViewModel : BaseModel
|
||||
{
|
||||
public required InputViewModel ParentModel { get; init; }
|
||||
|
||||
public RelayCommand LedDisabledChanged => Commands.Create(() =>
|
||||
{
|
||||
if (!EnableLedChanging) return;
|
||||
|
||||
if (TurnOffLed)
|
||||
ParentModel.SelectedGamepad.ClearLed();
|
||||
else
|
||||
ParentModel.SelectedGamepad.SetLed(LedColor.ToUInt32());
|
||||
});
|
||||
|
||||
[ObservableProperty] private bool _enableLedChanging;
|
||||
[ObservableProperty] private Color _ledColor;
|
||||
|
||||
public string RainbowSpeedText => RainbowSpeed.ToString(CultureInfo.CurrentCulture).Truncate(4, string.Empty);
|
||||
|
||||
public float RainbowSpeed
|
||||
{
|
||||
get => ConfigurationState.Instance.Hid.RainbowSpeed;
|
||||
set
|
||||
{
|
||||
ConfigurationState.Instance.Hid.RainbowSpeed.Value = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(RainbowSpeedText));
|
||||
}
|
||||
}
|
||||
|
||||
public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed;
|
||||
|
||||
private bool _turnOffLed;
|
||||
|
||||
public bool TurnOffLed
|
||||
{
|
||||
get => _turnOffLed;
|
||||
set
|
||||
{
|
||||
_turnOffLed = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(ShowLedColorPicker));
|
||||
}
|
||||
}
|
||||
|
||||
private bool _useRainbowLed;
|
||||
|
||||
public bool UseRainbowLed
|
||||
{
|
||||
get => _useRainbowLed;
|
||||
set
|
||||
{
|
||||
_useRainbowLed = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(ShowLedColorPicker));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using Avalonia.Media.Imaging;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using DynamicData;
|
||||
using DynamicData.Binding;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
@@ -104,6 +105,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
[ObservableProperty] private bool _isSubMenuOpen;
|
||||
[ObservableProperty] private ApplicationContextMenu _listAppContextMenu;
|
||||
[ObservableProperty] private ApplicationContextMenu _gridAppContextMenu;
|
||||
[ObservableProperty] private bool _updateAvailable;
|
||||
|
||||
public static AsyncRelayCommand UpdateCommand { get; } = Commands.Create(async () =>
|
||||
{
|
||||
if (Updater.CanUpdate(true))
|
||||
await Updater.BeginUpdateAsync(true);
|
||||
});
|
||||
|
||||
private bool _showLoadProgress;
|
||||
private bool _isGameRunning;
|
||||
@@ -349,6 +357,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
public bool HasCompatibilityEntry => SelectedApplication.HasPlayabilityInfo;
|
||||
|
||||
public bool HasDlc => ApplicationLibrary.HasDlcs(SelectedApplication.Id);
|
||||
|
||||
public bool OpenUserSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.UserAccountSaveDataSize > 0;
|
||||
|
||||
public bool OpenDeviceSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0;
|
||||
@@ -629,15 +641,15 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
return SortMode switch
|
||||
{
|
||||
ApplicationSort.Title => LocaleManager.Instance[LocaleKeys.GameListHeaderApplication],
|
||||
ApplicationSort.Developer => LocaleManager.Instance[LocaleKeys.GameListHeaderDeveloper],
|
||||
ApplicationSort.LastPlayed => LocaleManager.Instance[LocaleKeys.GameListHeaderLastPlayed],
|
||||
ApplicationSort.TotalTimePlayed => LocaleManager.Instance[LocaleKeys.GameListHeaderTimePlayed],
|
||||
ApplicationSort.FileType => LocaleManager.Instance[LocaleKeys.GameListHeaderFileExtension],
|
||||
ApplicationSort.FileSize => LocaleManager.Instance[LocaleKeys.GameListHeaderFileSize],
|
||||
ApplicationSort.Path => LocaleManager.Instance[LocaleKeys.GameListHeaderPath],
|
||||
ApplicationSort.Favorite => LocaleManager.Instance[LocaleKeys.CommonFavorite],
|
||||
ApplicationSort.TitleId => LocaleManager.Instance[LocaleKeys.DlcManagerTableHeadingTitleIdLabel],
|
||||
ApplicationSort.Title => LocaleManager.Instance[LocaleKeys.GameListHeaderApplication],
|
||||
ApplicationSort.Developer => LocaleManager.Instance[LocaleKeys.GameListSortDeveloper],
|
||||
ApplicationSort.LastPlayed => LocaleManager.Instance[LocaleKeys.GameListSortLastPlayed],
|
||||
ApplicationSort.TotalTimePlayed => LocaleManager.Instance[LocaleKeys.GameListSortTimePlayed],
|
||||
ApplicationSort.FileType => LocaleManager.Instance[LocaleKeys.GameListSortFileExtension],
|
||||
ApplicationSort.FileSize => LocaleManager.Instance[LocaleKeys.GameListSortFileSize],
|
||||
ApplicationSort.Path => LocaleManager.Instance[LocaleKeys.GameListSortPath],
|
||||
_ => string.Empty,
|
||||
};
|
||||
}
|
||||
@@ -1143,10 +1155,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
List<string> dirs = result.Select(it => it.Path.LocalPath).ToList();
|
||||
int numAdded = onDirsSelected(dirs, out int numRemoved);
|
||||
|
||||
string msg = String.Join("\r\n", new string[] {
|
||||
string msg = string.Join("\n",
|
||||
string.Format(LocaleManager.Instance[localeMessageRemovedKey], numRemoved),
|
||||
string.Format(LocaleManager.Instance[localeMessageAddedKey], numAdded)
|
||||
});
|
||||
);
|
||||
|
||||
await Dispatcher.UIThread.InvokeAsync(async () =>
|
||||
{
|
||||
@@ -1245,21 +1257,21 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
new(LocaleManager.Instance[LocaleKeys.FileDialogAllTypes])
|
||||
{
|
||||
Patterns = new[] { "*.xci", "*.zip" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci", "public.zip-archive" },
|
||||
MimeTypes = new[] { "application/x-nx-xci", "application/zip" },
|
||||
Patterns = ["*.xci", "*.zip"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.xci", "public.zip-archive"],
|
||||
MimeTypes = ["application/x-nx-xci", "application/zip"],
|
||||
},
|
||||
new("XCI")
|
||||
{
|
||||
Patterns = new[] { "*.xci" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" },
|
||||
MimeTypes = new[] { "application/x-nx-xci" },
|
||||
Patterns = ["*.xci"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.xci"],
|
||||
MimeTypes = ["application/x-nx-xci"],
|
||||
},
|
||||
new("ZIP")
|
||||
{
|
||||
Patterns = new[] { "*.zip" },
|
||||
AppleUniformTypeIdentifiers = new[] { "public.zip-archive" },
|
||||
MimeTypes = new[] { "application/zip" },
|
||||
Patterns = ["*.zip"],
|
||||
AppleUniformTypeIdentifiers = ["public.zip-archive"],
|
||||
MimeTypes = ["application/zip"],
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1292,21 +1304,21 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
new(LocaleManager.Instance[LocaleKeys.FileDialogAllTypes])
|
||||
{
|
||||
Patterns = new[] { "*.keys", "*.zip" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci", "public.zip-archive" },
|
||||
MimeTypes = new[] { "application/keys", "application/zip" },
|
||||
Patterns = ["*.keys", "*.zip"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.xci", "public.zip-archive"],
|
||||
MimeTypes = ["application/keys", "application/zip"],
|
||||
},
|
||||
new("KEYS")
|
||||
{
|
||||
Patterns = new[] { "*.keys" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" },
|
||||
MimeTypes = new[] { "application/keys" },
|
||||
Patterns = ["*.keys"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.xci"],
|
||||
MimeTypes = ["application/keys"],
|
||||
},
|
||||
new("ZIP")
|
||||
{
|
||||
Patterns = new[] { "*.zip" },
|
||||
AppleUniformTypeIdentifiers = new[] { "public.zip-archive" },
|
||||
MimeTypes = new[] { "application/zip" },
|
||||
Patterns = ["*.zip"],
|
||||
AppleUniformTypeIdentifiers = ["public.zip-archive"],
|
||||
MimeTypes = ["application/zip"],
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1335,6 +1347,25 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
OpenHelper.OpenFolder(AppDataManager.BaseDirPath);
|
||||
}
|
||||
|
||||
public void OpenScreenshotsFolder()
|
||||
{
|
||||
string screenshotsDir = Path.Combine(AppDataManager.BaseDirPath, "screenshots");
|
||||
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(screenshotsDir))
|
||||
Directory.CreateDirectory(screenshotsDir);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to create directory at path {screenshotsDir}. Error : {ex.GetType().Name}", "Screenshot");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
OpenHelper.OpenFolder(screenshotsDir);
|
||||
}
|
||||
|
||||
public void OpenLogsFolder()
|
||||
{
|
||||
string logPath = AppDataManager.GetOrCreateLogsDir();
|
||||
@@ -1418,53 +1449,53 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats])
|
||||
{
|
||||
Patterns = new[] { "*.nsp", "*.xci", "*.nca", "*.nro", "*.nso" },
|
||||
AppleUniformTypeIdentifiers = new[]
|
||||
{
|
||||
Patterns = ["*.nsp", "*.xci", "*.nca", "*.nro", "*.nso"],
|
||||
AppleUniformTypeIdentifiers =
|
||||
[
|
||||
"com.ryujinx.nsp",
|
||||
"com.ryujinx.xci",
|
||||
"com.ryujinx.nca",
|
||||
"com.ryujinx.nro",
|
||||
"com.ryujinx.nso",
|
||||
},
|
||||
MimeTypes = new[]
|
||||
{
|
||||
"com.ryujinx.nso"
|
||||
],
|
||||
MimeTypes =
|
||||
[
|
||||
"application/x-nx-nsp",
|
||||
"application/x-nx-xci",
|
||||
"application/x-nx-nca",
|
||||
"application/x-nx-nro",
|
||||
"application/x-nx-nso",
|
||||
},
|
||||
"application/x-nx-nso"
|
||||
],
|
||||
},
|
||||
new("NSP")
|
||||
{
|
||||
Patterns = new[] { "*.nsp" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" },
|
||||
MimeTypes = new[] { "application/x-nx-nsp" },
|
||||
Patterns = ["*.nsp"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.nsp"],
|
||||
MimeTypes = ["application/x-nx-nsp"],
|
||||
},
|
||||
new("XCI")
|
||||
{
|
||||
Patterns = new[] { "*.xci" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" },
|
||||
MimeTypes = new[] { "application/x-nx-xci" },
|
||||
Patterns = ["*.xci"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.xci"],
|
||||
MimeTypes = ["application/x-nx-xci"],
|
||||
},
|
||||
new("NCA")
|
||||
{
|
||||
Patterns = new[] { "*.nca" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nca" },
|
||||
MimeTypes = new[] { "application/x-nx-nca" },
|
||||
Patterns = ["*.nca"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.nca"],
|
||||
MimeTypes = ["application/x-nx-nca"],
|
||||
},
|
||||
new("NRO")
|
||||
{
|
||||
Patterns = new[] { "*.nro" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nro" },
|
||||
MimeTypes = new[] { "application/x-nx-nro" },
|
||||
Patterns = ["*.nro"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.nro"],
|
||||
MimeTypes = ["application/x-nx-nro"],
|
||||
},
|
||||
new("NSO")
|
||||
{
|
||||
Patterns = new[] { "*.nso" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nso" },
|
||||
MimeTypes = new[] { "application/x-nx-nso" },
|
||||
Patterns = ["*.nso"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.nso"],
|
||||
MimeTypes = ["application/x-nx-nso"],
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1690,7 +1721,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats])
|
||||
{
|
||||
Patterns = new[] { "*.bin" },
|
||||
Patterns = ["*.bin"],
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1802,7 +1833,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
XCIFileTrimmer trimmer = new XCIFileTrimmer(filename, new XCITrimmerLog.MainWindow(this));
|
||||
XCIFileTrimmer trimmer = new(filename, new XCITrimmerLog.MainWindow(this));
|
||||
|
||||
if (trimmer.CanBeTrimmed)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ using Gommon;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.Utilities.AppLibrary;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Common.Utilities;
|
||||
@@ -23,12 +24,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
private readonly string _modJsonPath;
|
||||
|
||||
private AvaloniaList<ModModel> _mods = new();
|
||||
[ObservableProperty] private AvaloniaList<ModModel> _views = new();
|
||||
[ObservableProperty] private AvaloniaList<ModModel> _selectedMods = new();
|
||||
private AvaloniaList<ModModel> _mods = [];
|
||||
[ObservableProperty] private AvaloniaList<ModModel> _views = [];
|
||||
[ObservableProperty] private AvaloniaList<ModModel> _selectedMods = [];
|
||||
|
||||
private string _search;
|
||||
private readonly ulong _applicationId;
|
||||
private readonly ulong[] _installedDlcIds;
|
||||
private readonly IStorageProvider _storageProvider;
|
||||
|
||||
private static readonly ModMetadataJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions());
|
||||
@@ -61,18 +63,23 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
get => string.Format(LocaleManager.Instance[LocaleKeys.ModWindowHeading], Mods.Count);
|
||||
}
|
||||
|
||||
public ModManagerViewModel(ulong applicationId)
|
||||
public ModManagerViewModel(ulong applicationId, ulong applicationIdBase, ApplicationLibrary appLibrary)
|
||||
{
|
||||
_applicationId = applicationId;
|
||||
|
||||
_installedDlcIds = appLibrary.DownloadableContents.Keys
|
||||
.Where(x => x.TitleIdBase == applicationIdBase)
|
||||
.Select(x => x.TitleId)
|
||||
.ToArray();
|
||||
|
||||
_modJsonPath = Path.Combine(AppDataManager.GamesDirPath, applicationId.ToString("x16"), "mods.json");
|
||||
|
||||
_storageProvider = RyujinxApp.MainWindow.StorageProvider;
|
||||
|
||||
LoadMods(applicationId);
|
||||
LoadMods(applicationId, _installedDlcIds);
|
||||
}
|
||||
|
||||
private void LoadMods(ulong applicationId)
|
||||
private void LoadMods(ulong applicationId, ulong[] installedDlcIds)
|
||||
{
|
||||
Mods.Clear();
|
||||
SelectedMods.Clear();
|
||||
@@ -82,13 +89,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
foreach (string path in modsBasePaths)
|
||||
{
|
||||
bool inSd = path == ModLoader.GetSdModsBasePath();
|
||||
ModLoader.ModCache modCache = new ModLoader.ModCache();
|
||||
ModLoader.ModCache modCache = new();
|
||||
|
||||
ModLoader.QueryContentsDir(modCache, new DirectoryInfo(Path.Combine(path, "contents")), applicationId);
|
||||
ModLoader.QueryContentsDir(modCache, new DirectoryInfo(Path.Combine(path, "contents")), applicationId, _installedDlcIds);
|
||||
|
||||
foreach (ModLoader.Mod<DirectoryInfo> mod in modCache.RomfsDirs)
|
||||
{
|
||||
ModModel modModel = new ModModel(mod.Path.Parent.FullName, mod.Name, mod.Enabled, inSd);
|
||||
ModModel modModel = new(mod.Path.Parent.FullName, mod.Name, mod.Enabled, inSd);
|
||||
if (Mods.All(x => x.Path != mod.Path.Parent.FullName))
|
||||
{
|
||||
Mods.Add(modModel);
|
||||
@@ -102,7 +109,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
foreach (ModLoader.Mod<DirectoryInfo> mod in modCache.ExefsDirs)
|
||||
{
|
||||
ModModel modModel = new ModModel(mod.Path.Parent.FullName, mod.Name, mod.Enabled, inSd);
|
||||
ModModel modModel = new(mod.Path.Parent.FullName, mod.Name, mod.Enabled, inSd);
|
||||
if (Mods.All(x => x.Path != mod.Path.Parent.FullName))
|
||||
{
|
||||
Mods.Add(modModel);
|
||||
@@ -278,7 +285,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
File.Copy(file, file.Replace(directory.Parent.ToString(), destinationDir), true);
|
||||
}
|
||||
|
||||
LoadMods(_applicationId);
|
||||
LoadMods(_applicationId, _installedDlcIds);
|
||||
}
|
||||
|
||||
public async void Add()
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Collections.ObjectModel;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
public partial class UserSelectorDialogViewModel : BaseModel
|
||||
public partial class ProfileSelectorDialogViewModel : BaseModel
|
||||
{
|
||||
|
||||
[ObservableProperty] private UserId _selectedUserId;
|
||||
@@ -2,7 +2,7 @@ using Avalonia.Collections;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Threading;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Gommon;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using LibHac.Tools.FsSystem;
|
||||
using Ryujinx.Audio.Backends.OpenAL;
|
||||
using Ryujinx.Audio.Backends.SDL2;
|
||||
@@ -13,9 +13,11 @@ using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Ava.Utilities.Configuration;
|
||||
using Ryujinx.Ava.Utilities.Configuration.System;
|
||||
using Ryujinx.Ava.Utilities.Configuration.UI;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Configuration.Multiplayer;
|
||||
using Ryujinx.Common.GraphicsDriver;
|
||||
using Ryujinx.Common.Helper;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Vulkan;
|
||||
@@ -27,8 +29,6 @@ using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using TimeZone = Ryujinx.Ava.UI.Models.TimeZone;
|
||||
|
||||
@@ -49,9 +49,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private int _graphicsBackendMultithreadingIndex;
|
||||
private float _volume;
|
||||
[ObservableProperty] private bool _isVulkanAvailable = true;
|
||||
[ObservableProperty] private bool _gameDirectoryChanged;
|
||||
[ObservableProperty] private bool _autoloadDirectoryChanged;
|
||||
private readonly List<string> _gpuIds = new();
|
||||
[ObservableProperty] private bool _gameListNeedsRefresh;
|
||||
private readonly List<string> _gpuIds = [];
|
||||
private int _graphicsBackendIndex;
|
||||
private int _scalingFilter;
|
||||
private int _scalingFilterLevel;
|
||||
@@ -115,10 +114,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
|
||||
|
||||
public bool IsAppleSiliconMac => OperatingSystem.IsMacOS() && RuntimeInformation.ProcessArchitecture == Architecture.Arm64;
|
||||
|
||||
public bool IsMacOS => OperatingSystem.IsMacOS();
|
||||
|
||||
public bool EnableDiscordIntegration { get; set; }
|
||||
public bool CheckUpdatesOnStart { get; set; }
|
||||
public bool ShowConfirmExit { get; set; }
|
||||
@@ -126,10 +121,15 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public bool RememberWindowState { get; set; }
|
||||
public bool ShowTitleBar { get; set; }
|
||||
public int HideCursor { get; set; }
|
||||
public int UpdateCheckerType { get; set; }
|
||||
public bool EnableDockedMode { get; set; }
|
||||
public bool EnableKeyboard { get; set; }
|
||||
public bool EnableMouse { get; set; }
|
||||
public bool EnableAutoAssign { get; set; }
|
||||
public bool DisableInputWhenOutOfFocus { get; set; }
|
||||
|
||||
public int FocusLostActionType { get; set; }
|
||||
|
||||
public VSyncMode VSyncMode
|
||||
{
|
||||
get => _vSyncMode;
|
||||
@@ -201,7 +201,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public bool EnableTextureRecompression { get; set; }
|
||||
public bool EnableMacroHLE { get; set; }
|
||||
public bool EnableColorSpacePassthrough { get; set; }
|
||||
public bool ColorSpacePassthroughAvailable => IsMacOS;
|
||||
public bool ColorSpacePassthroughAvailable => RunningPlatform.IsMacOS;
|
||||
public bool EnableFileLog { get; set; }
|
||||
public bool EnableStub { get; set; }
|
||||
public bool EnableInfo { get; set; }
|
||||
@@ -210,6 +210,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public bool EnableTrace { get; set; }
|
||||
public bool EnableGuest { get; set; }
|
||||
public bool EnableFsAccessLog { get; set; }
|
||||
public bool EnableAvaloniaLog { get; set; }
|
||||
public bool EnableDebug { get; set; }
|
||||
public bool IsOpenAlEnabled { get; set; }
|
||||
public bool IsSoundIoEnabled { get; set; }
|
||||
@@ -297,6 +298,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
[ObservableProperty] private bool _matchSystemTime;
|
||||
|
||||
public DateTimeOffset CurrentDate { get; set; }
|
||||
|
||||
public TimeSpan CurrentTime { get; set; }
|
||||
@@ -331,9 +334,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
}
|
||||
}
|
||||
|
||||
[GeneratedRegex("Ryujinx-[0-9a-f]{8}")]
|
||||
private static partial Regex LdnPassphraseRegex();
|
||||
|
||||
public bool IsInvalidLdnPassphraseVisible { get; set; }
|
||||
|
||||
public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager) : this()
|
||||
@@ -415,17 +415,6 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
Dispatcher.UIThread.Post(() => OnPropertyChanged(nameof(PreferredGpuIndex)));
|
||||
}
|
||||
|
||||
public void MatchSystemTime()
|
||||
{
|
||||
(DateTimeOffset dto, TimeSpan timeOfDay) = DateTimeOffset.Now.Extract();
|
||||
|
||||
CurrentDate = dto;
|
||||
CurrentTime = timeOfDay;
|
||||
|
||||
OnPropertyChanged(nameof(CurrentDate));
|
||||
OnPropertyChanged(nameof(CurrentTime));
|
||||
}
|
||||
|
||||
public async Task LoadTimeZones()
|
||||
{
|
||||
_timeZoneContentManager = new TimeZoneContentManager();
|
||||
@@ -471,7 +460,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private bool ValidateLdnPassphrase(string passphrase)
|
||||
{
|
||||
return string.IsNullOrEmpty(passphrase) || (passphrase.Length == 16 && LdnPassphraseRegex().IsMatch(passphrase));
|
||||
return string.IsNullOrEmpty(passphrase) || (passphrase.Length == 16 && Patterns.LdnPassphrase.IsMatch(passphrase));
|
||||
}
|
||||
|
||||
public void ValidateAndSetTimeZone(string location)
|
||||
@@ -493,6 +482,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
RememberWindowState = config.RememberWindowState;
|
||||
ShowTitleBar = config.ShowTitleBar;
|
||||
HideCursor = (int)config.HideCursor.Value;
|
||||
UpdateCheckerType = (int)config.UpdateCheckerType.Value;
|
||||
FocusLostActionType = (int)config.FocusLostActionType.Value;
|
||||
|
||||
GameDirectories.Clear();
|
||||
GameDirectories.AddRange(config.UI.GameDirs.Value);
|
||||
@@ -513,6 +504,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
EnableKeyboard = config.Hid.EnableKeyboard;
|
||||
EnableMouse = config.Hid.EnableMouse;
|
||||
EnableAutoAssign = config.Hid.EnableAutoAssign;
|
||||
DisableInputWhenOutOfFocus = config.Hid.DisableInputWhenOutOfFocus;
|
||||
|
||||
// Keyboard Hotkeys
|
||||
KeyboardHotkey = new HotkeyConfig(config.Hid.Hotkeys.Value);
|
||||
@@ -528,13 +520,15 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
CurrentDate = currentDateTime.Date;
|
||||
CurrentTime = currentDateTime.TimeOfDay;
|
||||
|
||||
EnableCustomVSyncInterval = config.Graphics.EnableCustomVSyncInterval.Value;
|
||||
MatchSystemTime = config.System.MatchSystemTime;
|
||||
|
||||
EnableCustomVSyncInterval = config.Graphics.EnableCustomVSyncInterval;
|
||||
CustomVSyncInterval = config.Graphics.CustomVSyncInterval;
|
||||
VSyncMode = config.Graphics.VSyncMode;
|
||||
EnableFsIntegrityChecks = config.System.EnableFsIntegrityChecks;
|
||||
DramSize = config.System.DramSize;
|
||||
IgnoreMissingServices = config.System.IgnoreMissingServices;
|
||||
IgnoreApplet = config.System.IgnoreApplet;
|
||||
IgnoreApplet = config.System.IgnoreControllerApplet;
|
||||
|
||||
// CPU
|
||||
EnablePptc = config.System.EnablePtc;
|
||||
@@ -577,6 +571,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
EnableGuest = config.Logger.EnableGuest;
|
||||
EnableDebug = config.Logger.EnableDebug;
|
||||
EnableFsAccessLog = config.Logger.EnableFsAccessLog;
|
||||
EnableAvaloniaLog = config.Logger.EnableAvaloniaLog;
|
||||
FsGlobalAccessLogMode = config.System.FsGlobalAccessLogMode;
|
||||
OpenglDebugLevel = (int)config.Logger.GraphicsDebugLevel.Value;
|
||||
|
||||
@@ -597,16 +592,10 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
config.RememberWindowState.Value = RememberWindowState;
|
||||
config.ShowTitleBar.Value = ShowTitleBar;
|
||||
config.HideCursor.Value = (HideCursorMode)HideCursor;
|
||||
|
||||
if (GameDirectoryChanged)
|
||||
{
|
||||
config.UI.GameDirs.Value = [..GameDirectories];
|
||||
}
|
||||
|
||||
if (AutoloadDirectoryChanged)
|
||||
{
|
||||
config.UI.AutoloadDirs.Value = [..AutoloadDirectories];
|
||||
}
|
||||
config.UpdateCheckerType.Value = (UpdaterType)UpdateCheckerType;
|
||||
config.FocusLostActionType.Value = (FocusLostType)FocusLostActionType;
|
||||
config.UI.GameDirs.Value = [..GameDirectories];
|
||||
config.UI.AutoloadDirs.Value = [..AutoloadDirectories];
|
||||
|
||||
config.UI.BaseStyle.Value = BaseStyleIndex switch
|
||||
{
|
||||
@@ -622,24 +611,29 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
config.Hid.EnableMouse.Value = EnableMouse;
|
||||
bool activatingAutoAssign = EnableAutoAssign && !config.Hid.EnableAutoAssign;
|
||||
config.Hid.EnableAutoAssign.Value = EnableAutoAssign;
|
||||
config.Hid.DisableInputWhenOutOfFocus.Value = DisableInputWhenOutOfFocus;
|
||||
|
||||
// Keyboard Hotkeys
|
||||
config.Hid.Hotkeys.Value = KeyboardHotkey.GetConfig();
|
||||
|
||||
// System
|
||||
config.System.Region.Value = (Region)Region;
|
||||
|
||||
if (config.System.Language.Value != (Language)Language)
|
||||
GameListNeedsRefresh = true;
|
||||
|
||||
config.System.Language.Value = (Language)Language;
|
||||
|
||||
if (_validTzRegions.Contains(TimeZone))
|
||||
{
|
||||
config.System.TimeZone.Value = TimeZone;
|
||||
}
|
||||
|
||||
config.System.MatchSystemTime.Value = MatchSystemTime;
|
||||
config.System.SystemTimeOffset.Value = Convert.ToInt64((CurrentDate.ToUnixTimeSeconds() + CurrentTime.TotalSeconds) - DateTimeOffset.Now.ToUnixTimeSeconds());
|
||||
config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
|
||||
config.System.DramSize.Value = DramSize;
|
||||
config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
|
||||
config.System.IgnoreApplet.Value = (EnableAutoAssign) || IgnoreApplet;
|
||||
config.System.IgnoreControllerApplet.Value = (EnableAutoAssign) || IgnoreApplet;
|
||||
|
||||
// CPU
|
||||
config.System.EnablePtc.Value = EnablePptc;
|
||||
@@ -697,6 +691,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
config.Logger.EnableGuest.Value = EnableGuest;
|
||||
config.Logger.EnableDebug.Value = EnableDebug;
|
||||
config.Logger.EnableFsAccessLog.Value = EnableFsAccessLog;
|
||||
config.Logger.EnableAvaloniaLog.Value = EnableAvaloniaLog;
|
||||
config.System.FsGlobalAccessLogMode.Value = FsGlobalAccessLogMode;
|
||||
config.Logger.GraphicsDebugLevel.Value = (GraphicsDebugLevel)OpenglDebugLevel;
|
||||
|
||||
@@ -725,8 +720,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
SaveSettingsEvent?.Invoke();
|
||||
}
|
||||
|
||||
GameDirectoryChanged = false;
|
||||
AutoloadDirectoryChanged = false;
|
||||
GameListNeedsRefresh = false;
|
||||
}
|
||||
|
||||
private static void RevertIfNotSaved()
|
||||
@@ -745,6 +739,25 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
CloseWindow?.Invoke();
|
||||
}
|
||||
|
||||
[ObservableProperty] private bool _wantsToReset;
|
||||
|
||||
public AsyncRelayCommand ResetButton => Commands.Create(async () =>
|
||||
{
|
||||
if (!WantsToReset) return;
|
||||
|
||||
CloseWindow?.Invoke();
|
||||
ConfigurationState.Instance.LoadDefault();
|
||||
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
|
||||
RyujinxApp.MainWindow.LoadApplications();
|
||||
|
||||
await ContentDialogHelper.CreateInfoDialog(
|
||||
$"Your {RyujinxApp.FullAppName} configuration has been reset.",
|
||||
"",
|
||||
string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.SettingsButtonClose],
|
||||
"Configuration Reset");
|
||||
});
|
||||
|
||||
public void CancelButton()
|
||||
{
|
||||
RevertIfNotSaved();
|
||||
|
||||
@@ -21,8 +21,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private ApplicationLibrary ApplicationLibrary { get; }
|
||||
private ApplicationData ApplicationData { get; }
|
||||
|
||||
[ObservableProperty] private AvaloniaList<TitleUpdateModel> _titleUpdates = new();
|
||||
[ObservableProperty] private AvaloniaList<object> _views = new();
|
||||
[ObservableProperty] private AvaloniaList<TitleUpdateModel> _titleUpdates = [];
|
||||
[ObservableProperty] private AvaloniaList<object> _views = [];
|
||||
[ObservableProperty] private object _selectedUpdate = new TitleUpdateViewModelNoUpdate();
|
||||
[ObservableProperty] private bool _showBundledContentNotice;
|
||||
|
||||
@@ -41,8 +41,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
private void LoadUpdates()
|
||||
{
|
||||
IEnumerable<(TitleUpdateModel TitleUpdate, bool IsSelected)> updates = ApplicationLibrary.TitleUpdates.Items
|
||||
.Where(it => it.TitleUpdate.TitleIdBase == ApplicationData.IdBase);
|
||||
(TitleUpdateModel TitleUpdate, bool IsSelected)[] updates = ApplicationLibrary.FindUpdateConfigurationFor(ApplicationData.Id);
|
||||
|
||||
bool hasBundledContent = false;
|
||||
SelectedUpdate = new TitleUpdateViewModelNoUpdate();
|
||||
@@ -149,9 +148,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats])
|
||||
{
|
||||
Patterns = new[] { "*.nsp" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" },
|
||||
MimeTypes = new[] { "application/x-nx-nsp" },
|
||||
Patterns = ["*.nsp"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.nsp"],
|
||||
MimeTypes = ["application/x-nx-nsp"],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public UserFirmwareAvatarSelectorViewModel()
|
||||
{
|
||||
_images = new ObservableCollection<ProfileImageModel>();
|
||||
_images = [];
|
||||
|
||||
LoadImagesFromStore();
|
||||
PropertyChanged += (_, args) =>
|
||||
@@ -104,7 +104,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
// TODO: Parse DatabaseInfo.bin and table.bin files for more accuracy.
|
||||
if (item.Type == DirectoryEntryType.File && item.FullPath.Contains("chara") && item.FullPath.Contains("szs"))
|
||||
{
|
||||
using UniqueRef<IFile> file = new UniqueRef<IFile>();
|
||||
using UniqueRef<IFile> file = new();
|
||||
|
||||
romfs.OpenFile(ref file.Ref, ("/" + item.FullPath).ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
public UserProfileViewModel()
|
||||
{
|
||||
Profiles = new ObservableCollection<BaseModel>();
|
||||
LostProfiles = new ObservableCollection<UserProfile>();
|
||||
Profiles = [];
|
||||
LostProfiles = [];
|
||||
IsEmpty = !LostProfiles.Any();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
[ObservableProperty] private int _sortIndex;
|
||||
[ObservableProperty] private int _orderIndex;
|
||||
[ObservableProperty] private string _search;
|
||||
[ObservableProperty] private ObservableCollection<SaveModel> _saves = new();
|
||||
[ObservableProperty] private ObservableCollection<SaveModel> _views = new();
|
||||
[ObservableProperty] private ObservableCollection<SaveModel> _saves = [];
|
||||
[ObservableProperty] private ObservableCollection<SaveModel> _views = [];
|
||||
private readonly AccountManager _accountManager;
|
||||
|
||||
public string SaveManagerHeading => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SaveManagerHeading, _accountManager.LastOpenedUser.Name, _accountManager.LastOpenedUser.UserId);
|
||||
|
||||
@@ -36,9 +36,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private readonly Ryujinx.Common.Logging.XCIFileTrimmerLog _logger;
|
||||
private ApplicationLibrary ApplicationLibrary => _mainWindowViewModel.ApplicationLibrary;
|
||||
private Optional<XCITrimmerFileModel> _processingApplication = null;
|
||||
private AvaloniaList<XCITrimmerFileModel> _allXCIFiles = new();
|
||||
private AvaloniaList<XCITrimmerFileModel> _selectedXCIFiles = new();
|
||||
private AvaloniaList<XCITrimmerFileModel> _displayedXCIFiles = new();
|
||||
private AvaloniaList<XCITrimmerFileModel> _allXCIFiles = [];
|
||||
private AvaloniaList<XCITrimmerFileModel> _selectedXCIFiles = [];
|
||||
private AvaloniaList<XCITrimmerFileModel> _displayedXCIFiles = [];
|
||||
private MainWindowViewModel _mainWindowViewModel;
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
private string _search;
|
||||
@@ -183,7 +183,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
break;
|
||||
|
||||
XCIFileTrimmer trimmer = new XCIFileTrimmer(xciApp.Path, _logger);
|
||||
XCIFileTrimmer trimmer = new(xciApp.Path, _logger);
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user