aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Ava/Ui/ViewModels
diff options
context:
space:
mode:
authorIsaac Marovitz <42140194+IsaacMarovitz@users.noreply.github.com>2022-12-29 14:24:05 +0000
committerGitHub <noreply@github.com>2022-12-29 15:24:05 +0100
commit76671d63d4f3ea18f8ad99e9ce9f0b2ec9a2599d (patch)
tree05013214e4696a9254369d0706173f58877f6a83 /Ryujinx.Ava/Ui/ViewModels
parent3d1a0bf3749afa14da5b5ba1e0666fdb78c99beb (diff)
Ava GUI: Restructure `Ryujinx.Ava` (#4165)
* Restructure `Ryujinx.Ava` * Stylistic consistency * Update Ryujinx.Ava/UI/Controls/UserEditor.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Controls/UserEditor.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Controls/UserSelector.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Controls/SaveManager.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Controls/SaveManager.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Windows/SettingsWindow.axaml.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/ViewModels/UserProfileViewModel.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Update Ryujinx.Ava/UI/Helpers/EmbeddedWindow.cs Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com> * Fix redundancies * Remove redunancies * Add back elses Co-authored-by: TSRBerry <20988865+TSRBerry@users.noreply.github.com>
Diffstat (limited to 'Ryujinx.Ava/Ui/ViewModels')
-rw-r--r--Ryujinx.Ava/Ui/ViewModels/AmiiboWindowViewModel.cs451
-rw-r--r--Ryujinx.Ava/Ui/ViewModels/AvatarProfileViewModel.cs363
-rw-r--r--Ryujinx.Ava/Ui/ViewModels/BaseModel.cs15
-rw-r--r--Ryujinx.Ava/Ui/ViewModels/ControllerSettingsViewModel.cs900
-rw-r--r--Ryujinx.Ava/Ui/ViewModels/MainWindowViewModel.cs1539
-rw-r--r--Ryujinx.Ava/Ui/ViewModels/SettingsViewModel.cs520
-rw-r--r--Ryujinx.Ava/Ui/ViewModels/UserProfileViewModel.cs213
7 files changed, 0 insertions, 4001 deletions
diff --git a/Ryujinx.Ava/Ui/ViewModels/AmiiboWindowViewModel.cs b/Ryujinx.Ava/Ui/ViewModels/AmiiboWindowViewModel.cs
deleted file mode 100644
index d007e0e7..00000000
--- a/Ryujinx.Ava/Ui/ViewModels/AmiiboWindowViewModel.cs
+++ /dev/null
@@ -1,451 +0,0 @@
-using Avalonia;
-using Avalonia.Collections;
-using Avalonia.Media.Imaging;
-using Avalonia.Threading;
-using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.Ui.Controls;
-using Ryujinx.Ava.Ui.Models;
-using Ryujinx.Ava.Ui.Windows;
-using Ryujinx.Common;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Utilities;
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.IO;
-using System.Linq;
-using System.Net.Http;
-using System.Text;
-using System.Text.Json;
-using System.Threading.Tasks;
-
-namespace Ryujinx.Ava.Ui.ViewModels
-{
- public class AmiiboWindowViewModel : BaseModel, IDisposable
- {
- private const string DefaultJson = "{ \"amiibo\": [] }";
- private const float AmiiboImageSize = 350f;
-
- private readonly string _amiiboJsonPath;
- private readonly byte[] _amiiboLogoBytes;
- private readonly HttpClient _httpClient;
- private readonly StyleableWindow _owner;
-
- private Bitmap _amiiboImage;
- private List<Amiibo.AmiiboApi> _amiiboList;
- private AvaloniaList<Amiibo.AmiiboApi> _amiibos;
- private ObservableCollection<string> _amiiboSeries;
-
- private int _amiiboSelectedIndex;
- private int _seriesSelectedIndex;
- private bool _enableScanning;
- private bool _showAllAmiibo;
- private bool _useRandomUuid;
- private string _usage;
-
- public AmiiboWindowViewModel(StyleableWindow owner, string lastScannedAmiiboId, string titleId)
- {
- _owner = owner;
- _httpClient = new HttpClient { Timeout = TimeSpan.FromMilliseconds(5000) };
- LastScannedAmiiboId = lastScannedAmiiboId;
- TitleId = titleId;
-
- Directory.CreateDirectory(Path.Join(AppDataManager.BaseDirPath, "system", "amiibo"));
-
- _amiiboJsonPath = Path.Join(AppDataManager.BaseDirPath, "system", "amiibo", "Amiibo.json");
- _amiiboList = new List<Amiibo.AmiiboApi>();
- _amiiboSeries = new ObservableCollection<string>();
- _amiibos = new AvaloniaList<Amiibo.AmiiboApi>();
-
- _amiiboLogoBytes = EmbeddedResources.Read("Ryujinx.Ui.Common/Resources/Logo_Amiibo.png");
-
- _ = LoadContentAsync();
- }
-
- public AmiiboWindowViewModel() { }
-
- public string TitleId { get; set; }
- public string LastScannedAmiiboId { get; set; }
-
- public UserResult Response { get; private set; }
-
- public bool UseRandomUuid
- {
- get => _useRandomUuid;
- set
- {
- _useRandomUuid = value;
-
- OnPropertyChanged();
- }
- }
-
- public bool ShowAllAmiibo
- {
- get => _showAllAmiibo;
- set
- {
- _showAllAmiibo = value;
-
-#pragma warning disable 4014
- ParseAmiiboData();
-#pragma warning restore 4014
-
- OnPropertyChanged();
- }
- }
-
- public AvaloniaList<Amiibo.AmiiboApi> AmiiboList
- {
- get => _amiibos;
- set
- {
- _amiibos = value;
-
- OnPropertyChanged();
- }
- }
-
- public ObservableCollection<string> AmiiboSeries
- {
- get => _amiiboSeries;
- set
- {
- _amiiboSeries = value;
- OnPropertyChanged();
- }
- }
-
- public int SeriesSelectedIndex
- {
- get => _seriesSelectedIndex;
- set
- {
- _seriesSelectedIndex = value;
-
- FilterAmiibo();
-
- OnPropertyChanged();
- }
- }
-
- public int AmiiboSelectedIndex
- {
- get => _amiiboSelectedIndex;
- set
- {
- _amiiboSelectedIndex = value;
-
- EnableScanning = _amiiboSelectedIndex >= 0 && _amiiboSelectedIndex < _amiibos.Count;
-
- SetAmiiboDetails();
-
- OnPropertyChanged();
- }
- }
-
- public Bitmap AmiiboImage
- {
- get => _amiiboImage;
- set
- {
- _amiiboImage = value;
-
- OnPropertyChanged();
- }
- }
-
- public string Usage
- {
- get => _usage;
- set
- {
- _usage = value;
-
- OnPropertyChanged();
- }
- }
-
- public bool EnableScanning
- {
- get => _enableScanning;
- set
- {
- _enableScanning = value;
-
- OnPropertyChanged();
- }
- }
-
- public void Dispose()
- {
- _httpClient.Dispose();
- }
-
- private async Task LoadContentAsync()
- {
- string amiiboJsonString = DefaultJson;
-
- if (File.Exists(_amiiboJsonPath))
- {
- amiiboJsonString = File.ReadAllText(_amiiboJsonPath);
-
- if (await NeedsUpdate(JsonHelper.Deserialize<Amiibo.AmiiboJson>(amiiboJsonString).LastUpdated))
- {
- amiiboJsonString = await DownloadAmiiboJson();
- }
- }
- else
- {
- try
- {
- amiiboJsonString = await DownloadAmiiboJson();
- }
- catch
- {
- ShowInfoDialog();
- }
- }
-
- _amiiboList = JsonHelper.Deserialize<Amiibo.AmiiboJson>(amiiboJsonString).Amiibo;
- _amiiboList = _amiiboList.OrderBy(amiibo => amiibo.AmiiboSeries).ToList();
-
- ParseAmiiboData();
- }
-
- private void ParseAmiiboData()
- {
- _amiiboSeries.Clear();
- _amiibos.Clear();
-
- for (int i = 0; i < _amiiboList.Count; i++)
- {
- if (!_amiiboSeries.Contains(_amiiboList[i].AmiiboSeries))
- {
- if (!ShowAllAmiibo)
- {
- foreach (Amiibo.AmiiboApiGamesSwitch game in _amiiboList[i].GamesSwitch)
- {
- if (game != null)
- {
- if (game.GameId.Contains(TitleId))
- {
- AmiiboSeries.Add(_amiiboList[i].AmiiboSeries);
-
- break;
- }
- }
- }
- }
- else
- {
- AmiiboSeries.Add(_amiiboList[i].AmiiboSeries);
- }
- }
- }
-
- if (LastScannedAmiiboId != "")
- {
- SelectLastScannedAmiibo();
- }
- else
- {
- SeriesSelectedIndex = 0;
- }
- }
-
- private void SelectLastScannedAmiibo()
- {
- Amiibo.AmiiboApi scanned = _amiiboList.FirstOrDefault(amiibo => amiibo.GetId() == LastScannedAmiiboId);
-
- SeriesSelectedIndex = AmiiboSeries.IndexOf(scanned.AmiiboSeries);
- AmiiboSelectedIndex = AmiiboList.IndexOf(scanned);
- }
-
- private void FilterAmiibo()
- {
- _amiibos.Clear();
-
- if (_seriesSelectedIndex < 0)
- {
- return;
- }
-
- List<Amiibo.AmiiboApi> amiiboSortedList = _amiiboList
- .Where(amiibo => amiibo.AmiiboSeries == _amiiboSeries[SeriesSelectedIndex])
- .OrderBy(amiibo => amiibo.Name).ToList();
-
- for (int i = 0; i < amiiboSortedList.Count; i++)
- {
- if (!_amiibos.Contains(amiiboSortedList[i]))
- {
- if (!_showAllAmiibo)
- {
- foreach (Amiibo.AmiiboApiGamesSwitch game in amiiboSortedList[i].GamesSwitch)
- {
- if (game != null)
- {
- if (game.GameId.Contains(TitleId))
- {
- _amiibos.Add(amiiboSortedList[i]);
-
- break;
- }
- }
- }
- }
- else
- {
- _amiibos.Add(amiiboSortedList[i]);
- }
- }
- }
-
- AmiiboSelectedIndex = 0;
- }
-
- private void SetAmiiboDetails()
- {
- ResetAmiiboPreview();
-
- Usage = string.Empty;
-
- if (_amiiboSelectedIndex < 0)
- {
- return;
- }
-
- Amiibo.AmiiboApi selected = _amiibos[_amiiboSelectedIndex];
-
- string imageUrl = _amiiboList.FirstOrDefault(amiibo => amiibo.Equals(selected)).Image;
-
- string usageString = "";
-
- for (int i = 0; i < _amiiboList.Count; i++)
- {
- if (_amiiboList[i].Equals(selected))
- {
- bool writable = false;
-
- foreach (Amiibo.AmiiboApiGamesSwitch item in _amiiboList[i].GamesSwitch)
- {
- if (item.GameId.Contains(TitleId))
- {
- foreach (Amiibo.AmiiboApiUsage usageItem in item.AmiiboUsage)
- {
- usageString += Environment.NewLine +
- $"- {usageItem.Usage.Replace("/", Environment.NewLine + "-")}";
-
- writable = usageItem.Write;
- }
- }
- }
-
- if (usageString.Length == 0)
- {
- usageString = LocaleManager.Instance["Unknown"] + ".";
- }
-
- Usage = $"{LocaleManager.Instance["Usage"]} {(writable ? $" ({LocaleManager.Instance["Writable"]})" : "")} : {usageString}";
- }
- }
-
- _ = UpdateAmiiboPreview(imageUrl);
- }
-
- private async Task<bool> NeedsUpdate(DateTime oldLastModified)
- {
- try
- {
- HttpResponseMessage response =
- await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://amiibo.ryujinx.org/"));
-
- if (response.IsSuccessStatusCode)
- {
- return response.Content.Headers.LastModified != oldLastModified;
- }
-
- return false;
- }
- catch
- {
- ShowInfoDialog();
-
- return false;
- }
- }
-
- private async Task<string> DownloadAmiiboJson()
- {
- HttpResponseMessage response = await _httpClient.GetAsync("https://amiibo.ryujinx.org/");
-
- if (response.IsSuccessStatusCode)
- {
- string amiiboJsonString = await response.Content.ReadAsStringAsync();
-
- using (FileStream amiiboJsonStream = File.Create(_amiiboJsonPath, 4096, FileOptions.WriteThrough))
- {
- amiiboJsonStream.Write(Encoding.UTF8.GetBytes(amiiboJsonString));
- }
-
- return amiiboJsonString;
- }
-
- await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance["DialogAmiiboApiTitle"],
- LocaleManager.Instance["DialogAmiiboApiFailFetchMessage"],
- LocaleManager.Instance["InputDialogOk"],
- "",
- LocaleManager.Instance["RyujinxInfo"]);
-
- Close();
-
- return DefaultJson;
- }
-
- private void Close()
- {
- Dispatcher.UIThread.Post(_owner.Close);
- }
-
- private async Task UpdateAmiiboPreview(string imageUrl)
- {
- HttpResponseMessage response = await _httpClient.GetAsync(imageUrl);
-
- if (response.IsSuccessStatusCode)
- {
- byte[] amiiboPreviewBytes = await response.Content.ReadAsByteArrayAsync();
- using (MemoryStream memoryStream = new(amiiboPreviewBytes))
- {
- Bitmap bitmap = new(memoryStream);
-
- double ratio = Math.Min(AmiiboImageSize / bitmap.Size.Width,
- AmiiboImageSize / bitmap.Size.Height);
-
- int resizeHeight = (int)(bitmap.Size.Height * ratio);
- int resizeWidth = (int)(bitmap.Size.Width * ratio);
-
- AmiiboImage = bitmap.CreateScaledBitmap(new PixelSize(resizeWidth, resizeHeight));
- }
- }
- }
-
- private void ResetAmiiboPreview()
- {
- using (MemoryStream memoryStream = new(_amiiboLogoBytes))
- {
- Bitmap bitmap = new(memoryStream);
-
- AmiiboImage = bitmap;
- }
- }
-
- private async void ShowInfoDialog()
- {
- await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance["DialogAmiiboApiTitle"],
- LocaleManager.Instance["DialogAmiiboApiConnectErrorMessage"],
- LocaleManager.Instance["InputDialogOk"],
- "",
- LocaleManager.Instance["RyujinxInfo"]);
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Ava/Ui/ViewModels/AvatarProfileViewModel.cs b/Ryujinx.Ava/Ui/ViewModels/AvatarProfileViewModel.cs
deleted file mode 100644
index c2983741..00000000
--- a/Ryujinx.Ava/Ui/ViewModels/AvatarProfileViewModel.cs
+++ /dev/null
@@ -1,363 +0,0 @@
-using Avalonia.Media;
-using DynamicData;
-using LibHac.Common;
-using LibHac.Fs;
-using LibHac.Fs.Fsa;
-using LibHac.FsSystem;
-using LibHac.Ncm;
-using LibHac.Tools.Fs;
-using LibHac.Tools.FsSystem;
-using LibHac.Tools.FsSystem.NcaUtils;
-using Ryujinx.Ava.Ui.Models;
-using Ryujinx.HLE.FileSystem;
-using SixLabors.ImageSharp;
-using SixLabors.ImageSharp.Formats.Png;
-using SixLabors.ImageSharp.PixelFormats;
-using SixLabors.ImageSharp.Processing;
-using System;
-using System.Buffers.Binary;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.IO;
-using System.Linq;
-using System.Threading;
-using System.Threading.Tasks;
-using Color = Avalonia.Media.Color;
-
-namespace Ryujinx.Ava.Ui.ViewModels
-{
- internal class AvatarProfileViewModel : BaseModel, IDisposable
- {
- private const int MaxImageTasks = 4;
-
- private static readonly Dictionary<string, byte[]> _avatarStore = new();
- private static bool _isPreloading;
- private static Action _loadCompleteAction;
-
- private ObservableCollection<ProfileImageModel> _images;
- private Color _backgroundColor = Colors.White;
-
- private int _selectedIndex;
- private int _imagesLoaded;
- private bool _isActive;
- private byte[] _selectedImage;
- private bool _isIndeterminate = true;
-
- public bool IsActive
- {
- get => _isActive;
- set => _isActive = value;
- }
-
- public AvatarProfileViewModel()
- {
- _images = new ObservableCollection<ProfileImageModel>();
- }
-
- public AvatarProfileViewModel(Action loadCompleteAction)
- {
- _images = new ObservableCollection<ProfileImageModel>();
-
- if (_isPreloading)
- {
- _loadCompleteAction = loadCompleteAction;
- }
- else
- {
- ReloadImages();
- }
- }
-
- public Color BackgroundColor
- {
- get => _backgroundColor;
- set
- {
- _backgroundColor = value;
-
- IsActive = false;
-
- ReloadImages();
- }
- }
-
- public ObservableCollection<ProfileImageModel> Images
- {
- get => _images;
- set
- {
- _images = value;
- OnPropertyChanged();
- }
- }
-
- public bool IsIndeterminate
- {
- get => _isIndeterminate;
- set
- {
- _isIndeterminate = value;
-
- OnPropertyChanged();
- }
- }
-
- public int ImageCount => _avatarStore.Count;
-
- public int ImagesLoaded
- {
- get => _imagesLoaded;
- set
- {
- _imagesLoaded = value;
- OnPropertyChanged();
- }
- }
-
- public int SelectedIndex
- {
- get => _selectedIndex;
- set
- {
- _selectedIndex = value;
-
- if (_selectedIndex == -1)
- {
- SelectedImage = null;
- }
- else
- {
- SelectedImage = _images[_selectedIndex].Data;
- }
-
- OnPropertyChanged();
- }
- }
-
- public byte[] SelectedImage
- {
- get => _selectedImage;
- private set => _selectedImage = value;
- }
-
- public void ReloadImages()
- {
- if (_isPreloading)
- {
- IsIndeterminate = false;
- return;
- }
- Task.Run(() =>
- {
- IsActive = true;
-
- Images.Clear();
- int selectedIndex = _selectedIndex;
- int index = 0;
-
- ImagesLoaded = 0;
- IsIndeterminate = false;
-
- var keys = _avatarStore.Keys.ToList();
-
- var newImages = new List<ProfileImageModel>();
- var tasks = new List<Task>();
-
- for (int i = 0; i < MaxImageTasks; i++)
- {
- var start = i;
- tasks.Add(Task.Run(() => ImageTask(start)));
- }
-
- Task.WaitAll(tasks.ToArray());
-
- Images.AddRange(newImages);
-
- void ImageTask(int start)
- {
- for (int i = start; i < keys.Count; i += MaxImageTasks)
- {
- if (!IsActive)
- {
- return;
- }
-
- var key = keys[i];
- var image = _avatarStore[keys[i]];
-
- var data = ProcessImage(image);
- newImages.Add(new ProfileImageModel(key, data));
- if (index++ == selectedIndex)
- {
- SelectedImage = data;
- }
-
- Interlocked.Increment(ref _imagesLoaded);
- OnPropertyChanged(nameof(ImagesLoaded));
- }
- }
- });
- }
-
- private byte[] ProcessImage(byte[] data)
- {
- using (MemoryStream streamJpg = new())
- {
- Image avatarImage = Image.Load(data, new PngDecoder());
-
- avatarImage.Mutate(x => x.BackgroundColor(new Rgba32(BackgroundColor.R,
- BackgroundColor.G,
- BackgroundColor.B,
- BackgroundColor.A)));
- avatarImage.SaveAsJpeg(streamJpg);
-
- return streamJpg.ToArray();
- }
- }
-
- public static void PreloadAvatars(ContentManager contentManager, VirtualFileSystem virtualFileSystem)
- {
- try
- {
- if (_avatarStore.Count > 0)
- {
- return;
- }
-
- _isPreloading = true;
-
- string contentPath =
- contentManager.GetInstalledContentPath(0x010000000000080A, StorageId.BuiltInSystem,
- NcaContentType.Data);
- string avatarPath = virtualFileSystem.SwitchPathToSystemPath(contentPath);
-
- if (!string.IsNullOrWhiteSpace(avatarPath))
- {
- using (IStorage ncaFileStream = new LocalStorage(avatarPath, FileAccess.Read, FileMode.Open))
- {
- Nca nca = new(virtualFileSystem.KeySet, ncaFileStream);
- IFileSystem romfs = nca.OpenFileSystem(NcaSectionType.Data, IntegrityCheckLevel.ErrorOnInvalid);
-
- foreach (DirectoryEntryEx item in romfs.EnumerateEntries())
- {
- // 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 var file = new UniqueRef<IFile>();
-
- romfs.OpenFile(ref file.Ref(), ("/" + item.FullPath).ToU8Span(), OpenMode.Read)
- .ThrowIfFailure();
-
- using (MemoryStream stream = new())
- using (MemoryStream streamPng = new())
- {
- file.Get.AsStream().CopyTo(stream);
-
- stream.Position = 0;
-
- Image avatarImage = Image.LoadPixelData<Rgba32>(DecompressYaz0(stream), 256, 256);
-
- avatarImage.SaveAsPng(streamPng);
-
- _avatarStore.Add(item.FullPath, streamPng.ToArray());
- }
- }
- }
- }
- }
- }
- finally
- {
- _isPreloading = false;
- _loadCompleteAction?.Invoke();
- }
- }
-
- private static byte[] DecompressYaz0(Stream stream)
- {
- using (BinaryReader reader = new(stream))
- {
- reader.ReadInt32(); // Magic
-
- uint decodedLength = BinaryPrimitives.ReverseEndianness(reader.ReadUInt32());
-
- reader.ReadInt64(); // Padding
-
- byte[] input = new byte[stream.Length - stream.Position];
- stream.Read(input, 0, input.Length);
-
- uint inputOffset = 0;
-
- byte[] output = new byte[decodedLength];
- uint outputOffset = 0;
-
- ushort mask = 0;
- byte header = 0;
-
- while (outputOffset < decodedLength)
- {
- if ((mask >>= 1) == 0)
- {
- header = input[inputOffset++];
- mask = 0x80;
- }
-
- if ((header & mask) != 0)
- {
- if (outputOffset == output.Length)
- {
- break;
- }
-
- output[outputOffset++] = input[inputOffset++];
- }
- else
- {
- byte byte1 = input[inputOffset++];
- byte byte2 = input[inputOffset++];
-
- uint dist = (uint)((byte1 & 0xF) << 8) | byte2;
- uint position = outputOffset - (dist + 1);
-
- uint length = (uint)byte1 >> 4;
- if (length == 0)
- {
- length = (uint)input[inputOffset++] + 0x12;
- }
- else
- {
- length += 2;
- }
-
- uint gap = outputOffset - position;
- uint nonOverlappingLength = length;
-
- if (nonOverlappingLength > gap)
- {
- nonOverlappingLength = gap;
- }
-
- Buffer.BlockCopy(output, (int)position, output, (int)outputOffset, (int)nonOverlappingLength);
- outputOffset += nonOverlappingLength;
- position += nonOverlappingLength;
- length -= nonOverlappingLength;
-
- while (length-- > 0)
- {
- output[outputOffset++] = output[position++];
- }
- }
- }
-
- return output;
- }
- }
-
- public void Dispose()
- {
- _loadCompleteAction = null;
- IsActive = false;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Ava/Ui/ViewModels/BaseModel.cs b/Ryujinx.Ava/Ui/ViewModels/BaseModel.cs
deleted file mode 100644
index abb14c7d..00000000
--- a/Ryujinx.Ava/Ui/ViewModels/BaseModel.cs
+++ /dev/null
@@ -1,15 +0,0 @@
-using System.ComponentModel;
-using System.Runtime.CompilerServices;
-
-namespace Ryujinx.Ava.Ui.ViewModels
-{
- public class BaseModel : INotifyPropertyChanged
- {
- public event PropertyChangedEventHandler PropertyChanged;
-
- protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Ava/Ui/ViewModels/ControllerSettingsViewModel.cs b/Ryujinx.Ava/Ui/ViewModels/ControllerSettingsViewModel.cs
deleted file mode 100644
index c7690316..00000000
--- a/Ryujinx.Ava/Ui/ViewModels/ControllerSettingsViewModel.cs
+++ /dev/null
@@ -1,900 +0,0 @@
-using Avalonia.Collections;
-using Avalonia.Controls;
-using Avalonia.Controls.ApplicationLifetimes;
-using Avalonia.Svg.Skia;
-using Avalonia.Threading;
-using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.Input;
-using Ryujinx.Ava.Ui.Controls;
-using Ryujinx.Ava.Ui.Models;
-using Ryujinx.Ava.Ui.Windows;
-using Ryujinx.Common;
-using Ryujinx.Common.Configuration;
-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 Ryujinx.Common.Logging;
-using Ryujinx.Common.Utilities;
-using Ryujinx.Input;
-using Ryujinx.Ui.Common.Configuration;
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.IO;
-using System.Linq;
-using System.Text.Json;
-using ConfigGamepadInputId = Ryujinx.Common.Configuration.Hid.Controller.GamepadInputId;
-using ConfigStickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
-using Key = Ryujinx.Common.Configuration.Hid.Key;
-
-namespace Ryujinx.Ava.Ui.ViewModels
-{
- public class ControllerSettingsViewModel : BaseModel, IDisposable
- {
- private const string Disabled = "disabled";
- private const string ProControllerResource = "Ryujinx.Ui.Common/Resources/Controller_ProCon.svg";
- private const string JoyConPairResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConPair.svg";
- private const string JoyConLeftResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConLeft.svg";
- private const string JoyConRightResource = "Ryujinx.Ui.Common/Resources/Controller_JoyConRight.svg";
- private const string KeyboardString = "keyboard";
- private const string ControllerString = "controller";
- private readonly MainWindow _mainWindow;
-
- private PlayerIndex _playerId;
- private int _controller;
- private int _controllerNumber = 0;
- private string _controllerImage;
- private int _device;
- private object _configuration;
- private string _profileName;
- private bool _isLoaded;
- private readonly UserControl _owner;
-
- public IGamepadDriver AvaloniaKeyboardDriver { get; }
- public IGamepad SelectedGamepad { get; private set; }
-
- public ObservableCollection<PlayerModel> PlayerIndexes { get; set; }
- public ObservableCollection<(DeviceType Type, string Id, string Name)> Devices { get; set; }
- internal ObservableCollection<ControllerModel> Controllers { get; set; }
- public AvaloniaList<string> ProfilesList { get; set; }
- public AvaloniaList<string> DeviceList { get; set; }
-
- // XAML Flags
- public bool ShowSettings => _device > 0;
- public bool IsController => _device > 1;
- public bool IsKeyboard => !IsController;
- public bool IsRight { get; set; }
- public bool IsLeft { get; set; }
-
- public bool IsModified { get; set; }
-
- public object Configuration
- {
- get => _configuration;
- set
- {
- _configuration = value;
-
- OnPropertyChanged();
- }
- }
-
- public PlayerIndex PlayerId
- {
- get => _playerId;
- set
- {
- if (IsModified)
- {
- return;
- }
-
- IsModified = false;
- _playerId = value;
-
- if (!Enum.IsDefined(typeof(PlayerIndex), _playerId))
- {
- _playerId = PlayerIndex.Player1;
- }
-
- LoadConfiguration();
- LoadDevice();
- LoadProfiles();
-
- _isLoaded = true;
-
- OnPropertyChanged();
- }
- }
-
- public int Controller
- {
- get => _controller;
- set
- {
- _controller = value;
-
- if (_controller == -1)
- {
- _controller = 0;
- }
-
- if (Controllers.Count > 0 && value < Controllers.Count && _controller > -1)
- {
- ControllerType controller = Controllers[_controller].Type;
-
- IsLeft = true;
- IsRight = true;
-
- switch (controller)
- {
- case ControllerType.Handheld:
- ControllerImage = JoyConPairResource;
- break;
- case ControllerType.ProController:
- ControllerImage = ProControllerResource;
- break;
- case ControllerType.JoyconPair:
- ControllerImage = JoyConPairResource;
- break;
- case ControllerType.JoyconLeft:
- ControllerImage = JoyConLeftResource;
- IsRight = false;
- break;
- case ControllerType.JoyconRight:
- ControllerImage = JoyConRightResource;
- IsLeft = false;
- break;
- }
-
- LoadInputDriver();
- LoadProfiles();
- }
-
- OnPropertyChanged();
- NotifyChanges();
- }
- }
-
- public string ControllerImage
- {
- get => _controllerImage;
- set
- {
- _controllerImage = value;
-
- OnPropertyChanged();
- OnPropertyChanged(nameof(Image));
- }
- }
-
- public SvgImage Image
- {
- get
- {
- SvgImage image = new SvgImage();
-
- if (!string.IsNullOrWhiteSpace(_controllerImage))
- {
- SvgSource source = new SvgSource();
-
- source.Load(EmbeddedResources.GetStream(_controllerImage));
-
- image.Source = source;
- }
-
- return image;
- }
- }
-
- public string ProfileName
- {
- get => _profileName; set
- {
- _profileName = value;
-
- OnPropertyChanged();
- }
- }
-
- public int Device
- {
- get => _device;
- set
- {
- _device = value < 0 ? 0 : value;
-
- if (_device >= Devices.Count)
- {
- return;
- }
-
- var selected = Devices[_device].Type;
-
- if (selected != DeviceType.None)
- {
- LoadControllers();
-
- if (_isLoaded)
- {
- LoadConfiguration(LoadDefaultConfiguration());
- }
- }
-
- OnPropertyChanged();
- NotifyChanges();
- }
- }
-
- public InputConfig Config { get; set; }
-
- public ControllerSettingsViewModel(UserControl owner) : this()
- {
- _owner = owner;
-
- if (Program.PreviewerDetached)
- {
- _mainWindow =
- (MainWindow)((IClassicDesktopStyleApplicationLifetime)Avalonia.Application.Current
- .ApplicationLifetime).MainWindow;
-
- AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner);
-
- _mainWindow.InputManager.GamepadDriver.OnGamepadConnected += HandleOnGamepadConnected;
- _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected += HandleOnGamepadDisconnected;
- if (_mainWindow.AppHost != null)
- {
- _mainWindow.AppHost.NpadManager.BlockInputUpdates();
- }
-
- _isLoaded = false;
-
- LoadDevices();
-
- PlayerId = PlayerIndex.Player1;
- }
- }
-
- public ControllerSettingsViewModel()
- {
- 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>();
-
- ControllerImage = ProControllerResource;
-
- PlayerIndexes.Add(new(PlayerIndex.Player1, LocaleManager.Instance["ControllerSettingsPlayer1"]));
- PlayerIndexes.Add(new(PlayerIndex.Player2, LocaleManager.Instance["ControllerSettingsPlayer2"]));
- PlayerIndexes.Add(new(PlayerIndex.Player3, LocaleManager.Instance["ControllerSettingsPlayer3"]));
- PlayerIndexes.Add(new(PlayerIndex.Player4, LocaleManager.Instance["ControllerSettingsPlayer4"]));
- PlayerIndexes.Add(new(PlayerIndex.Player5, LocaleManager.Instance["ControllerSettingsPlayer5"]));
- PlayerIndexes.Add(new(PlayerIndex.Player6, LocaleManager.Instance["ControllerSettingsPlayer6"]));
- PlayerIndexes.Add(new(PlayerIndex.Player7, LocaleManager.Instance["ControllerSettingsPlayer7"]));
- PlayerIndexes.Add(new(PlayerIndex.Player8, LocaleManager.Instance["ControllerSettingsPlayer8"]));
- PlayerIndexes.Add(new(PlayerIndex.Handheld, LocaleManager.Instance["ControllerSettingsHandheld"]));
- }
-
- private void LoadConfiguration(InputConfig inputConfig = null)
- {
- Config = inputConfig ?? ConfigurationState.Instance.Hid.InputConfig.Value.Find(inputConfig => inputConfig.PlayerIndex == _playerId);
-
- if (Config is StandardKeyboardInputConfig keyboardInputConfig)
- {
- Configuration = new InputConfiguration<Key, ConfigStickInputId>(keyboardInputConfig);
- }
-
- if (Config is StandardControllerInputConfig controllerInputConfig)
- {
- Configuration = new InputConfiguration<ConfigGamepadInputId, ConfigStickInputId>(controllerInputConfig);
- }
- }
-
- public void LoadDevice()
- {
- if (Config == null || Config.Backend == InputBackendType.Invalid)
- {
- Device = 0;
- }
- else
- {
- var type = DeviceType.None;
-
- if (Config is StandardKeyboardInputConfig)
- {
- type = DeviceType.Keyboard;
- }
-
- if (Config is StandardControllerInputConfig)
- {
- type = DeviceType.Controller;
- }
-
- var item = Devices.FirstOrDefault(x => x.Type == type && x.Id == Config.Id);
- if (item != default)
- {
- Device = Devices.ToList().FindIndex(x => x.Id == item.Id);
- }
- else
- {
- Device = 0;
- }
- }
- }
-
- public async void ShowMotionConfig()
- {
- await MotionSettingsWindow.Show(this);
- }
-
- public async void ShowRumbleConfig()
- {
- await RumbleSettingsWindow.Show(this);
- }
-
- private void LoadInputDriver()
- {
- if (_device < 0)
- {
- return;
- }
-
- string id = GetCurrentGamepadId();
- var type = Devices[Device].Type;
-
- if (type == DeviceType.None)
- {
- return;
- }
- else if (type == DeviceType.Keyboard)
- {
- if (_mainWindow.InputManager.KeyboardDriver is AvaloniaKeyboardDriver)
- {
- // NOTE: To get input in this window, we need to bind a custom keyboard driver instead of using the InputManager one as the main window isn't focused...
- SelectedGamepad = AvaloniaKeyboardDriver.GetGamepad(id);
- }
- else
- {
- SelectedGamepad = _mainWindow.InputManager.KeyboardDriver.GetGamepad(id);
- }
- }
- else
- {
- SelectedGamepad = _mainWindow.InputManager.GamepadDriver.GetGamepad(id);
- }
- }
-
- private void HandleOnGamepadDisconnected(string id)
- {
- Dispatcher.UIThread.Post(() =>
- {
- LoadDevices();
- });
- }
-
- private void HandleOnGamepadConnected(string id)
- {
- Dispatcher.UIThread.Post(() =>
- {
- LoadDevices();
- });
- }
-
- private string GetCurrentGamepadId()
- {
- if (_device < 0)
- {
- return string.Empty;
- }
-
- var device = Devices[Device];
-
- if (device.Type == DeviceType.None)
- {
- return null;
- }
-
- return device.Id.Split(" ")[0];
- }
-
- public void LoadControllers()
- {
- Controllers.Clear();
-
- if (_playerId == PlayerIndex.Handheld)
- {
- Controllers.Add(new(ControllerType.Handheld, LocaleManager.Instance["ControllerSettingsControllerTypeHandheld"]));
-
- Controller = 0;
- }
- else
- {
- Controllers.Add(new(ControllerType.ProController, LocaleManager.Instance["ControllerSettingsControllerTypeProController"]));
- Controllers.Add(new(ControllerType.JoyconPair, LocaleManager.Instance["ControllerSettingsControllerTypeJoyConPair"]));
- Controllers.Add(new(ControllerType.JoyconLeft, LocaleManager.Instance["ControllerSettingsControllerTypeJoyConLeft"]));
- Controllers.Add(new(ControllerType.JoyconRight, LocaleManager.Instance["ControllerSettingsControllerTypeJoyConRight"]));
-
- if (Config != null && Controllers.ToList().FindIndex(x => x.Type == Config.ControllerType) != -1)
- {
- Controller = Controllers.ToList().FindIndex(x => x.Type == Config.ControllerType);
- }
- else
- {
- Controller = 0;
- }
- }
- }
-
- private static string GetShortGamepadName(string str)
- {
- const string Ellipsis = "...";
- const int MaxSize = 50;
-
- if (str.Length > MaxSize)
- {
- return str.Substring(0, MaxSize - Ellipsis.Length) + Ellipsis;
- }
-
- return str;
- }
-
- private static string GetShortGamepadId(string str)
- {
- const string Hyphen = "-";
- const int Offset = 1;
-
- return str.Substring(str.IndexOf(Hyphen) + Offset);
- }
-
- public void LoadDevices()
- {
- lock (Devices)
- {
- Devices.Clear();
- DeviceList.Clear();
- Devices.Add((DeviceType.None, Disabled, LocaleManager.Instance["ControllerSettingsDeviceDisabled"]));
-
- foreach (string id in _mainWindow.InputManager.KeyboardDriver.GamepadsIds)
- {
- using IGamepad gamepad = _mainWindow.InputManager.KeyboardDriver.GetGamepad(id);
-
- if (gamepad != null)
- {
- Devices.Add((DeviceType.Keyboard, id, $"{GetShortGamepadName(gamepad.Name)}"));
- }
- }
-
- foreach (string id in _mainWindow.InputManager.GamepadDriver.GamepadsIds)
- {
- using IGamepad gamepad = _mainWindow.InputManager.GamepadDriver.GetGamepad(id);
-
- if (gamepad != null)
- {
- if (Devices.Any(controller => GetShortGamepadId(controller.Id) == GetShortGamepadId(gamepad.Id)))
- {
- _controllerNumber++;
- }
-
- Devices.Add((DeviceType.Controller, id, $"{GetShortGamepadName(gamepad.Name)} ({_controllerNumber})"));
- }
- }
-
- _controllerNumber = 0;
-
- DeviceList.AddRange(Devices.Select(x => x.Name));
- Device = Math.Min(Device, DeviceList.Count);
- }
- }
-
- private string GetProfileBasePath()
- {
- string path = AppDataManager.ProfilesDirPath;
- var type = Devices[Device == -1 ? 0 : Device].Type;
-
- if (type == DeviceType.Keyboard)
- {
- path = Path.Combine(path, KeyboardString);
- }
- else if (type == DeviceType.Controller)
- {
- path = Path.Combine(path, ControllerString);
- }
-
- return path;
- }
-
- private void LoadProfiles()
- {
- ProfilesList.Clear();
-
- string basePath = GetProfileBasePath();
-
- if (!Directory.Exists(basePath))
- {
- Directory.CreateDirectory(basePath);
- }
-
- ProfilesList.Add((LocaleManager.Instance["ControllerSettingsProfileDefault"]));
-
- foreach (string profile in Directory.GetFiles(basePath, "*.json", SearchOption.AllDirectories))
- {
- ProfilesList.Add(Path.GetFileNameWithoutExtension(profile));
- }
-
- if (string.IsNullOrWhiteSpace(ProfileName))
- {
- ProfileName = LocaleManager.Instance["ControllerSettingsProfileDefault"];
- }
- }
-
- public InputConfig LoadDefaultConfiguration()
- {
- var activeDevice = Devices.FirstOrDefault();
-
- if (Devices.Count > 0 && Device < Devices.Count && Device >= 0)
- {
- activeDevice = Devices[Device];
- }
-
- InputConfig config;
- if (activeDevice.Type == DeviceType.Keyboard)
- {
- string id = activeDevice.Id;
-
- config = new StandardKeyboardInputConfig
- {
- Version = InputConfig.CurrentVersion,
- Backend = InputBackendType.WindowKeyboard,
- Id = id,
- ControllerType = ControllerType.ProController,
- LeftJoycon = new LeftJoyconCommonConfig<Key>
- {
- DpadUp = Key.Up,
- DpadDown = Key.Down,
- DpadLeft = Key.Left,
- DpadRight = Key.Right,
- ButtonMinus = Key.Minus,
- ButtonL = Key.E,
- ButtonZl = Key.Q,
- ButtonSl = Key.Unbound,
- ButtonSr = Key.Unbound
- },
- LeftJoyconStick =
- new JoyconConfigKeyboardStick<Key>
- {
- StickUp = Key.W,
- StickDown = Key.S,
- StickLeft = Key.A,
- StickRight = Key.D,
- StickButton = Key.F
- },
- RightJoycon = new RightJoyconCommonConfig<Key>
- {
- ButtonA = Key.Z,
- ButtonB = Key.X,
- ButtonX = Key.C,
- ButtonY = Key.V,
- ButtonPlus = Key.Plus,
- ButtonR = Key.U,
- ButtonZr = Key.O,
- ButtonSl = Key.Unbound,
- ButtonSr = Key.Unbound
- },
- RightJoyconStick = new JoyconConfigKeyboardStick<Key>
- {
- StickUp = Key.I,
- StickDown = Key.K,
- StickLeft = Key.J,
- StickRight = Key.L,
- StickButton = Key.H
- }
- };
- }
- else if (activeDevice.Type == DeviceType.Controller)
- {
- bool isNintendoStyle = Devices.ToList().Find(x => x.Id == activeDevice.Id).Name.Contains("Nintendo");
-
- string id = activeDevice.Id.Split(" ")[0];
-
- config = new StandardControllerInputConfig
- {
- Version = InputConfig.CurrentVersion,
- Backend = InputBackendType.GamepadSDL2,
- Id = id,
- ControllerType = ControllerType.ProController,
- DeadzoneLeft = 0.1f,
- DeadzoneRight = 0.1f,
- RangeLeft = 1.0f,
- RangeRight = 1.0f,
- TriggerThreshold = 0.5f,
- LeftJoycon = new LeftJoyconCommonConfig<ConfigGamepadInputId>
- {
- DpadUp = ConfigGamepadInputId.DpadUp,
- DpadDown = ConfigGamepadInputId.DpadDown,
- DpadLeft = ConfigGamepadInputId.DpadLeft,
- DpadRight = ConfigGamepadInputId.DpadRight,
- ButtonMinus = ConfigGamepadInputId.Minus,
- ButtonL = ConfigGamepadInputId.LeftShoulder,
- ButtonZl = ConfigGamepadInputId.LeftTrigger,
- ButtonSl = ConfigGamepadInputId.Unbound,
- ButtonSr = ConfigGamepadInputId.Unbound
- },
- LeftJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
- {
- Joystick = ConfigStickInputId.Left,
- StickButton = ConfigGamepadInputId.LeftStick,
- InvertStickX = false,
- InvertStickY = false
- },
- RightJoycon = new RightJoyconCommonConfig<ConfigGamepadInputId>
- {
- ButtonA = isNintendoStyle ? ConfigGamepadInputId.A : ConfigGamepadInputId.B,
- ButtonB = isNintendoStyle ? ConfigGamepadInputId.B : ConfigGamepadInputId.A,
- ButtonX = isNintendoStyle ? ConfigGamepadInputId.X : ConfigGamepadInputId.Y,
- ButtonY = isNintendoStyle ? ConfigGamepadInputId.Y : ConfigGamepadInputId.X,
- ButtonPlus = ConfigGamepadInputId.Plus,
- ButtonR = ConfigGamepadInputId.RightShoulder,
- ButtonZr = ConfigGamepadInputId.RightTrigger,
- ButtonSl = ConfigGamepadInputId.Unbound,
- ButtonSr = ConfigGamepadInputId.Unbound
- },
- RightJoyconStick = new JoyconConfigControllerStick<ConfigGamepadInputId, ConfigStickInputId>
- {
- Joystick = ConfigStickInputId.Right,
- StickButton = ConfigGamepadInputId.RightStick,
- InvertStickX = false,
- InvertStickY = false
- },
- Motion = new StandardMotionConfigController
- {
- MotionBackend = MotionInputBackendType.GamepadDriver,
- EnableMotion = true,
- Sensitivity = 100,
- GyroDeadzone = 1
- },
- Rumble = new RumbleConfigController
- {
- StrongRumble = 1f,
- WeakRumble = 1f,
- EnableRumble = false
- }
- };
- }
- else
- {
- config = new InputConfig();
- }
-
- config.PlayerIndex = _playerId;
-
- return config;
- }
-
- public async void LoadProfile()
- {
- if (Device == 0)
- {
- return;
- }
-
- InputConfig config = null;
-
- if (string.IsNullOrWhiteSpace(ProfileName))
- {
- return;
- }
-
- if (ProfileName == LocaleManager.Instance["ControllerSettingsProfileDefault"])
- {
- config = LoadDefaultConfiguration();
- }
- else
- {
- string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
-
- if (!File.Exists(path))
- {
- var index = ProfilesList.IndexOf(ProfileName);
- if (index != -1)
- {
- ProfilesList.RemoveAt(index);
- }
- return;
- }
-
- try
- {
- using (Stream stream = File.OpenRead(path))
- {
- config = JsonHelper.Deserialize<InputConfig>(stream);
- }
- }
- catch (JsonException) { }
- catch (InvalidOperationException)
- {
- Logger.Error?.Print(LogClass.Configuration, $"Profile {ProfileName} is incompatible with the current input configuration system.");
-
- await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["DialogProfileInvalidProfileErrorMessage"], ProfileName));
-
- return;
- }
- }
-
- if (config != null)
- {
- _isLoaded = false;
-
- LoadConfiguration(config);
-
- LoadDevice();
-
- _isLoaded = true;
-
- NotifyChanges();
- }
- }
-
- public async void SaveProfile()
- {
- if (Device == 0)
- {
- return;
- }
-
- if (Configuration == null)
- {
- return;
- }
-
- if (ProfileName == LocaleManager.Instance["ControllerSettingsProfileDefault"])
- {
- await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogProfileDefaultProfileOverwriteErrorMessage"]);
-
- return;
- }
- else
- {
- bool validFileName = ProfileName.IndexOfAny(Path.GetInvalidFileNameChars()) == -1;
-
- if (validFileName)
- {
- string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
-
- InputConfig config = null;
-
- if (IsKeyboard)
- {
- config = (Configuration as InputConfiguration<Key, ConfigStickInputId>).GetConfig();
- }
- else if (IsController)
- {
- config = (Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>).GetConfig();
- }
-
- config.ControllerType = Controllers[_controller].Type;
-
- string jsonString = JsonHelper.Serialize(config, true);
-
- await File.WriteAllTextAsync(path, jsonString);
-
- LoadProfiles();
- }
- else
- {
- await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogProfileInvalidProfileNameErrorMessage"]);
- }
- }
- }
-
- public async void RemoveProfile()
- {
- if (Device == 0 || ProfileName == LocaleManager.Instance["ControllerSettingsProfileDefault"] || ProfilesList.IndexOf(ProfileName) == -1)
- {
- return;
- }
-
- UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
- LocaleManager.Instance["DialogProfileDeleteProfileTitle"],
- LocaleManager.Instance["DialogProfileDeleteProfileMessage"],
- LocaleManager.Instance["InputDialogYes"],
- LocaleManager.Instance["InputDialogNo"],
- LocaleManager.Instance["RyujinxConfirm"]);
-
- if (result == UserResult.Yes)
- {
- string path = Path.Combine(GetProfileBasePath(), ProfileName + ".json");
-
- if (File.Exists(path))
- {
- File.Delete(path);
- }
-
- LoadProfiles();
- }
- }
-
- public void Save()
- {
- IsModified = false;
-
- List<InputConfig> newConfig = new();
-
- newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value);
-
- newConfig.Remove(newConfig.Find(x => x == null));
-
- if (Device == 0)
- {
- newConfig.Remove(newConfig.Find(x => x.PlayerIndex == this.PlayerId));
- }
- else
- {
- var device = Devices[Device];
-
- if (device.Type == DeviceType.Keyboard)
- {
- var inputConfig = Configuration as InputConfiguration<Key, ConfigStickInputId>;
- inputConfig.Id = device.Id;
- }
- else
- {
- var inputConfig = Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>;
- inputConfig.Id = device.Id.Split(" ")[0];
- }
-
- var config = !IsController
- ? (Configuration as InputConfiguration<Key, ConfigStickInputId>).GetConfig()
- : (Configuration as InputConfiguration<GamepadInputId, ConfigStickInputId>).GetConfig();
- config.ControllerType = Controllers[_controller].Type;
- config.PlayerIndex = _playerId;
-
- int i = newConfig.FindIndex(x => x.PlayerIndex == PlayerId);
- if (i == -1)
- {
- newConfig.Add(config);
- }
- else
- {
- newConfig[i] = config;
- }
- }
-
- _mainWindow.AppHost?.NpadManager.ReloadConfiguration(newConfig, ConfigurationState.Instance.Hid.EnableKeyboard, ConfigurationState.Instance.Hid.EnableMouse);
-
- // Atomically replace and signal input change.
- // NOTE: Do not modify InputConfig.Value directly as other code depends on the on-change event.
- ConfigurationState.Instance.Hid.InputConfig.Value = newConfig;
-
- ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
- }
-
- public void NotifyChange(string property)
- {
- OnPropertyChanged(property);
- }
-
- public void NotifyChanges()
- {
- OnPropertyChanged(nameof(Configuration));
- OnPropertyChanged(nameof(IsController));
- OnPropertyChanged(nameof(ShowSettings));
- OnPropertyChanged(nameof(IsKeyboard));
- OnPropertyChanged(nameof(IsRight));
- OnPropertyChanged(nameof(IsLeft));
- }
-
- public void Dispose()
- {
- _mainWindow.InputManager.GamepadDriver.OnGamepadConnected -= HandleOnGamepadConnected;
- _mainWindow.InputManager.GamepadDriver.OnGamepadDisconnected -= HandleOnGamepadDisconnected;
-
- _mainWindow.AppHost?.NpadManager.UnblockInputUpdates();
-
- SelectedGamepad?.Dispose();
-
- AvaloniaKeyboardDriver.Dispose();
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Ava/Ui/ViewModels/MainWindowViewModel.cs b/Ryujinx.Ava/Ui/ViewModels/MainWindowViewModel.cs
deleted file mode 100644
index 06513e37..00000000
--- a/Ryujinx.Ava/Ui/ViewModels/MainWindowViewModel.cs
+++ /dev/null
@@ -1,1539 +0,0 @@
-using ARMeilleure.Translation.PTC;
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.Input;
-using Avalonia.Media;
-using Avalonia.Threading;
-using DynamicData;
-using DynamicData.Binding;
-using LibHac.Fs;
-using LibHac.FsSystem;
-using LibHac.Ncm;
-using Ryujinx.Ava.Common;
-using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.Input;
-using Ryujinx.Ava.Ui.Controls;
-using Ryujinx.Ava.Ui.Windows;
-using Ryujinx.Common;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Logging;
-using Ryujinx.HLE;
-using Ryujinx.HLE.FileSystem;
-using Ryujinx.HLE.HOS;
-using Ryujinx.Modules;
-using Ryujinx.Ui.App.Common;
-using Ryujinx.Ui.Common;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Helper;
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Globalization;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-using Path = System.IO.Path;
-using ShaderCacheLoadingState = Ryujinx.Graphics.Gpu.Shader.ShaderCacheState;
-
-namespace Ryujinx.Ava.Ui.ViewModels
-{
- internal class MainWindowViewModel : BaseModel
- {
- private const int HotKeyPressDelayMs = 500;
-
- private readonly MainWindow _owner;
- private ObservableCollection<ApplicationData> _applications;
- private string _aspectStatusText;
-
- private string _loadHeading;
- private string _cacheLoadStatus;
- private string _searchText;
- private Timer _searchTimer;
- private string _dockedStatusText;
- private string _fifoStatusText;
- private string _gameStatusText;
- private string _volumeStatusText;
- private string _gpuStatusText;
- private bool _isAmiiboRequested;
- private bool _isGameRunning;
- private bool _isLoading;
- 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 _vsyncColor;
- private byte[] _selectedIcon;
- private bool _isAppletMenuActive;
- private int _statusBarProgressMaximum;
- private int _statusBarProgressValue;
- private bool _isPaused;
- private bool _showContent = true;
- private bool _isLoadingIndeterminate = true;
- private bool _showAll;
- private string _lastScannedAmiiboId;
- private ReadOnlyObservableCollection<ApplicationData> _appsObservableList;
- public ApplicationLibrary ApplicationLibrary => _owner.ApplicationLibrary;
-
- public string TitleName { get; internal set; }
-
- public MainWindowViewModel(MainWindow owner) : this()
- {
- _owner = owner;
- }
-
- public MainWindowViewModel()
- {
- Applications = new ObservableCollection<ApplicationData>();
-
- Applications.ToObservableChangeSet()
- .Filter(Filter)
- .Sort(GetComparer())
- .Bind(out _appsObservableList).AsObservableList();
-
- if (Program.PreviewerDetached)
- {
- LoadConfigurableHotKeys();
-
- Volume = ConfigurationState.Instance.System.AudioVolume;
- }
- }
-
- public void Initialize()
- {
- ApplicationLibrary.ApplicationCountUpdated += ApplicationLibrary_ApplicationCountUpdated;
- ApplicationLibrary.ApplicationAdded += ApplicationLibrary_ApplicationAdded;
-
- Ptc.PtcStateChanged -= ProgressHandler;
- Ptc.PtcStateChanged += ProgressHandler;
- }
-
- public string SearchText
- {
- get => _searchText;
- set
- {
- _searchText = value;
-
- _searchTimer?.Dispose();
-
- _searchTimer = new Timer(TimerCallback, null, 1000, 0);
- }
- }
-
- private void TimerCallback(object obj)
- {
- RefreshView();
-
- _searchTimer.Dispose();
- _searchTimer = null;
- }
-
- public ReadOnlyObservableCollection<ApplicationData> AppsObservableList
- {
- get => _appsObservableList;
- set
- {
- _appsObservableList = value;
-
- OnPropertyChanged();
- }
- }
-
- public bool IsPaused
- {
- get => _isPaused;
- set
- {
- _isPaused = value;
-
- OnPropertyChanged();
- }
- }
-
- public bool EnableNonGameRunningControls => !IsGameRunning;
-
- public bool ShowFirmwareStatus => !ShowLoadProgress;
-
- public bool IsGameRunning
- {
- get => _isGameRunning;
- set
- {
- _isGameRunning = value;
-
- if (!value)
- {
- ShowMenuAndStatusBar = false;
- }
-
- OnPropertyChanged();
- OnPropertyChanged(nameof(EnableNonGameRunningControls));
- OnPropertyChanged(nameof(ShowFirmwareStatus));
- }
- }
-
- public bool IsAmiiboRequested
- {
- get => _isAmiiboRequested && _isGameRunning;
- set
- {
- _isAmiiboRequested = value;
-
- OnPropertyChanged();
- }
- }
-
- public bool ShowLoadProgress
- {
- get => _showLoadProgress;
- set
- {
- _showLoadProgress = value;
-
- OnPropertyChanged();
- OnPropertyChanged(nameof(ShowFirmwareStatus));
- }
- }
-
- public string GameStatusText
- {
- get => _gameStatusText;
- set
- {
- _gameStatusText = value;
-
- OnPropertyChanged();
- }
- }
-
- private string _showUikey = "F4";
- private string _pauseKey = "F5";
- private string _screenshotkey = "F8";
- private float _volume;
- private string _backendText;
-
- public ApplicationData SelectedApplication
- {
- get
- {
- return Glyph switch
- {
- Glyph.List => _owner.GameList.SelectedApplication,
- Glyph.Grid => _owner.GameGrid.SelectedApplication,
- _ => null,
- };
- }
- }
-
- public string LoadHeading
- {
- get => _loadHeading;
- set
- {
- _loadHeading = value;
-
- OnPropertyChanged();
- }
- }
-
- 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 VsyncColor
- {
- get => _vsyncColor;
- set
- {
- _vsyncColor = value;
-
- OnPropertyChanged();
- }
- }
-
- 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 string FifoStatusText
- {
- get => _fifoStatusText;
- set
- {
- _fifoStatusText = value;
-
- OnPropertyChanged();
- }
- }
-
- public string GpuNameText
- {
- get => _gpuStatusText;
- set
- {
- _gpuStatusText = value;
-
- OnPropertyChanged();
- }
- }
-
- public string BackendText
- {
- get => _backendText;
- set
- {
- _backendText = 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();
- }
- }
-
- public bool VolumeMuted => _volume == 0;
-
- public float Volume
- {
- get => _volume;
- set
- {
- _volume = value;
-
- if (_isGameRunning)
- {
- _owner.AppHost.Device.SetVolume(_volume);
- }
-
- OnPropertyChanged(nameof(VolumeStatusText));
- OnPropertyChanged(nameof(VolumeMuted));
- 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 ShowContent
- {
- get => _showContent;
- set
- {
- _showContent = value;
-
- OnPropertyChanged();
- }
- }
-
- public bool IsAppletMenuActive
- {
- get => _isAppletMenuActive && EnableNonGameRunningControls;
- set
- {
- _isAppletMenuActive = value;
-
- OnPropertyChanged();
- }
- }
-
- public bool IsGrid => Glyph == Glyph.Grid;
- public bool IsList => Glyph == Glyph.List;
-
- internal void Sort(bool isAscending)
- {
- IsAscending = isAscending;
-
- RefreshView();
- }
-
- internal void Sort(ApplicationSort sort)
- {
- SortMode = sort;
-
- RefreshView();
- }
-
- private IComparer<ApplicationData> GetComparer()
- {
- return SortMode switch
- {
- ApplicationSort.LastPlayed => new Models.Generic.LastPlayedSortComparer(IsAscending),
- ApplicationSort.FileSize => IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => app.FileSizeBytes)
- : SortExpressionComparer<ApplicationData>.Descending(app => app.FileSizeBytes),
- ApplicationSort.TotalTimePlayed => IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => app.TimePlayedNum)
- : SortExpressionComparer<ApplicationData>.Descending(app => app.TimePlayedNum),
- ApplicationSort.Title => IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => app.TitleName)
- : SortExpressionComparer<ApplicationData>.Descending(app => app.TitleName),
- ApplicationSort.Favorite => !IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => app.Favorite)
- : SortExpressionComparer<ApplicationData>.Descending(app => app.Favorite),
- ApplicationSort.Developer => IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => app.Developer)
- : SortExpressionComparer<ApplicationData>.Descending(app => app.Developer),
- ApplicationSort.FileType => IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => app.FileExtension)
- : SortExpressionComparer<ApplicationData>.Descending(app => app.FileExtension),
- ApplicationSort.Path => IsAscending ? SortExpressionComparer<ApplicationData>.Ascending(app => app.Path)
- : SortExpressionComparer<ApplicationData>.Descending(app => app.Path),
- _ => null,
- };
- }
-
- private void RefreshView()
- {
- RefreshGrid();
- }
-
- private void RefreshGrid()
- {
- Applications.ToObservableChangeSet()
- .Filter(Filter)
- .Sort(GetComparer())
- .Bind(out _appsObservableList).AsObservableList();
-
- OnPropertyChanged(nameof(AppsObservableList));
- }
-
- public bool StartGamesInFullscreen
- {
- get => ConfigurationState.Instance.Ui.StartFullscreen;
- set
- {
- ConfigurationState.Instance.Ui.StartFullscreen.Value = value;
-
- ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
-
- OnPropertyChanged();
- }
- }
-
- public bool ShowConsole
- {
- get => ConfigurationState.Instance.Ui.ShowConsole;
- set
- {
- ConfigurationState.Instance.Ui.ShowConsole.Value = value;
-
- ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
-
- OnPropertyChanged();
- }
- }
-
- public bool ShowConsoleVisible
- {
- get => ConsoleHelper.SetConsoleWindowStateSupported;
- }
-
- public ObservableCollection<ApplicationData> Applications
- {
- get => _applications;
- set
- {
- _applications = value;
-
- OnPropertyChanged();
- }
- }
-
- public Glyph Glyph
- {
- get => (Glyph)ConfigurationState.Instance.Ui.GameListViewMode.Value;
- set
- {
- ConfigurationState.Instance.Ui.GameListViewMode.Value = (int)value;
-
- OnPropertyChanged();
- OnPropertyChanged(nameof(IsGrid));
- OnPropertyChanged(nameof(IsList));
-
- ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
- }
- }
-
- public bool ShowNames
- {
- get => ConfigurationState.Instance.Ui.ShowNames && ConfigurationState.Instance.Ui.GridSize > 1; set
- {
- ConfigurationState.Instance.Ui.ShowNames.Value = value;
-
- OnPropertyChanged();
- OnPropertyChanged(nameof(GridSizeScale));
-
- ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
- }
- }
-
- internal ApplicationSort SortMode
- {
- get => (ApplicationSort)ConfigurationState.Instance.Ui.ApplicationSort.Value;
- private set
- {
- ConfigurationState.Instance.Ui.ApplicationSort.Value = (int)value;
-
- OnPropertyChanged();
- OnPropertyChanged(nameof(SortName));
-
- ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
- }
- }
-
- public bool IsSortedByFavorite => SortMode == ApplicationSort.Favorite;
- public bool IsSortedByTitle => SortMode == ApplicationSort.Title;
- public bool IsSortedByDeveloper => SortMode == ApplicationSort.Developer;
- public bool IsSortedByLastPlayed => SortMode == ApplicationSort.LastPlayed;
- public bool IsSortedByTimePlayed => SortMode == ApplicationSort.TotalTimePlayed;
- public bool IsSortedByType => SortMode == ApplicationSort.FileType;
- public bool IsSortedBySize => SortMode == ApplicationSort.FileSize;
- public bool IsSortedByPath => SortMode == ApplicationSort.Path;
-
- public string SortName
- {
- get
- {
- return SortMode switch
- {
- ApplicationSort.Title => LocaleManager.Instance["GameListHeaderApplication"],
- ApplicationSort.Developer => LocaleManager.Instance["GameListHeaderDeveloper"],
- ApplicationSort.LastPlayed => LocaleManager.Instance["GameListHeaderLastPlayed"],
- ApplicationSort.TotalTimePlayed => LocaleManager.Instance["GameListHeaderTimePlayed"],
- ApplicationSort.FileType => LocaleManager.Instance["GameListHeaderFileExtension"],
- ApplicationSort.FileSize => LocaleManager.Instance["GameListHeaderFileSize"],
- ApplicationSort.Path => LocaleManager.Instance["GameListHeaderPath"],
- ApplicationSort.Favorite => LocaleManager.Instance["CommonFavorite"],
- _ => string.Empty,
- };
- }
- }
-
- public bool IsAscending
- {
- get => ConfigurationState.Instance.Ui.IsAscendingOrder;
- private set
- {
- ConfigurationState.Instance.Ui.IsAscendingOrder.Value = value;
-
- OnPropertyChanged();
- OnPropertyChanged(nameof(SortMode));
- OnPropertyChanged(nameof(SortName));
-
- ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
- }
- }
-
- public KeyGesture ShowUiKey
- {
- get => KeyGesture.Parse(_showUikey); set
- {
- _showUikey = value.ToString();
-
- OnPropertyChanged();
- }
- }
-
- public KeyGesture ScreenshotKey
- {
- get => KeyGesture.Parse(_screenshotkey); set
- {
- _screenshotkey = value.ToString();
-
- OnPropertyChanged();
- }
- }
-
- public KeyGesture PauseKey
- {
- get => KeyGesture.Parse(_pauseKey); set
- {
- _pauseKey = value.ToString();
-
- OnPropertyChanged();
- }
- }
-
- public bool IsGridSmall => ConfigurationState.Instance.Ui.GridSize == 1;
- public bool IsGridMedium => ConfigurationState.Instance.Ui.GridSize == 2;
- public bool IsGridLarge => ConfigurationState.Instance.Ui.GridSize == 3;
- public bool IsGridHuge => ConfigurationState.Instance.Ui.GridSize == 4;
-
- public int GridSizeScale
- {
- get => ConfigurationState.Instance.Ui.GridSize;
- set
- {
- ConfigurationState.Instance.Ui.GridSize.Value = value;
-
- if (value < 2)
- {
- ShowNames = false;
- }
-
- OnPropertyChanged();
- OnPropertyChanged(nameof(IsGridSmall));
- OnPropertyChanged(nameof(IsGridMedium));
- OnPropertyChanged(nameof(IsGridLarge));
- OnPropertyChanged(nameof(IsGridHuge));
- OnPropertyChanged(nameof(ShowNames));
-
- ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath);
- }
- }
-
- public async void OpenAmiiboWindow()
- {
- if (!_isAmiiboRequested)
- {
- return;
- }
-
- if (_owner.AppHost.Device.System.SearchingForAmiibo(out int deviceId))
- {
- string titleId = _owner.AppHost.Device.Application.TitleIdText.ToUpper();
- AmiiboWindow window = new(_showAll, _lastScannedAmiiboId, titleId);
-
- await window.ShowDialog(_owner);
-
- if (window.IsScanned)
- {
- _showAll = window.ViewModel.ShowAllAmiibo;
- _lastScannedAmiiboId = window.ScannedAmiibo.GetId();
-
- _owner.AppHost.Device.System.ScanAmiibo(deviceId, _lastScannedAmiiboId, window.ViewModel.UseRandomUuid);
- }
- }
- }
-
- public void HandleShaderProgress(Switch emulationContext)
- {
- emulationContext.Gpu.ShaderCacheStateChanged -= ProgressHandler;
- emulationContext.Gpu.ShaderCacheStateChanged += ProgressHandler;
- }
-
- private bool Filter(object arg)
- {
- if (arg is ApplicationData app)
- {
- return string.IsNullOrWhiteSpace(_searchText) || app.TitleName.ToLower().Contains(_searchText.ToLower());
- }
-
- return false;
- }
-
- private void ApplicationLibrary_ApplicationAdded(object sender, ApplicationAddedEventArgs e)
- {
- AddApplication(e.AppData);
- }
-
- private void ApplicationLibrary_ApplicationCountUpdated(object sender, ApplicationCountUpdatedEventArgs e)
- {
- StatusBarProgressValue = e.NumAppsLoaded;
- StatusBarProgressMaximum = e.NumAppsFound;
-
- LocaleManager.Instance.UpdateDynamicValue("StatusBarGamesLoaded", StatusBarProgressValue, StatusBarProgressMaximum);
-
- Dispatcher.UIThread.Post(() =>
- {
- if (e.NumAppsFound == 0)
- {
- _owner.LoadProgressBar.IsVisible = false;
- }
-
- if (e.NumAppsLoaded == e.NumAppsFound)
- {
- _owner.LoadProgressBar.IsVisible = false;
- }
- });
- }
-
- public void AddApplication(ApplicationData applicationData)
- {
- Dispatcher.UIThread.InvokeAsync(() =>
- {
- Applications.Add(applicationData);
- });
- }
-
- public async void LoadApplications()
- {
- await Dispatcher.UIThread.InvokeAsync(() =>
- {
- Applications.Clear();
-
- _owner.LoadProgressBar.IsVisible = true;
- StatusBarProgressMaximum = 0;
- StatusBarProgressValue = 0;
-
- LocaleManager.Instance.UpdateDynamicValue("StatusBarGamesLoaded", 0, 0);
- });
-
- ReloadGameList();
- }
-
- private void ReloadGameList()
- {
- if (_isLoading)
- {
- return;
- }
-
- _isLoading = true;
-
- Thread thread = new(() =>
- {
- ApplicationLibrary.LoadApplications(ConfigurationState.Instance.Ui.GameDirs.Value, ConfigurationState.Instance.System.Language);
-
- _isLoading = false;
- })
- { Name = "GUI.AppListLoadThread", Priority = ThreadPriority.AboveNormal };
-
- thread.Start();
- }
-
- public async void OpenFile()
- {
- OpenFileDialog dialog = new()
- {
- Title = LocaleManager.Instance["OpenFileDialogTitle"]
- };
-
- dialog.Filters.Add(new FileDialogFilter
- {
- Name = LocaleManager.Instance["AllSupportedFormats"],
- Extensions =
- {
- "nsp",
- "pfs0",
- "xci",
- "nca",
- "nro",
- "nso"
- }
- });
-
- dialog.Filters.Add(new FileDialogFilter { Name = "NSP", Extensions = { "nsp" } });
- dialog.Filters.Add(new FileDialogFilter { Name = "PFS0", Extensions = { "pfs0" } });
- dialog.Filters.Add(new FileDialogFilter { Name = "XCI", Extensions = { "xci" } });
- dialog.Filters.Add(new FileDialogFilter { Name = "NCA", Extensions = { "nca" } });
- dialog.Filters.Add(new FileDialogFilter { Name = "NRO", Extensions = { "nro" } });
- dialog.Filters.Add(new FileDialogFilter { Name = "NSO", Extensions = { "nso" } });
-
- string[] files = await dialog.ShowAsync(_owner);
-
- if (files != null && files.Length > 0)
- {
- _owner.LoadApplication(files[0]);
- }
- }
-
- public async void OpenFolder()
- {
- OpenFolderDialog dialog = new()
- {
- Title = LocaleManager.Instance["OpenFolderDialogTitle"]
- };
-
- string folder = await dialog.ShowAsync(_owner);
-
- if (!string.IsNullOrWhiteSpace(folder) && Directory.Exists(folder))
- {
- _owner.LoadApplication(folder);
- }
- }
-
- public void LoadConfigurableHotKeys()
- {
- if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUi, out var showUiKey))
- {
- ShowUiKey = new KeyGesture(showUiKey, KeyModifiers.None);
- }
-
- if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot, out var screenshotKey))
- {
- ScreenshotKey = new KeyGesture(screenshotKey, KeyModifiers.None);
- }
-
- if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Ryujinx.Input.Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause, out var pauseKey))
- {
- PauseKey = new KeyGesture(pauseKey, KeyModifiers.None);
- }
- }
-
- public void TakeScreenshot()
- {
- _owner.AppHost.ScreenshotRequested = true;
- }
-
- public void HideUi()
- {
- ShowMenuAndStatusBar = false;
- }
-
- public void SetListMode()
- {
- Glyph = Glyph.List;
- }
-
- public void SetGridMode()
- {
- Glyph = Glyph.Grid;
- }
-
- public void OpenMiiApplet()
- {
- string contentPath = _owner.ContentManager.GetInstalledContentPath(0x0100000000001009, StorageId.BuiltInSystem, NcaContentType.Program);
-
- if (!string.IsNullOrWhiteSpace(contentPath))
- {
- _owner.LoadApplication(contentPath, false, "Mii Applet");
- }
- }
-
- public static void OpenRyujinxFolder()
- {
- OpenHelper.OpenFolder(AppDataManager.BaseDirPath);
- }
-
- public static void OpenLogsFolder()
- {
- string logPath = Path.Combine(ReleaseInformations.GetBaseApplicationDirectory(), "Logs");
-
- new DirectoryInfo(logPath).Create();
-
- OpenHelper.OpenFolder(logPath);
- }
-
- public void ToggleFullscreen()
- {
- if (Environment.TickCount64 - _lastFullscreenToggle < HotKeyPressDelayMs)
- {
- return;
- }
-
- _lastFullscreenToggle = Environment.TickCount64;
-
- if (_owner.WindowState == WindowState.FullScreen)
- {
- _owner.WindowState = WindowState.Normal;
-
- if (IsGameRunning)
- {
- ShowMenuAndStatusBar = true;
- }
- }
- else
- {
- _owner.WindowState = WindowState.FullScreen;
-
- if (IsGameRunning)
- {
- ShowMenuAndStatusBar = false;
- }
- }
-
- OnPropertyChanged(nameof(IsFullScreen));
- }
-
- public bool IsFullScreen => _owner.WindowState == WindowState.FullScreen;
-
- public void ToggleDockMode()
- {
- if (IsGameRunning)
- {
- ConfigurationState.Instance.System.EnableDockedMode.Value = !ConfigurationState.Instance.System.EnableDockedMode.Value;
- }
- }
-
- public async void ExitCurrentState()
- {
- if (_owner.WindowState == WindowState.FullScreen)
- {
- ToggleFullscreen();
- }
- else if (IsGameRunning)
- {
- await Task.Delay(100);
-
- _owner.AppHost?.ShowExitPrompt();
- }
- }
-
- public async void OpenSettings()
- {
- _owner.SettingsWindow = new(_owner.VirtualFileSystem, _owner.ContentManager);
-
- await _owner.SettingsWindow.ShowDialog(_owner);
-
- LoadConfigurableHotKeys();
- }
-
- public async void ManageProfiles()
- {
- await NavigationDialogHost.Show(_owner.AccountManager, _owner.ContentManager, _owner.VirtualFileSystem, _owner.LibHacHorizonManager.RyujinxClient);
- }
-
- public async void OpenAboutWindow()
- {
- await new AboutWindow().ShowDialog(_owner);
- }
-
- public void ChangeLanguage(object obj)
- {
- LocaleManager.Instance.LoadDefaultLanguage();
- LocaleManager.Instance.LoadLanguage((string)obj);
- }
-
- private void ProgressHandler<T>(T state, int current, int total) where T : Enum
- {
- try
- {
- ProgressMaximum = total;
- ProgressValue = current;
-
- switch (state)
- {
- case PtcLoadingState ptcState:
- CacheLoadStatus = $"{current} / {total}";
- switch (ptcState)
- {
- case PtcLoadingState.Start:
- case PtcLoadingState.Loading:
- LoadHeading = LocaleManager.Instance["CompilingPPTC"];
- IsLoadingIndeterminate = false;
- break;
- case PtcLoadingState.Loaded:
- LoadHeading = string.Format(LocaleManager.Instance["LoadingHeading"], TitleName);
- IsLoadingIndeterminate = true;
- CacheLoadStatus = "";
- break;
- }
- break;
- case ShaderCacheLoadingState shaderCacheState:
- CacheLoadStatus = $"{current} / {total}";
- switch (shaderCacheState)
- {
- case ShaderCacheLoadingState.Start:
- case ShaderCacheLoadingState.Loading:
- LoadHeading = LocaleManager.Instance["CompilingShaders"];
- IsLoadingIndeterminate = false;
- break;
- case ShaderCacheLoadingState.Loaded:
- LoadHeading = string.Format(LocaleManager.Instance["LoadingHeading"], TitleName);
- IsLoadingIndeterminate = true;
- CacheLoadStatus = "";
- break;
- }
- break;
- default:
- throw new ArgumentException($"Unknown Progress Handler type {typeof(T)}");
- }
- }
- catch (Exception) { }
- }
-
- public void OpenUserSaveDirectory()
- {
- ApplicationData selection = SelectedApplication;
- if (selection != null)
- {
- Task.Run(() =>
- {
- if (!ulong.TryParse(selection.TitleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNumber))
- {
- Dispatcher.UIThread.Post(async () =>
- {
- await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogRyujinxErrorMessage"], LocaleManager.Instance["DialogInvalidTitleIdErrorMessage"]);
- });
-
- return;
- }
-
- UserId userId = new((ulong)_owner.AccountManager.LastOpenedUser.UserId.High, (ulong)_owner.AccountManager.LastOpenedUser.UserId.Low);
- SaveDataFilter saveDataFilter = SaveDataFilter.Make(titleIdNumber, saveType: default, userId, saveDataId: default, index: default);
- OpenSaveDirectory(in saveDataFilter, selection, titleIdNumber);
- });
- }
- }
-
- public void ToggleFavorite()
- {
- ApplicationData selection = SelectedApplication;
- if (selection != null)
- {
- selection.Favorite = !selection.Favorite;
-
- ApplicationLibrary.LoadAndSaveMetaData(selection.TitleId, appMetadata =>
- {
- appMetadata.Favorite = selection.Favorite;
- });
-
- RefreshView();
- }
- }
-
- public void OpenModsDirectory()
- {
- ApplicationData selection = SelectedApplication;
- if (selection != null)
- {
- string modsBasePath = _owner.VirtualFileSystem.ModLoader.GetModsBasePath();
- string titleModsPath = _owner.VirtualFileSystem.ModLoader.GetTitleDir(modsBasePath, selection.TitleId);
-
- OpenHelper.OpenFolder(titleModsPath);
- }
- }
-
- public void OpenSdModsDirectory()
- {
- ApplicationData selection = SelectedApplication;
-
- if (selection != null)
- {
- string sdModsBasePath = _owner.VirtualFileSystem.ModLoader.GetSdModsBasePath();
- string titleModsPath = _owner.VirtualFileSystem.ModLoader.GetTitleDir(sdModsBasePath, selection.TitleId);
-
- OpenHelper.OpenFolder(titleModsPath);
- }
- }
-
- public void OpenPtcDirectory()
- {
- ApplicationData selection = SelectedApplication;
- if (selection != null)
- {
- string ptcDir = Path.Combine(AppDataManager.GamesDirPath, selection.TitleId, "cache", "cpu");
- string mainPath = Path.Combine(ptcDir, "0");
- string backupPath = Path.Combine(ptcDir, "1");
-
- if (!Directory.Exists(ptcDir))
- {
- Directory.CreateDirectory(ptcDir);
- Directory.CreateDirectory(mainPath);
- Directory.CreateDirectory(backupPath);
- }
-
- OpenHelper.OpenFolder(ptcDir);
- }
- }
-
- public async void PurgePtcCache()
- {
- ApplicationData selection = SelectedApplication;
- if (selection != null)
- {
- DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, selection.TitleId, "cache", "cpu", "0"));
- DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, selection.TitleId, "cache", "cpu", "1"));
-
- // FIXME: Found a way to reproduce the bold effect on the title name (fork?).
- UserResult result = await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance["DialogWarning"],
- string.Format(LocaleManager.Instance["DialogPPTCDeletionMessage"], selection.TitleName),
- LocaleManager.Instance["InputDialogYes"],
- LocaleManager.Instance["InputDialogNo"],
- LocaleManager.Instance["RyujinxConfirm"]);
-
- List<FileInfo> cacheFiles = new();
-
- if (mainDir.Exists)
- {
- cacheFiles.AddRange(mainDir.EnumerateFiles("*.cache"));
- }
-
- if (backupDir.Exists)
- {
- cacheFiles.AddRange(backupDir.EnumerateFiles("*.cache"));
- }
-
- if (cacheFiles.Count > 0 && result == UserResult.Yes)
- {
- foreach (FileInfo file in cacheFiles)
- {
- try
- {
- file.Delete();
- }
- catch (Exception e)
- {
- await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["DialogPPTCDeletionErrorMessage"], file.Name, e));
- }
- }
- }
- }
- }
-
- public void OpenShaderCacheDirectory()
- {
- ApplicationData selection = SelectedApplication;
- if (selection != null)
- {
- string shaderCacheDir = Path.Combine(AppDataManager.GamesDirPath, selection.TitleId, "cache", "shader");
-
- if (!Directory.Exists(shaderCacheDir))
- {
- Directory.CreateDirectory(shaderCacheDir);
- }
-
- OpenHelper.OpenFolder(shaderCacheDir);
- }
- }
-
- public void SimulateWakeUpMessage()
- {
- _owner.AppHost.Device.System.SimulateWakeUpMessage();
- }
-
- public async void PurgeShaderCache()
- {
- ApplicationData selection = SelectedApplication;
- if (selection != null)
- {
- DirectoryInfo shaderCacheDir = new(Path.Combine(AppDataManager.GamesDirPath, selection.TitleId, "cache", "shader"));
-
- // FIXME: Found a way to reproduce the bold effect on the title name (fork?).
- UserResult result = await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance["DialogWarning"],
- string.Format(LocaleManager.Instance["DialogShaderDeletionMessage"], selection.TitleName),
- LocaleManager.Instance["InputDialogYes"],
- LocaleManager.Instance["InputDialogNo"],
- LocaleManager.Instance["RyujinxConfirm"]);
-
- List<DirectoryInfo> oldCacheDirectories = new();
- List<FileInfo> newCacheFiles = new();
-
- if (shaderCacheDir.Exists)
- {
- oldCacheDirectories.AddRange(shaderCacheDir.EnumerateDirectories("*"));
- newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.toc"));
- newCacheFiles.AddRange(shaderCacheDir.GetFiles("*.data"));
- }
-
- if ((oldCacheDirectories.Count > 0 || newCacheFiles.Count > 0) && result == UserResult.Yes)
- {
- foreach (DirectoryInfo directory in oldCacheDirectories)
- {
- try
- {
- directory.Delete(true);
- }
- catch (Exception e)
- {
- await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["DialogPPTCDeletionErrorMessage"], directory.Name, e));
- }
- }
- }
-
- foreach (FileInfo file in newCacheFiles)
- {
- try
- {
- file.Delete();
- }
- catch (Exception e)
- {
- await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["ShaderCachePurgeError"], file.Name, e));
- }
- }
- }
- }
-
- public async void CheckForUpdates()
- {
- if (Updater.CanUpdate(true, _owner))
- {
- await Updater.BeginParse(_owner, true);
- }
- }
-
- public async void OpenTitleUpdateManager()
- {
- ApplicationData selection = SelectedApplication;
- if (selection != null)
- {
- await new TitleUpdateWindow(_owner.VirtualFileSystem, ulong.Parse(selection.TitleId, NumberStyles.HexNumber), selection.TitleName).ShowDialog(_owner);
- }
- }
-
- public async void OpenDownloadableContentManager()
- {
- ApplicationData selection = SelectedApplication;
- if (selection != null)
- {
- await new DownloadableContentManagerWindow(_owner.VirtualFileSystem, ulong.Parse(selection.TitleId, NumberStyles.HexNumber), selection.TitleName).ShowDialog(_owner);
- }
- }
-
- public async void OpenCheatManager()
- {
- ApplicationData selection = SelectedApplication;
- if (selection != null)
- {
- await new CheatWindow(_owner.VirtualFileSystem, selection.TitleId, selection.TitleName).ShowDialog(_owner);
- }
- }
-
- public async void OpenCheatManagerForCurrentApp()
- {
- if (!IsGameRunning)
- {
- return;
- }
-
- ApplicationLoader application = _owner.AppHost.Device.Application;
- if (application != null)
- {
- await new CheatWindow(_owner.VirtualFileSystem, application.TitleIdText, application.TitleName).ShowDialog(_owner);
-
- _owner.AppHost.Device.EnableCheats();
- }
- }
-
- public void OpenDeviceSaveDirectory()
- {
- ApplicationData selection = SelectedApplication;
- if (selection != null)
- {
- Task.Run(() =>
- {
- if (!ulong.TryParse(selection.TitleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNumber))
- {
- Dispatcher.UIThread.Post(async () =>
- {
- await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogRyujinxErrorMessage"], LocaleManager.Instance["DialogInvalidTitleIdErrorMessage"]);
- });
-
- return;
- }
-
- var saveDataFilter = SaveDataFilter.Make(titleIdNumber, SaveDataType.Device, userId: default, saveDataId: default, index: default);
- OpenSaveDirectory(in saveDataFilter, selection, titleIdNumber);
- });
- }
- }
-
- public void OpenBcatSaveDirectory()
- {
- ApplicationData selection = SelectedApplication;
- if (selection != null)
- {
- Task.Run(() =>
- {
- if (!ulong.TryParse(selection.TitleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out ulong titleIdNumber))
- {
- Dispatcher.UIThread.Post(async () =>
- {
- await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogRyujinxErrorMessage"], LocaleManager.Instance["DialogInvalidTitleIdErrorMessage"]);
- });
-
- return;
- }
-
- var saveDataFilter = SaveDataFilter.Make(titleIdNumber, SaveDataType.Bcat, userId: default, saveDataId: default, index: default);
- OpenSaveDirectory(in saveDataFilter, selection, titleIdNumber);
- });
- }
- }
-
- private void OpenSaveDirectory(in SaveDataFilter filter, ApplicationData data, ulong titleId)
- {
- ApplicationHelper.OpenSaveDir(in filter, titleId, data.ControlHolder, data.TitleName);
- }
-
- private async void ExtractLogo()
- {
- var selection = SelectedApplication;
- if (selection != null)
- {
- await ApplicationHelper.ExtractSection(NcaSectionType.Logo, selection.Path);
- }
- }
-
- private async void ExtractRomFs()
- {
- var selection = SelectedApplication;
- if (selection != null)
- {
- await ApplicationHelper.ExtractSection(NcaSectionType.Data, selection.Path);
- }
- }
-
- private async void ExtractExeFs()
- {
- var selection = SelectedApplication;
- if (selection != null)
- {
- await ApplicationHelper.ExtractSection(NcaSectionType.Code, selection.Path);
- }
- }
-
- public void CloseWindow()
- {
- _owner.Close();
- }
-
- private async Task HandleFirmwareInstallation(string filename)
- {
- try
- {
- SystemVersion firmwareVersion = _owner.ContentManager.VerifyFirmwarePackage(filename);
-
- if (firmwareVersion == null)
- {
- await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["DialogFirmwareInstallerFirmwareNotFoundErrorMessage"], filename));
-
- return;
- }
-
- string dialogTitle = string.Format(LocaleManager.Instance["DialogFirmwareInstallerFirmwareInstallTitle"], firmwareVersion.VersionString);
-
- SystemVersion currentVersion = _owner.ContentManager.GetCurrentFirmwareVersion();
-
- string dialogMessage = string.Format(LocaleManager.Instance["DialogFirmwareInstallerFirmwareInstallMessage"], firmwareVersion.VersionString);
-
- if (currentVersion != null)
- {
- dialogMessage += string.Format(LocaleManager.Instance["DialogFirmwareInstallerFirmwareInstallSubMessage"], currentVersion.VersionString);
- }
-
- dialogMessage += LocaleManager.Instance["DialogFirmwareInstallerFirmwareInstallConfirmMessage"];
-
- UserResult result = await ContentDialogHelper.CreateConfirmationDialog(
- dialogTitle,
- dialogMessage,
- LocaleManager.Instance["InputDialogYes"],
- LocaleManager.Instance["InputDialogNo"],
- LocaleManager.Instance["RyujinxConfirm"]);
-
- UpdateWaitWindow waitingDialog = ContentDialogHelper.CreateWaitingDialog(dialogTitle, LocaleManager.Instance["DialogFirmwareInstallerFirmwareInstallWaitMessage"]);
-
- if (result == UserResult.Yes)
- {
- Logger.Info?.Print(LogClass.Application, $"Installing firmware {firmwareVersion.VersionString}");
-
- Thread thread = new(() =>
- {
- Dispatcher.UIThread.InvokeAsync(delegate
- {
- waitingDialog.Show();
- });
-
- try
- {
- _owner.ContentManager.InstallFirmware(filename);
-
- Dispatcher.UIThread.InvokeAsync(async delegate
- {
- waitingDialog.Close();
-
- string message = string.Format(LocaleManager.Instance["DialogFirmwareInstallerFirmwareInstallSuccessMessage"], firmwareVersion.VersionString);
-
- await ContentDialogHelper.CreateInfoDialog(dialogTitle, message, LocaleManager.Instance["InputDialogOk"], "", LocaleManager.Instance["RyujinxInfo"]);
-
- Logger.Info?.Print(LogClass.Application, message);
-
- // Purge Applet Cache.
-
- DirectoryInfo miiEditorCacheFolder = new DirectoryInfo(Path.Combine(AppDataManager.GamesDirPath, "0100000000001009", "cache"));
-
- if (miiEditorCacheFolder.Exists)
- {
- miiEditorCacheFolder.Delete(true);
- }
- });
- }
- catch (Exception ex)
- {
- Dispatcher.UIThread.InvokeAsync(async () =>
- {
- waitingDialog.Close();
-
- await ContentDialogHelper.CreateErrorDialog(ex.Message);
- });
- }
- finally
- {
- _owner.RefreshFirmwareStatus();
- }
- });
-
- thread.Name = "GUI.FirmwareInstallerThread";
- thread.Start();
- }
- }
- catch (LibHac.Common.Keys.MissingKeyException ex)
- {
- Logger.Error?.Print(LogClass.Application, ex.ToString());
-
- Dispatcher.UIThread.Post(async () => await UserErrorDialog.ShowUserErrorDialog(UserError.NoKeys, _owner));
- }
- catch (Exception ex)
- {
- await ContentDialogHelper.CreateErrorDialog(ex.Message);
- }
- }
-
- public async void InstallFirmwareFromFile()
- {
- OpenFileDialog dialog = new() { AllowMultiple = false };
- dialog.Filters.Add(new FileDialogFilter { Name = LocaleManager.Instance["FileDialogAllTypes"], Extensions = { "xci", "zip" } });
- dialog.Filters.Add(new FileDialogFilter { Name = "XCI", Extensions = { "xci" } });
- dialog.Filters.Add(new FileDialogFilter { Name = "ZIP", Extensions = { "zip" } });
-
- string[] file = await dialog.ShowAsync(_owner);
-
- if (file != null && file.Length > 0)
- {
- await HandleFirmwareInstallation(file[0]);
- }
- }
-
- public async void InstallFirmwareFromFolder()
- {
- OpenFolderDialog dialog = new();
-
- string folder = await dialog.ShowAsync(_owner);
-
- if (!string.IsNullOrWhiteSpace(folder))
- {
- await HandleFirmwareInstallation(folder);
- }
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Ava/Ui/ViewModels/SettingsViewModel.cs b/Ryujinx.Ava/Ui/ViewModels/SettingsViewModel.cs
deleted file mode 100644
index c752697b..00000000
--- a/Ryujinx.Ava/Ui/ViewModels/SettingsViewModel.cs
+++ /dev/null
@@ -1,520 +0,0 @@
-using Avalonia;
-using Avalonia.Collections;
-using Avalonia.Controls;
-using Avalonia.Threading;
-using DynamicData;
-using LibHac.Tools.FsSystem;
-using Ryujinx.Audio.Backends.OpenAL;
-using Ryujinx.Audio.Backends.SDL2;
-using Ryujinx.Audio.Backends.SoundIo;
-using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.Input;
-using Ryujinx.Ava.Ui.Controls;
-using Ryujinx.Ava.Ui.Windows;
-using Ryujinx.Common.Configuration;
-using Ryujinx.Common.Configuration.Hid;
-using Ryujinx.Common.GraphicsDriver;
-using Ryujinx.Common.Logging;
-using Ryujinx.Graphics.Vulkan;
-using Ryujinx.HLE.FileSystem;
-using Ryujinx.HLE.HOS.Services.Time.TimeZone;
-using Ryujinx.Input;
-using Ryujinx.Ui.Common.Configuration;
-using Ryujinx.Ui.Common.Configuration.System;
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Linq;
-using TimeZone = Ryujinx.Ava.Ui.Models.TimeZone;
-
-namespace Ryujinx.Ava.Ui.ViewModels
-{
- internal class SettingsViewModel : BaseModel
- {
- private readonly VirtualFileSystem _virtualFileSystem;
- private readonly ContentManager _contentManager;
- private readonly StyleableWindow _owner;
- private TimeZoneContentManager _timeZoneContentManager;
-
- private readonly List<string> _validTzRegions;
-
- private float _customResolutionScale;
- private int _resolutionScale;
- private int _graphicsBackendMultithreadingIndex;
- private float _previousVolumeLevel;
- private float _volume;
- private bool _isVulkanAvailable = true;
- private bool _directoryChanged = false;
- private List<string> _gpuIds = new List<string>();
- private KeyboardHotkeys _keyboardHotkeys;
- private int _graphicsBackendIndex;
-
- public int ResolutionScale
- {
- get => _resolutionScale;
- set
- {
- _resolutionScale = value;
-
- OnPropertyChanged(nameof(CustomResolutionScale));
- OnPropertyChanged(nameof(IsCustomResolutionScaleActive));
- }
- }
- public int GraphicsBackendMultithreadingIndex
- {
- get => _graphicsBackendMultithreadingIndex;
- set
- {
- _graphicsBackendMultithreadingIndex = value;
-
- if (_owner != null)
- {
- if (_graphicsBackendMultithreadingIndex != (int)ConfigurationState.Instance.Graphics.BackendThreading.Value)
- {
- Dispatcher.UIThread.Post(async () =>
- {
- await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance["DialogSettingsBackendThreadingWarningMessage"],
- "",
- "",
- LocaleManager.Instance["InputDialogOk"],
- LocaleManager.Instance["DialogSettingsBackendThreadingWarningTitle"]);
- });
- }
- }
-
- OnPropertyChanged();
- }
- }
-
- public float CustomResolutionScale
- {
- get => _customResolutionScale;
- set
- {
- _customResolutionScale = MathF.Round(value, 1);
-
- OnPropertyChanged();
- }
- }
-
- public bool IsVulkanAvailable
- {
- get => _isVulkanAvailable;
- set
- {
- _isVulkanAvailable = value;
-
- OnPropertyChanged();
- }
- }
-
- public bool IsOpenGLAvailable => !OperatingSystem.IsMacOS();
-
- public bool DirectoryChanged
- {
- get => _directoryChanged;
- set
- {
- _directoryChanged = value;
-
- OnPropertyChanged();
- }
- }
-
- public bool IsMacOS
- {
- get => OperatingSystem.IsMacOS();
- }
-
- public bool EnableDiscordIntegration { get; set; }
- public bool CheckUpdatesOnStart { get; set; }
- public bool ShowConfirmExit { get; set; }
- public bool HideCursorOnIdle { get; set; }
- public bool EnableDockedMode { get; set; }
- public bool EnableKeyboard { get; set; }
- public bool EnableMouse { get; set; }
- public bool EnableVsync { get; set; }
- public bool EnablePptc { get; set; }
- public bool EnableInternetAccess { get; set; }
- public bool EnableFsIntegrityChecks { get; set; }
- public bool IgnoreMissingServices { get; set; }
- public bool ExpandDramSize { get; set; }
- public bool EnableShaderCache { get; set; }
- public bool EnableTextureRecompression { get; set; }
- public bool EnableMacroHLE { get; set; }
- public bool EnableFileLog { get; set; }
- public bool EnableStub { get; set; }
- public bool EnableInfo { get; set; }
- public bool EnableWarn { get; set; }
- public bool EnableError { get; set; }
- public bool EnableTrace { get; set; }
- public bool EnableGuest { get; set; }
- public bool EnableFsAccessLog { get; set; }
- public bool EnableDebug { get; set; }
- public bool IsOpenAlEnabled { get; set; }
- public bool IsSoundIoEnabled { get; set; }
- public bool IsSDL2Enabled { get; set; }
- public bool EnableCustomTheme { get; set; }
- public bool IsCustomResolutionScaleActive => _resolutionScale == 0;
- public bool IsVulkanSelected => GraphicsBackendIndex == 0;
-
- public string TimeZone { get; set; }
- public string ShaderDumpPath { get; set; }
- public string CustomThemePath { get; set; }
-
- public int Language { get; set; }
- public int Region { get; set; }
- public int FsGlobalAccessLogMode { get; set; }
- public int AudioBackend { get; set; }
- public int MaxAnisotropy { get; set; }
- public int AspectRatio { get; set; }
- public int OpenglDebugLevel { get; set; }
- public int MemoryMode { get; set; }
- public int BaseStyleIndex { get; set; }
- public int GraphicsBackendIndex
- {
- get => _graphicsBackendIndex;
- set
- {
- _graphicsBackendIndex = value;
- OnPropertyChanged();
- OnPropertyChanged(nameof(IsVulkanSelected));
- }
- }
-
- public int PreferredGpuIndex { get; set; }
-
- public float Volume
- {
- get => _volume;
- set
- {
- _volume = value;
-
- ConfigurationState.Instance.System.AudioVolume.Value = (float)(_volume / 100);
-
- OnPropertyChanged();
- }
- }
-
- public DateTimeOffset DateOffset { get; set; }
- public TimeSpan TimeOffset { get; set; }
- public AvaloniaList<TimeZone> TimeZones { get; set; }
- public AvaloniaList<string> GameDirectories { get; set; }
- public ObservableCollection<ComboBoxItem> AvailableGpus { get; set; }
-
- public KeyboardHotkeys KeyboardHotkeys
- {
- get => _keyboardHotkeys;
- set
- {
- _keyboardHotkeys = value;
-
- OnPropertyChanged();
- }
- }
-
- public IGamepadDriver AvaloniaKeyboardDriver { get; }
-
- public SettingsViewModel(VirtualFileSystem virtualFileSystem, ContentManager contentManager, StyleableWindow owner) : this()
- {
- _virtualFileSystem = virtualFileSystem;
- _contentManager = contentManager;
- _owner = owner;
- if (Program.PreviewerDetached)
- {
- LoadTimeZones();
- AvaloniaKeyboardDriver = new AvaloniaKeyboardDriver(owner);
- }
- }
-
- public SettingsViewModel()
- {
- GameDirectories = new AvaloniaList<string>();
- TimeZones = new AvaloniaList<TimeZone>();
- AvailableGpus = new ObservableCollection<ComboBoxItem>();
- _validTzRegions = new List<string>();
-
- CheckSoundBackends();
-
- if (Program.PreviewerDetached)
- {
- LoadAvailableGpus();
- LoadCurrentConfiguration();
- }
- }
-
- public void CheckSoundBackends()
- {
- IsOpenAlEnabled = OpenALHardwareDeviceDriver.IsSupported;
- IsSoundIoEnabled = SoundIoHardwareDeviceDriver.IsSupported;
- IsSDL2Enabled = SDL2HardwareDeviceDriver.IsSupported;
- }
-
- private unsafe void LoadAvailableGpus()
- {
- _gpuIds = new List<string>();
- List<string> names = new List<string>();
- var devices = VulkanRenderer.GetPhysicalDevices();
-
- if (devices.Length == 0)
- {
- IsVulkanAvailable = false;
- GraphicsBackendIndex = 1;
- }
- else
- {
- foreach (var device in devices)
- {
- _gpuIds.Add(device.Id);
- names.Add($"{device.Name} {(device.IsDiscrete ? "(dGPU)" : "")}");
- }
- }
-
- AvailableGpus.Clear();
- AvailableGpus.AddRange(names.Select(x => new ComboBoxItem() { Content = x }));
- }
-
- public void LoadTimeZones()
- {
- _timeZoneContentManager = new TimeZoneContentManager();
-
- _timeZoneContentManager.InitializeInstance(_virtualFileSystem, _contentManager, IntegrityCheckLevel.None);
-
- foreach ((int offset, string location, string abbr) in _timeZoneContentManager.ParseTzOffsets())
- {
- int hours = Math.DivRem(offset, 3600, out int seconds);
- int minutes = Math.Abs(seconds) / 60;
-
- string abbr2 = abbr.StartsWith('+') || abbr.StartsWith('-') ? string.Empty : abbr;
-
- TimeZones.Add(new TimeZone($"UTC{hours:+0#;-0#;+00}:{minutes:D2}", location, abbr2));
-
- _validTzRegions.Add(location);
- }
- }
-
- public void ValidateAndSetTimeZone(string location)
- {
- if (_validTzRegions.Contains(location))
- {
- TimeZone = location;
- }
- }
-
- public async void BrowseTheme()
- {
- var dialog = new OpenFileDialog()
- {
- Title = LocaleManager.Instance["SettingsSelectThemeFileDialogTitle"],
- AllowMultiple = false
- };
-
- dialog.Filters.Add(new FileDialogFilter() { Extensions = { "xaml" }, Name = LocaleManager.Instance["SettingsXamlThemeFile"] });
-
- var file = await dialog.ShowAsync(_owner);
-
- if (file != null && file.Length > 0)
- {
- CustomThemePath = file[0];
- OnPropertyChanged(nameof(CustomThemePath));
- }
- }
-
- public void LoadCurrentConfiguration()
- {
- ConfigurationState config = ConfigurationState.Instance;
-
- GameDirectories.Clear();
- GameDirectories.AddRange(config.Ui.GameDirs.Value);
-
- EnableDiscordIntegration = config.EnableDiscordIntegration;
- CheckUpdatesOnStart = config.CheckUpdatesOnStart;
- ShowConfirmExit = config.ShowConfirmExit;
- HideCursorOnIdle = config.HideCursorOnIdle;
- EnableDockedMode = config.System.EnableDockedMode;
- EnableKeyboard = config.Hid.EnableKeyboard;
- EnableMouse = config.Hid.EnableMouse;
- EnableVsync = config.Graphics.EnableVsync;
- EnablePptc = config.System.EnablePtc;
- EnableInternetAccess = config.System.EnableInternetAccess;
- EnableFsIntegrityChecks = config.System.EnableFsIntegrityChecks;
- IgnoreMissingServices = config.System.IgnoreMissingServices;
- ExpandDramSize = config.System.ExpandRam;
- EnableShaderCache = config.Graphics.EnableShaderCache;
- EnableTextureRecompression = config.Graphics.EnableTextureRecompression;
- EnableMacroHLE = config.Graphics.EnableMacroHLE;
- EnableFileLog = config.Logger.EnableFileLog;
- EnableStub = config.Logger.EnableStub;
- EnableInfo = config.Logger.EnableInfo;
- EnableWarn = config.Logger.EnableWarn;
- EnableError = config.Logger.EnableError;
- EnableTrace = config.Logger.EnableTrace;
- EnableGuest = config.Logger.EnableGuest;
- EnableDebug = config.Logger.EnableDebug;
- EnableFsAccessLog = config.Logger.EnableFsAccessLog;
- EnableCustomTheme = config.Ui.EnableCustomTheme;
- Volume = config.System.AudioVolume * 100;
-
- GraphicsBackendMultithreadingIndex = (int)config.Graphics.BackendThreading.Value;
-
- OpenglDebugLevel = (int)config.Logger.GraphicsDebugLevel.Value;
-
- TimeZone = config.System.TimeZone;
- ShaderDumpPath = config.Graphics.ShadersDumpPath;
- CustomThemePath = config.Ui.CustomThemePath;
- BaseStyleIndex = config.Ui.BaseStyle == "Light" ? 0 : 1;
- GraphicsBackendIndex = (int)config.Graphics.GraphicsBackend.Value;
-
- PreferredGpuIndex = _gpuIds.Contains(config.Graphics.PreferredGpu) ? _gpuIds.IndexOf(config.Graphics.PreferredGpu) : 0;
-
- Language = (int)config.System.Language.Value;
- Region = (int)config.System.Region.Value;
- FsGlobalAccessLogMode = config.System.FsGlobalAccessLogMode;
- AudioBackend = (int)config.System.AudioBackend.Value;
- MemoryMode = (int)config.System.MemoryManagerMode.Value;
-
- float anisotropy = config.Graphics.MaxAnisotropy;
-
- MaxAnisotropy = anisotropy == -1 ? 0 : (int)(MathF.Log2(anisotropy));
- AspectRatio = (int)config.Graphics.AspectRatio.Value;
-
- int resolution = config.Graphics.ResScale;
-
- ResolutionScale = resolution == -1 ? 0 : resolution;
- CustomResolutionScale = config.Graphics.ResScaleCustom;
-
- DateTime dateTimeOffset = DateTime.Now.AddSeconds(config.System.SystemTimeOffset);
-
- DateOffset = dateTimeOffset.Date;
- TimeOffset = dateTimeOffset.TimeOfDay;
-
- KeyboardHotkeys = config.Hid.Hotkeys.Value;
-
- _previousVolumeLevel = Volume;
- }
-
- public void SaveSettings()
- {
- ConfigurationState config = ConfigurationState.Instance;
-
- if (_directoryChanged)
- {
- List<string> gameDirs = new List<string>(GameDirectories);
- config.Ui.GameDirs.Value = gameDirs;
- }
-
- if (_validTzRegions.Contains(TimeZone))
- {
- config.System.TimeZone.Value = TimeZone;
- }
-
- config.Logger.EnableError.Value = EnableError;
- config.Logger.EnableTrace.Value = EnableTrace;
- config.Logger.EnableWarn.Value = EnableWarn;
- config.Logger.EnableInfo.Value = EnableInfo;
- config.Logger.EnableStub.Value = EnableStub;
- config.Logger.EnableDebug.Value = EnableDebug;
- config.Logger.EnableGuest.Value = EnableGuest;
- config.Logger.EnableFsAccessLog.Value = EnableFsAccessLog;
- config.Logger.EnableFileLog.Value = EnableFileLog;
- config.Logger.GraphicsDebugLevel.Value = (GraphicsDebugLevel)OpenglDebugLevel;
- config.System.EnableDockedMode.Value = EnableDockedMode;
- config.EnableDiscordIntegration.Value = EnableDiscordIntegration;
- config.CheckUpdatesOnStart.Value = CheckUpdatesOnStart;
- config.ShowConfirmExit.Value = ShowConfirmExit;
- config.HideCursorOnIdle.Value = HideCursorOnIdle;
- config.Graphics.EnableVsync.Value = EnableVsync;
- config.Graphics.EnableShaderCache.Value = EnableShaderCache;
- config.Graphics.EnableTextureRecompression.Value = EnableTextureRecompression;
- config.Graphics.EnableMacroHLE.Value = EnableMacroHLE;
- config.Graphics.GraphicsBackend.Value = (GraphicsBackend)GraphicsBackendIndex;
- config.System.EnablePtc.Value = EnablePptc;
- config.System.EnableInternetAccess.Value = EnableInternetAccess;
- config.System.EnableFsIntegrityChecks.Value = EnableFsIntegrityChecks;
- config.System.IgnoreMissingServices.Value = IgnoreMissingServices;
- config.System.ExpandRam.Value = ExpandDramSize;
- config.Hid.EnableKeyboard.Value = EnableKeyboard;
- config.Hid.EnableMouse.Value = EnableMouse;
- config.Ui.CustomThemePath.Value = CustomThemePath;
- config.Ui.EnableCustomTheme.Value = EnableCustomTheme;
- config.Ui.BaseStyle.Value = BaseStyleIndex == 0 ? "Light" : "Dark";
- config.System.Language.Value = (Language)Language;
- config.System.Region.Value = (Region)Region;
-
- config.Graphics.PreferredGpu.Value = _gpuIds.ElementAtOrDefault(PreferredGpuIndex);
-
- if (ConfigurationState.Instance.Graphics.BackendThreading != (BackendThreading)GraphicsBackendMultithreadingIndex)
- {
- DriverUtilities.ToggleOGLThreading(GraphicsBackendMultithreadingIndex == (int)BackendThreading.Off);
- }
-
- config.Graphics.BackendThreading.Value = (BackendThreading)GraphicsBackendMultithreadingIndex;
-
- TimeSpan systemTimeOffset = DateOffset - DateTime.Now;
-
- config.System.SystemTimeOffset.Value = systemTimeOffset.Seconds;
- config.Graphics.ShadersDumpPath.Value = ShaderDumpPath;
- config.System.FsGlobalAccessLogMode.Value = FsGlobalAccessLogMode;
- config.System.MemoryManagerMode.Value = (MemoryManagerMode)MemoryMode;
-
- float anisotropy = MaxAnisotropy == 0 ? -1 : MathF.Pow(2, MaxAnisotropy);
-
- config.Graphics.MaxAnisotropy.Value = anisotropy;
- config.Graphics.AspectRatio.Value = (AspectRatio)AspectRatio;
- config.Graphics.ResScale.Value = ResolutionScale == 0 ? -1 : ResolutionScale;
- config.Graphics.ResScaleCustom.Value = CustomResolutionScale;
- config.System.AudioVolume.Value = Volume / 100;
-
- AudioBackend audioBackend = (AudioBackend)AudioBackend;
- if (audioBackend != config.System.AudioBackend.Value)
- {
- config.System.AudioBackend.Value = audioBackend;
-
- Logger.Info?.Print(LogClass.Application, $"AudioBackend toggled to: {audioBackend}");
- }
-
- config.Hid.Hotkeys.Value = KeyboardHotkeys;
-
- config.ToFileFormat().SaveConfig(Program.ConfigurationPath);
-
- MainWindow.UpdateGraphicsConfig();
-
- _previousVolumeLevel = Volume;
-
- if (_owner is SettingsWindow owner)
- {
- owner.ControllerSettings?.SaveCurrentProfile();
- }
-
- if (_owner.Owner is MainWindow window && _directoryChanged)
- {
- window.ViewModel.LoadApplications();
- }
-
- _directoryChanged = false;
- }
-
- public void RevertIfNotSaved()
- {
- Program.ReloadConfig();
- }
-
- public void ApplyButton()
- {
- SaveSettings();
- }
-
- public void OkButton()
- {
- SaveSettings();
- _owner.Close();
- }
-
- public void CancelButton()
- {
- RevertIfNotSaved();
- _owner.Close();
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Ava/Ui/ViewModels/UserProfileViewModel.cs b/Ryujinx.Ava/Ui/ViewModels/UserProfileViewModel.cs
deleted file mode 100644
index eb9f69d6..00000000
--- a/Ryujinx.Ava/Ui/ViewModels/UserProfileViewModel.cs
+++ /dev/null
@@ -1,213 +0,0 @@
-using Avalonia;
-using Avalonia.Threading;
-using FluentAvalonia.UI.Controls;
-using LibHac.Common;
-using LibHac.Fs;
-using LibHac.Fs.Shim;
-using Ryujinx.Ava.Common.Locale;
-using Ryujinx.Ava.Ui.Controls;
-using Ryujinx.HLE.HOS.Services.Account.Acc;
-using System;
-using System.Collections.Generic;
-using System.Collections.ObjectModel;
-using System.Linq;
-using UserProfile = Ryujinx.Ava.Ui.Models.UserProfile;
-
-namespace Ryujinx.Ava.Ui.ViewModels
-{
- public class UserProfileViewModel : BaseModel, IDisposable
- {
- private readonly NavigationDialogHost _owner;
-
- private UserProfile _selectedProfile;
- private UserProfile _highlightedProfile;
-
- public UserProfileViewModel()
- {
- Profiles = new ObservableCollection<UserProfile>();
- LostProfiles = new ObservableCollection<UserProfile>();
- }
-
- public UserProfileViewModel(NavigationDialogHost owner) : this()
- {
- _owner = owner;
-
- LoadProfiles();
- }
-
- public ObservableCollection<UserProfile> Profiles { get; set; }
-
- public ObservableCollection<UserProfile> LostProfiles { get; set; }
-
- public UserProfile SelectedProfile
- {
- get => _selectedProfile;
- set
- {
- _selectedProfile = value;
-
- OnPropertyChanged(nameof(SelectedProfile));
- OnPropertyChanged(nameof(IsHighlightedProfileDeletable));
- OnPropertyChanged(nameof(IsHighlightedProfileEditable));
- }
- }
-
- public bool IsHighlightedProfileEditable => _highlightedProfile != null;
-
- public bool IsHighlightedProfileDeletable => _highlightedProfile != null && _highlightedProfile.UserId != AccountManager.DefaultUserId;
-
- public UserProfile HighlightedProfile
- {
- get => _highlightedProfile;
- set
- {
- _highlightedProfile = value;
-
- OnPropertyChanged(nameof(HighlightedProfile));
- OnPropertyChanged(nameof(IsHighlightedProfileDeletable));
- OnPropertyChanged(nameof(IsHighlightedProfileEditable));
- }
- }
-
- public void Dispose() { }
-
- public void LoadProfiles()
- {
- Profiles.Clear();
- LostProfiles.Clear();
-
- var profiles = _owner.AccountManager.GetAllUsers().OrderByDescending(x => x.AccountState == AccountState.Open);
-
- foreach (var profile in profiles)
- {
- Profiles.Add(new UserProfile(profile, _owner));
- }
-
- SelectedProfile = Profiles.FirstOrDefault(x => x.UserId == _owner.AccountManager.LastOpenedUser.UserId);
-
- if (SelectedProfile == null)
- {
- SelectedProfile = Profiles.First();
-
- if (SelectedProfile != null)
- {
- _owner.AccountManager.OpenUser(_selectedProfile.UserId);
- }
- }
-
- var saveDataFilter = SaveDataFilter.Make(programId: default, saveType: SaveDataType.Account,
- default, saveDataId: default, index: default);
-
- using var saveDataIterator = new UniqueRef<SaveDataIterator>();
-
- _owner.HorizonClient.Fs.OpenSaveDataIterator(ref saveDataIterator.Ref(), SaveDataSpaceId.User, in saveDataFilter).ThrowIfFailure();
-
- Span<SaveDataInfo> saveDataInfo = stackalloc SaveDataInfo[10];
-
- HashSet<HLE.HOS.Services.Account.Acc.UserId> lostAccounts = new HashSet<HLE.HOS.Services.Account.Acc.UserId>();
-
- while (true)
- {
- saveDataIterator.Get.ReadSaveDataInfo(out long readCount, saveDataInfo).ThrowIfFailure();
-
- if (readCount == 0)
- {
- break;
- }
-
- for (int i = 0; i < readCount; i++)
- {
- var save = saveDataInfo[i];
- var id = new HLE.HOS.Services.Account.Acc.UserId((long)save.UserId.Id.Low, (long)save.UserId.Id.High);
- if (Profiles.FirstOrDefault( x=> x.UserId == id) == null)
- {
- lostAccounts.Add(id);
- }
- }
- }
-
- foreach(var account in lostAccounts)
- {
- LostProfiles.Add(new UserProfile(new HLE.HOS.Services.Account.Acc.UserProfile(account, "", null), _owner));
- }
- }
-
- public void AddUser()
- {
- UserProfile userProfile = null;
-
- _owner.Navigate(typeof(UserEditor), (this._owner, userProfile, true));
- }
-
- public async void ManageSaves()
- {
- UserProfile userProfile = _highlightedProfile ?? SelectedProfile;
-
- SaveManager manager = new SaveManager(userProfile, _owner.HorizonClient, _owner.VirtualFileSystem);
-
- ContentDialog contentDialog = new ContentDialog
- {
- Title = string.Format(LocaleManager.Instance["SaveManagerHeading"], userProfile.Name),
- PrimaryButtonText = "",
- SecondaryButtonText = "",
- CloseButtonText = LocaleManager.Instance["UserProfilesClose"],
- Content = manager,
- Padding = new Thickness(0)
- };
-
- await contentDialog.ShowAsync();
- }
-
- public void EditUser()
- {
- _owner.Navigate(typeof(UserEditor), (this._owner, _highlightedProfile ?? SelectedProfile, false));
- }
-
- public async void DeleteUser()
- {
- if (_highlightedProfile != null)
- {
- var lastUserId = _owner.AccountManager.LastOpenedUser.UserId;
-
- if (_highlightedProfile.UserId == lastUserId)
- {
- // If we are deleting the currently open profile, then we must open something else before deleting.
- var profile = Profiles.FirstOrDefault(x => x.UserId != lastUserId);
-
- if (profile == null)
- {
- Dispatcher.UIThread.Post(async () =>
- {
- await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogUserProfileDeletionWarningMessage"]);
- });
-
- return;
- }
-
- _owner.AccountManager.OpenUser(profile.UserId);
- }
-
- var result =
- await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance["DialogUserProfileDeletionConfirmMessage"], "",
- LocaleManager.Instance["InputDialogYes"], LocaleManager.Instance["InputDialogNo"], "");
-
- if (result == UserResult.Yes)
- {
- _owner.AccountManager.DeleteUser(_highlightedProfile.UserId);
- }
- }
-
- LoadProfiles();
- }
-
- public void GoBack()
- {
- _owner.GoBack();
- }
-
- public void RecoverLostAccounts()
- {
- _owner.Navigate(typeof(UserRecoverer), (this._owner, this));
- }
- }
-} \ No newline at end of file