using Avalonia.Controls; using Avalonia.Interactivity; using Avalonia.Threading; using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Navigation; using LibHac; using LibHac.Common; using LibHac.Fs; using LibHac.Fs.Shim; using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Models; using Ryujinx.Ava.UI.ViewModels; using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.Services.Account.Acc; using System; using System.Collections.ObjectModel; using System.Threading.Tasks; using UserId = LibHac.Fs.UserId; namespace Ryujinx.Ava.UI.Views.User { public partial class UserSaveManager : UserControl { internal UserSaveManagerViewModel ViewModel { get; private set; } private AccountManager _accountManager; private HorizonClient _horizonClient; private VirtualFileSystem _virtualFileSystem; private NavigationDialogHost _parent; public UserSaveManager() { InitializeComponent(); AddHandler(Frame.NavigatedToEvent, (s, e) => { NavigatedTo(e); }, RoutingStrategies.Direct); } private void NavigatedTo(NavigationEventArgs arg) { if (Program.PreviewerDetached) { switch (arg.NavigationMode) { case NavigationMode.New: var args = ((NavigationDialogHost parent, AccountManager accountManager, HorizonClient client, VirtualFileSystem virtualFileSystem))arg.Parameter; _accountManager = args.accountManager; _horizonClient = args.client; _virtualFileSystem = args.virtualFileSystem; _parent = args.parent; break; } DataContext = ViewModel = new UserSaveManagerViewModel(); Task.Run(LoadSaves); } } public void LoadSaves() { ViewModel.Saves.Clear(); var saves = new ObservableCollection(); var saveDataFilter = SaveDataFilter.Make(programId: default, saveType: SaveDataType.Account, new UserId((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low), saveDataId: default, index: default); using var saveDataIterator = new UniqueRef(); _horizonClient.Fs.OpenSaveDataIterator(ref saveDataIterator.Ref(), SaveDataSpaceId.User, in saveDataFilter).ThrowIfFailure(); Span saveDataInfo = stackalloc SaveDataInfo[10]; 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]; if (save.ProgramId.Value != 0) { var saveModel = new SaveModel(save, _horizonClient, _virtualFileSystem); saves.Add(saveModel); saveModel.DeleteAction = () => { ViewModel.Saves.Remove(saveModel); }; } } } Dispatcher.UIThread.Post(() => { ViewModel.Saves = saves; ViewModel.Sort(); }); } private void GoBack(object sender, RoutedEventArgs e) { _parent?.GoBack(); } private void OpenLocation(object sender, RoutedEventArgs e) { if (sender is Avalonia.Controls.Button button) { (button.DataContext as SaveModel).OpenLocation(); } } private void Delete(object sender, RoutedEventArgs e) { if (sender is Avalonia.Controls.Button button) { (button.DataContext as SaveModel).Delete(); } } } }