mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-01-12 13:49:12 +00:00
Cleanup + Fix warnings
This commit is contained in:
parent
79f94020df
commit
c8b39e0c98
6 changed files with 89 additions and 281 deletions
|
@ -1,10 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.Common.SaveManager
|
||||
{
|
||||
public readonly record struct BackupRequestOutcome
|
||||
{
|
||||
public bool DidFail { get; init; }
|
||||
public string Message { get; init; }
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
|
||||
using LibHac.Fs;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ui.Common.Helper;
|
||||
using Ryujinx.Ui.Common.SaveManager;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.Ava.Common.SaveManager
|
||||
{
|
||||
public interface ISaveManager
|
||||
{
|
||||
public event EventHandler<LoadingBarEventArgs> BackupProgressUpdated;
|
||||
public event EventHandler<ImportSaveEventArgs> BackupImportSave;
|
||||
|
||||
#region Backup
|
||||
public Task<BackupRequestOutcome> BackupUserSaveDataToZip(UserId userId,
|
||||
string location,
|
||||
SaveOptions saveOptions = SaveOptions.Default);
|
||||
|
||||
public Task<BackupRequestOutcome> BackupUserTitleSaveDataToZip(UserId userId,
|
||||
ulong titleId,
|
||||
string location,
|
||||
SaveOptions saveOptions = SaveOptions.Default);
|
||||
#endregion
|
||||
|
||||
#region Restore
|
||||
public Task<BackupRequestOutcome> RestoreUserSaveDataFromZip(UserId userId,
|
||||
string sourceDataPath);
|
||||
|
||||
public Task<BackupRequestOutcome> RestoreUserTitleSaveFromZip(UserId userId,
|
||||
ulong titleId,
|
||||
string sourceDataPath);
|
||||
#endregion
|
||||
}
|
||||
}
|
|
@ -5,11 +5,9 @@ using LibHac.Fs;
|
|||
using LibHac.Fs.Shim;
|
||||
using LibHac.Ns;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Ryujinx.Ava.UI.ViewModels;
|
||||
using Ryujinx.Ava.UI.Windows;
|
||||
using Ryujinx.Common.Configuration;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.HLE.HOS.Services.Account.Acc;
|
||||
using Ryujinx.Ui.Common.Helper;
|
||||
using Ryujinx.Ui.Common.SaveManager;
|
||||
using System;
|
||||
|
@ -23,52 +21,32 @@ using Path = System.IO.Path;
|
|||
|
||||
namespace Ryujinx.Ava.Common.SaveManager
|
||||
{
|
||||
public class SaveManager : ISaveManager
|
||||
public class SaveManager
|
||||
{
|
||||
// UI Metadata
|
||||
public event EventHandler<LoadingBarEventArgs> BackupProgressUpdated;
|
||||
public event EventHandler<ImportSaveEventArgs> BackupImportSave;
|
||||
private readonly LoadingBarEventArgs _loadingEventArgs;
|
||||
private readonly LoadingBarEventArgs _loadingEventArgs = new();
|
||||
|
||||
private readonly HorizonClient _horizonClient;
|
||||
private readonly AccountManager _accountManager;
|
||||
|
||||
public SaveManager(HorizonClient hzClient, AccountManager acctManager)
|
||||
public SaveManager(HorizonClient hzClient)
|
||||
{
|
||||
_loadingEventArgs = new();
|
||||
|
||||
_horizonClient = hzClient;
|
||||
_accountManager = acctManager;
|
||||
}
|
||||
|
||||
#region Backup
|
||||
public Task<BackupRequestOutcome> BackupUserTitleSaveDataToZip(LibHacUserId userId,
|
||||
ulong titleId,
|
||||
string location,
|
||||
SaveOptions saveOptions = SaveOptions.Default)
|
||||
public async Task<bool> BackupUserSaveDataToZip(LibHacUserId userId, Uri savePath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<BackupRequestOutcome> BackupUserSaveDataToZip(LibHacUserId userId,
|
||||
string location,
|
||||
SaveOptions saveOptions = SaveOptions.Default)
|
||||
{
|
||||
// TODO: Eventually add cancellation source
|
||||
|
||||
var userSaves = GetUserSaveData(userId, saveOptions);
|
||||
if (userSaves.IsNullOrEmpty())
|
||||
var userSaves = GetUserSaveData(userId).ToArray();
|
||||
if (userSaves.Length == 0)
|
||||
{
|
||||
Logger.Warning?.Print(LogClass.Application, "No save data found");
|
||||
return new BackupRequestOutcome
|
||||
{
|
||||
DidFail = false,
|
||||
Message = "No save data found"
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
_loadingEventArgs.Curr = 0;
|
||||
_loadingEventArgs.Max = userSaves.Count() + 1; // add one for metadata file
|
||||
_loadingEventArgs.Max = userSaves.Length + 1; // Add one for metadata file
|
||||
BackupProgressUpdated?.Invoke(this, _loadingEventArgs);
|
||||
|
||||
// Create the top level temp dir for the intermediate copies - ensure it's empty
|
||||
|
@ -80,25 +58,13 @@ namespace Ryujinx.Ava.Common.SaveManager
|
|||
// Delete temp for good measure?
|
||||
_ = Directory.CreateDirectory(backupTempDir);
|
||||
|
||||
var outcome = await BatchCopySavesToTempDir(userId, userSaves, backupTempDir)
|
||||
&& CompleteBackup(location, userId, backupTempDir);
|
||||
|
||||
return new BackupRequestOutcome
|
||||
{
|
||||
DidFail = !outcome,
|
||||
Message = outcome
|
||||
? string.Empty
|
||||
: "Failed to backup user saves"
|
||||
};
|
||||
return await BatchCopySavesToTempDir(userSaves, backupTempDir)
|
||||
&& CreateOrReplaceZipFile(backupTempDir, savePath.LocalPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to backup user data - {ex.Message}");
|
||||
return new BackupRequestOutcome
|
||||
{
|
||||
DidFail = true,
|
||||
Message = $"Failed to backup user data - {ex.Message}"
|
||||
};
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
@ -107,36 +73,20 @@ namespace Ryujinx.Ava.Common.SaveManager
|
|||
Directory.Delete(backupTempDir, true);
|
||||
}
|
||||
}
|
||||
|
||||
// Produce the actual zip
|
||||
bool CompleteBackup(string location, LibHacUserId userId, string backupTempDir)
|
||||
{
|
||||
var currDate = DateTime.UtcNow.ToString("yyyy-MM-dd");
|
||||
var profileName = _accountManager
|
||||
.GetAllUsers()
|
||||
.FirstOrDefault(u => u.UserId.ToLibHacUserId() == userId)?.Name;
|
||||
|
||||
var backupFile = Path.Combine(location, $"{profileName}_{currDate}_saves.zip");
|
||||
return CreateOrReplaceZipFile(backupTempDir, backupFile);
|
||||
}
|
||||
}
|
||||
|
||||
private IEnumerable<BackupSaveMeta> GetUserSaveData(LibHacUserId userId, SaveOptions saveOptions)
|
||||
private IEnumerable<BackupSaveMeta> GetUserSaveData(LibHacUserId userId)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Almost all games have user savess
|
||||
// Almost all games have user saves
|
||||
var userSaves = GetSaveData(userId, SaveDataType.Account)
|
||||
.ToList();
|
||||
|
||||
var deviceSaves = saveOptions.HasFlag(SaveOptions.SaveTypeDevice)
|
||||
? GetSaveData(default, SaveDataType.Device)
|
||||
: Enumerable.Empty<BackupSaveMeta>();
|
||||
var deviceSaves = GetSaveData(default, SaveDataType.Device);
|
||||
userSaves.AddRange(deviceSaves);
|
||||
|
||||
var bcatSaves = saveOptions.HasFlag(SaveOptions.SaveTypeDevice)
|
||||
? GetSaveData(default, SaveDataType.Bcat)
|
||||
: Enumerable.Empty<BackupSaveMeta>();
|
||||
var bcatSaves = GetSaveData(default, SaveDataType.Bcat);
|
||||
userSaves.AddRange(bcatSaves);
|
||||
|
||||
return userSaves;
|
||||
|
@ -195,14 +145,11 @@ namespace Ryujinx.Ava.Common.SaveManager
|
|||
return saves;
|
||||
}
|
||||
|
||||
private async Task<bool> BatchCopySavesToTempDir(LibHacUserId userId, IEnumerable<BackupSaveMeta> userSaves, string backupTempDir)
|
||||
private async Task<bool> BatchCopySavesToTempDir(IEnumerable<BackupSaveMeta> userSaves, string backupTempDir)
|
||||
{
|
||||
// Generate a metadata item so users know what titleIds ares in case they're moving around, jksv, sanity, etc
|
||||
Dictionary<ulong, UserFriendlyAppData> userFriendlyMetadataMap = new();
|
||||
|
||||
try
|
||||
{
|
||||
// batch intermediate copies so we don't overwhelm systems
|
||||
// Batch intermediate copies so we don't overwhelm systems
|
||||
const int BATCH_SIZE = 5;
|
||||
List<Task<bool>> tempCopyTasks = new(BATCH_SIZE);
|
||||
|
||||
|
@ -219,29 +166,11 @@ namespace Ryujinx.Ava.Common.SaveManager
|
|||
|
||||
// Add backup task
|
||||
tempCopyTasks.Add(CopySaveDataToIntermediateDirectory(meta, backupTempDir));
|
||||
|
||||
// Add title metadata entry - might be dupe from bcat/device
|
||||
if (!userFriendlyMetadataMap.ContainsKey(meta.TitleId.Value))
|
||||
{
|
||||
var titleIdHex = meta.TitleId.Value.ToString("x16");
|
||||
|
||||
var appData = MainWindow.MainWindowViewModel.Applications
|
||||
.FirstOrDefault(x => x.TitleId.Equals(titleIdHex, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
userFriendlyMetadataMap.Add(meta.TitleId.Value, new UserFriendlyAppData
|
||||
{
|
||||
Title = appData?.TitleName,
|
||||
TitleId = meta.TitleId.Value,
|
||||
TitleIdHex = titleIdHex
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// wait for any outstanding temp copies to complete
|
||||
_ = await Task.WhenAll(tempCopyTasks);
|
||||
|
||||
// finally, move the metadata tag file into the backup dir and track progress
|
||||
await WriteMetadataFile(backupTempDir, userId, userFriendlyMetadataMap);
|
||||
_loadingEventArgs.Curr++;
|
||||
BackupProgressUpdated?.Invoke(this, _loadingEventArgs);
|
||||
|
||||
|
@ -253,34 +182,6 @@ namespace Ryujinx.Ava.Common.SaveManager
|
|||
}
|
||||
|
||||
return false;
|
||||
|
||||
#region LocalMethods
|
||||
async Task WriteMetadataFile(string backupTempDir,
|
||||
LibHacUserId userId,
|
||||
Dictionary<ulong, UserFriendlyAppData> userFriendlyMetadataMap)
|
||||
{
|
||||
try
|
||||
{
|
||||
var userProfile = _accountManager.GetAllUsers()
|
||||
.FirstOrDefault(u => u.UserId.ToLibHacUserId() == userId);
|
||||
|
||||
var tagFile = Path.Combine(backupTempDir, "tag.json");
|
||||
|
||||
var completeMeta = System.Text.Json.JsonSerializer.Serialize(new UserFriendlySaveMetadata
|
||||
{
|
||||
UserId = userId.ToString(),
|
||||
ProfileName = userProfile.Name,
|
||||
CreationTimeUtc = DateTime.UtcNow,
|
||||
ApplicationMap = userFriendlyMetadataMap.Values
|
||||
});
|
||||
await File.WriteAllTextAsync(tagFile, completeMeta);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to write user friendly save metadata file - {ex.Message}");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
private async Task<bool> CopySaveDataToIntermediateDirectory(BackupSaveMeta saveMeta, string destinationDir)
|
||||
|
@ -322,14 +223,7 @@ namespace Ryujinx.Ava.Common.SaveManager
|
|||
#endregion
|
||||
|
||||
#region Restore
|
||||
public Task<BackupRequestOutcome> RestoreUserTitleSaveFromZip(LibHacUserId userId,
|
||||
ulong titleId,
|
||||
string sourceDataPath)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<BackupRequestOutcome> RestoreUserSaveDataFromZip(LibHacUserId userId,
|
||||
public async Task<bool> RestoreUserSaveDataFromZip(LibHacUserId userId,
|
||||
string sourceDataPath)
|
||||
{
|
||||
var sourceInfo = new FileInfo(sourceDataPath);
|
||||
|
@ -352,11 +246,7 @@ namespace Ryujinx.Ava.Common.SaveManager
|
|||
var error = $"Failed to extract save backup zip {ex.Message}";
|
||||
Logger.Error?.Print(LogClass.Application, error);
|
||||
|
||||
return new()
|
||||
{
|
||||
DidFail = true,
|
||||
Message = error
|
||||
};
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -370,10 +260,7 @@ namespace Ryujinx.Ava.Common.SaveManager
|
|||
var identifiedTitleDirectories = GetTitleDirectories(sourceInfo);
|
||||
if (identifiedTitleDirectories.IsNullOrEmpty())
|
||||
{
|
||||
return new()
|
||||
{
|
||||
DidFail = true,
|
||||
};
|
||||
return false;
|
||||
}
|
||||
|
||||
// Start import
|
||||
|
@ -403,18 +290,12 @@ namespace Ryujinx.Ava.Common.SaveManager
|
|||
// let the import complete
|
||||
_ = await Task.WhenAll(importBuffer);
|
||||
|
||||
return new BackupRequestOutcome
|
||||
{
|
||||
DidFail = false
|
||||
};
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Error?.Print(LogClass.Application, $"Failed to import save data - {ex.Message}");
|
||||
return new BackupRequestOutcome
|
||||
{
|
||||
DidFail = false
|
||||
};
|
||||
return false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace Ryujinx.Ava.Common.SaveManager
|
||||
{
|
||||
[Flags]
|
||||
public enum SaveOptions
|
||||
{
|
||||
// Save Data Types
|
||||
SaveTypeAccount,
|
||||
SaveTypeBcat,
|
||||
SaveTypeDevice,
|
||||
SaveTypeAll = SaveTypeAccount | SaveTypeBcat | SaveTypeDevice,
|
||||
|
||||
// Request Semantics -- Not Implemented
|
||||
SkipEmptyDirectories,
|
||||
FlattenSaveStructure,
|
||||
StopOnFirstFailure,
|
||||
UseDateInName,
|
||||
ObfuscateZipExtension,
|
||||
|
||||
Default = SaveTypeAll
|
||||
}
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Ryujinx.Ava.Common.SaveManager
|
||||
{
|
||||
internal readonly record struct UserFriendlyAppData
|
||||
{
|
||||
public ulong TitleId { get; init; }
|
||||
public string Title { get; init; }
|
||||
public string TitleIdHex { get; init; }
|
||||
}
|
||||
|
||||
internal readonly record struct UserFriendlySaveMetadata
|
||||
{
|
||||
public string UserId { get; init; }
|
||||
public string ProfileName { get; init; }
|
||||
public DateTime CreationTimeUtc { get; init; }
|
||||
public IEnumerable<UserFriendlyAppData> ApplicationMap { get; init; }
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Notifications;
|
||||
using Avalonia.Interactivity;
|
||||
using Avalonia.Platform.Storage;
|
||||
using Avalonia.Threading;
|
||||
using Avalonia.VisualTree;
|
||||
using DynamicData;
|
||||
|
@ -22,6 +23,7 @@ using Ryujinx.HLE.HOS.Services.Account.Acc;
|
|||
using Ryujinx.Ui.Common.Helper;
|
||||
using Ryujinx.Ui.Common.SaveManager;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -36,9 +38,8 @@ namespace Ryujinx.Ava.UI.Views.User
|
|||
|
||||
private AccountManager _accountManager;
|
||||
private HorizonClient _horizonClient;
|
||||
private VirtualFileSystem _virtualFileSystem;
|
||||
private NavigationDialogHost _parent;
|
||||
private ISaveManager _saveManager;
|
||||
private SaveManager _saveManager;
|
||||
|
||||
public UserSaveManagerView()
|
||||
{
|
||||
|
@ -59,10 +60,10 @@ namespace Ryujinx.Ava.UI.Views.User
|
|||
switch (arg.NavigationMode)
|
||||
{
|
||||
case NavigationMode.New:
|
||||
(_parent, _accountManager, _horizonClient, _virtualFileSystem) =
|
||||
(_parent, _accountManager, _horizonClient, _) =
|
||||
((NavigationDialogHost parent, AccountManager accountManager, HorizonClient client, VirtualFileSystem virtualFileSystem))arg.Parameter;
|
||||
|
||||
_saveManager = new SaveManager(_horizonClient, _accountManager);
|
||||
_saveManager = new SaveManager(_horizonClient);
|
||||
_saveManager.BackupProgressUpdated += BackupManager_ProgressUpdate;
|
||||
_saveManager.BackupImportSave += BackupManager_ImportSave;
|
||||
|
||||
|
@ -79,11 +80,11 @@ namespace Ryujinx.Ava.UI.Views.User
|
|||
ViewModel.Saves.Clear();
|
||||
var saves = new ObservableCollection<SaveModel>();
|
||||
var saveDataFilter = SaveDataFilter.Make(
|
||||
programId: default,
|
||||
saveType: SaveDataType.Account,
|
||||
default,
|
||||
SaveDataType.Account,
|
||||
new UserId((ulong)_accountManager.LastOpenedUser.UserId.High, (ulong)_accountManager.LastOpenedUser.UserId.Low),
|
||||
saveDataId: default,
|
||||
index: default);
|
||||
default,
|
||||
default);
|
||||
|
||||
using var saveDataIterator = new UniqueRef<SaveDataIterator>();
|
||||
|
||||
|
@ -143,7 +144,8 @@ namespace Ryujinx.Ava.UI.Views.User
|
|||
{
|
||||
if (button.DataContext is SaveModel saveModel)
|
||||
{
|
||||
var result = await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance[LocaleKeys.DeleteUserSave],
|
||||
var result = await ContentDialogHelper.CreateConfirmationDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DeleteUserSave],
|
||||
LocaleManager.Instance[LocaleKeys.IrreversibleActionNote],
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogYes],
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogNo], "");
|
||||
|
@ -160,16 +162,26 @@ namespace Ryujinx.Ava.UI.Views.User
|
|||
|
||||
private async void GenerateProfileSaveBackup(object sender, RoutedEventArgs e)
|
||||
{
|
||||
OpenFolderDialog dialog = new()
|
||||
{
|
||||
Title = LocaleManager.Instance[LocaleKeys.SaveManagerChooseBackupFolderTitle]
|
||||
};
|
||||
var window = ((TopLevel)_parent.GetVisualRoot()) as Window;
|
||||
var currDate = DateTime.UtcNow.ToString("yyyy-MM-dd");
|
||||
var profileName = _accountManager.LastOpenedUser.Name;
|
||||
var fileName = $"{profileName}_{currDate}_saves";
|
||||
|
||||
var backupDir = await dialog.ShowAsync(((TopLevel)_parent.GetVisualRoot()) as Window);
|
||||
if (string.IsNullOrWhiteSpace(backupDir))
|
||||
var file = await window.StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions
|
||||
{
|
||||
return;
|
||||
Title = LocaleManager.Instance[LocaleKeys.SaveManagerChooseBackupFolderTitle],
|
||||
DefaultExtension = "zip",
|
||||
SuggestedFileName = fileName,
|
||||
FileTypeChoices = new List<FilePickerFileType>
|
||||
{
|
||||
new("zip")
|
||||
{
|
||||
Patterns = new[] { "*.zip" },
|
||||
AppleUniformTypeIdentifiers = new[] { "public.zip-archive" },
|
||||
MimeTypes = new[] { "application/zip" }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Disable the user from doing anything until we complete
|
||||
ViewModel.IsGoBackEnabled = false;
|
||||
|
@ -178,23 +190,21 @@ namespace Ryujinx.Ava.UI.Views.User
|
|||
{
|
||||
// Could potentially seed with existing saves already enumerated but we still need bcat and device data
|
||||
var result = await _saveManager.BackupUserSaveDataToZip(
|
||||
userId: _accountManager.LastOpenedUser.UserId.ToLibHacUserId(),
|
||||
location: backupDir,
|
||||
saveOptions: SaveOptions.Default);
|
||||
_accountManager.LastOpenedUser.UserId.ToLibHacUserId(),
|
||||
file.Path);
|
||||
|
||||
var notificationType = result.DidFail
|
||||
? NotificationType.Error
|
||||
: NotificationType.Success;
|
||||
var notificationType = result
|
||||
? NotificationType.Success
|
||||
: NotificationType.Error;
|
||||
|
||||
var message = result.DidFail
|
||||
? LocaleManager.Instance[LocaleKeys.SaveManagerBackupFailed]
|
||||
: LocaleManager.Instance[LocaleKeys.SaveManagerBackupComplete];
|
||||
var message = result
|
||||
? LocaleManager.Instance[LocaleKeys.SaveManagerBackupComplete]
|
||||
: LocaleManager.Instance[LocaleKeys.SaveManagerBackupFailed];
|
||||
|
||||
NotificationHelper.Show(LocaleManager.Instance[LocaleKeys.NotificationBackupTitle],
|
||||
NotificationHelper.Show(
|
||||
LocaleManager.Instance[LocaleKeys.NotificationBackupTitle],
|
||||
message,
|
||||
notificationType);
|
||||
|
||||
return;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
@ -209,37 +219,42 @@ namespace Ryujinx.Ava.UI.Views.User
|
|||
|
||||
private async void ImportSaveBackup(object sender, RoutedEventArgs e)
|
||||
{
|
||||
bool userConfirmation = await ContentDialogHelper.CreateChoiceDialog(LocaleManager.Instance[LocaleKeys.SaveManagerConfirmRestoreTitle],
|
||||
bool userConfirmation = await ContentDialogHelper.CreateChoiceDialog(
|
||||
LocaleManager.Instance[LocaleKeys.SaveManagerConfirmRestoreTitle],
|
||||
LocaleManager.Instance[LocaleKeys.SaveManagerChooseRestoreZipPrimaryMessage],
|
||||
LocaleManager.Instance[LocaleKeys.SaveManagerChooseRestoreZipSecondaryMessage],
|
||||
primaryButtonKey: LocaleKeys.SaveMangerRestoreUserConfirm,
|
||||
closeButtonKey: LocaleKeys.SaveMangerRestoreUserCancel);
|
||||
LocaleKeys.SaveMangerRestoreUserConfirm,
|
||||
LocaleKeys.SaveMangerRestoreUserCancel);
|
||||
|
||||
if (!userConfirmation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
OpenFileDialog dialog = new()
|
||||
var window = ((TopLevel)_parent.GetVisualRoot()) as Window;
|
||||
|
||||
var fileResult = await window.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
|
||||
{
|
||||
Title = LocaleManager.Instance[LocaleKeys.SaveManagerChooseRestoreZipTitle],
|
||||
AllowMultiple = false,
|
||||
Filters = {
|
||||
new FileDialogFilter() {
|
||||
Name = "Zip files",
|
||||
Extensions = { "zip" },
|
||||
FileTypeFilter = new List<FilePickerFileType>
|
||||
{
|
||||
new("zip")
|
||||
{
|
||||
Patterns = new[] { "*.zip" },
|
||||
AppleUniformTypeIdentifiers = new[] { "public.zip-archive" },
|
||||
MimeTypes = new[] { "application/zip" }
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
var saveBackupZip = await dialog.ShowAsync(((TopLevel)_parent.GetVisualRoot()) as Window);
|
||||
if (saveBackupZip is null
|
||||
|| saveBackupZip.Length == 0
|
||||
|| string.IsNullOrWhiteSpace(saveBackupZip[0]))
|
||||
if (fileResult.Count <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var saveBackupZip = fileResult[0].Path.LocalPath;
|
||||
|
||||
// Disable the user from doing anything until we complete
|
||||
ViewModel.IsGoBackEnabled = false;
|
||||
|
||||
|
@ -247,16 +262,16 @@ namespace Ryujinx.Ava.UI.Views.User
|
|||
{
|
||||
// Could potentially seed with existing saves already enumerated but we still need bcat and device data
|
||||
var result = await _saveManager.RestoreUserSaveDataFromZip(
|
||||
userId: _accountManager.LastOpenedUser.UserId.ToLibHacUserId(),
|
||||
sourceDataPath: saveBackupZip[0]);
|
||||
_accountManager.LastOpenedUser.UserId.ToLibHacUserId(),
|
||||
saveBackupZip);
|
||||
|
||||
var notificationType = result.DidFail
|
||||
? NotificationType.Error
|
||||
: NotificationType.Success;
|
||||
var notificationType = result
|
||||
? NotificationType.Success
|
||||
: NotificationType.Error;
|
||||
|
||||
var message = result.DidFail
|
||||
? LocaleManager.Instance[LocaleKeys.SaveManagerRestoreFailed]
|
||||
: LocaleManager.Instance[LocaleKeys.SaveManagerRestoreComplete];
|
||||
var message = result
|
||||
? LocaleManager.Instance[LocaleKeys.SaveManagerRestoreComplete]
|
||||
: LocaleManager.Instance[LocaleKeys.SaveManagerRestoreFailed];
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(ViewModel.Search))
|
||||
{
|
||||
|
@ -266,7 +281,8 @@ namespace Ryujinx.Ava.UI.Views.User
|
|||
});
|
||||
}
|
||||
|
||||
NotificationHelper.Show(LocaleManager.Instance[LocaleKeys.NotificationBackupTitle],
|
||||
NotificationHelper.Show(
|
||||
LocaleManager.Instance[LocaleKeys.NotificationBackupTitle],
|
||||
message,
|
||||
notificationType);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue