d9053bbe37
* Add save manager to account selector * add fallback to app metadata for titlename if app is not in gamelist * Allow recovering lost accounts
160 lines
4.7 KiB
C#
160 lines
4.7 KiB
C#
using Avalonia.Controls;
|
|
using DynamicData;
|
|
using DynamicData.Binding;
|
|
using LibHac;
|
|
using LibHac.Common;
|
|
using LibHac.Fs;
|
|
using LibHac.Fs.Shim;
|
|
using Ryujinx.Ava.Common;
|
|
using Ryujinx.Ava.Common.Locale;
|
|
using Ryujinx.Ava.Ui.Models;
|
|
using Ryujinx.HLE.FileSystem;
|
|
using Ryujinx.Ui.App.Common;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Threading.Tasks;
|
|
using UserProfile = Ryujinx.Ava.Ui.Models.UserProfile;
|
|
|
|
namespace Ryujinx.Ava.Ui.Controls
|
|
{
|
|
public partial class SaveManager : UserControl
|
|
{
|
|
private readonly UserProfile _userProfile;
|
|
private readonly HorizonClient _horizonClient;
|
|
private readonly VirtualFileSystem _virtualFileSystem;
|
|
private int _sortIndex;
|
|
private int _orderIndex;
|
|
private ObservableCollection<SaveModel> _view = new ObservableCollection<SaveModel>();
|
|
private string _search;
|
|
|
|
public ObservableCollection<SaveModel> Saves { get; set; } = new ObservableCollection<SaveModel>();
|
|
|
|
public ObservableCollection<SaveModel> View
|
|
{
|
|
get => _view;
|
|
set => _view = value;
|
|
}
|
|
|
|
public int SortIndex
|
|
{
|
|
get => _sortIndex;
|
|
set
|
|
{
|
|
_sortIndex = value;
|
|
Sort();
|
|
}
|
|
}
|
|
|
|
public int OrderIndex
|
|
{
|
|
get => _orderIndex;
|
|
set
|
|
{
|
|
_orderIndex = value;
|
|
Sort();
|
|
}
|
|
}
|
|
|
|
public string Search
|
|
{
|
|
get => _search;
|
|
set
|
|
{
|
|
_search = value;
|
|
Sort();
|
|
}
|
|
}
|
|
|
|
public SaveManager()
|
|
{
|
|
InitializeComponent();
|
|
}
|
|
|
|
public SaveManager(UserProfile userProfile, HorizonClient horizonClient, VirtualFileSystem virtualFileSystem)
|
|
{
|
|
_userProfile = userProfile;
|
|
_horizonClient = horizonClient;
|
|
_virtualFileSystem = virtualFileSystem;
|
|
InitializeComponent();
|
|
|
|
DataContext = this;
|
|
|
|
Task.Run(LoadSaves);
|
|
}
|
|
|
|
public void LoadSaves()
|
|
{
|
|
Saves.Clear();
|
|
var saveDataFilter = SaveDataFilter.Make(programId: default, saveType: SaveDataType.Account,
|
|
new UserId((ulong)_userProfile.UserId.High, (ulong)_userProfile.UserId.Low), saveDataId: default, index: default);
|
|
|
|
using var saveDataIterator = new UniqueRef<SaveDataIterator>();
|
|
|
|
_horizonClient.Fs.OpenSaveDataIterator(ref saveDataIterator.Ref(), SaveDataSpaceId.User, in saveDataFilter).ThrowIfFailure();
|
|
|
|
Span<SaveDataInfo> 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 = () => { Saves.Remove(saveModel); };
|
|
}
|
|
|
|
Sort();
|
|
}
|
|
}
|
|
}
|
|
|
|
private void Sort()
|
|
{
|
|
Saves.AsObservableChangeSet()
|
|
.Filter(Filter)
|
|
.Sort(GetComparer())
|
|
.Bind(out var view).AsObservableList();
|
|
|
|
_view.Clear();
|
|
_view.AddRange(view);
|
|
}
|
|
|
|
private IComparer<SaveModel> GetComparer()
|
|
{
|
|
switch (SortIndex)
|
|
{
|
|
case 0:
|
|
return OrderIndex == 0
|
|
? SortExpressionComparer<SaveModel>.Ascending(save => save.Title)
|
|
: SortExpressionComparer<SaveModel>.Descending(save => save.Title);
|
|
case 1:
|
|
return OrderIndex == 0
|
|
? SortExpressionComparer<SaveModel>.Ascending(save => save.Size)
|
|
: SortExpressionComparer<SaveModel>.Descending(save => save.Size);
|
|
default:
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private bool Filter(object arg)
|
|
{
|
|
if (arg is SaveModel save)
|
|
{
|
|
return string.IsNullOrWhiteSpace(_search) || save.Title.ToLower().Contains(_search.ToLower());
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|
|
} |