Merge branch 'master' into xeyes
This commit is contained in:
@@ -172,7 +172,7 @@ namespace Ryujinx.Ava.UI.Applet
|
||||
try
|
||||
{
|
||||
_parent.ViewModel.AppHost.NpadManager.BlockInputUpdates();
|
||||
SoftwareKeyboardUIArgs args = new SoftwareKeyboardUIArgs();
|
||||
SoftwareKeyboardUIArgs args = new();
|
||||
args.KeyboardMode = KeyboardMode.Default;
|
||||
args.InitialText = "Ryujinx";
|
||||
args.StringLengthMin = 1;
|
||||
@@ -264,7 +264,7 @@ namespace Ryujinx.Ava.UI.Applet
|
||||
{
|
||||
UserId selected = UserId.Null;
|
||||
byte[] defaultGuestImage = EmbeddedResources.Read("Ryujinx.HLE/HOS/Services/Account/Acc/GuestUserImage.jpg");
|
||||
UserProfile guest = new UserProfile(new UserId("00000000000000000000000000000080"), "Guest", defaultGuestImage);
|
||||
UserProfile guest = new(new UserId("00000000000000000000000000000080"), "Guest", defaultGuestImage);
|
||||
|
||||
ManualResetEvent dialogCloseEvent = new(false);
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Ryujinx.Ava.UI.Applet
|
||||
{
|
||||
if (item is UserProfile originalItem)
|
||||
{
|
||||
UserProfileSft profile = new UserProfileSft(originalItem.UserId, originalItem.Name, originalItem.Image);
|
||||
UserProfileSft profile = new(originalItem.UserId, originalItem.Name, originalItem.Image);
|
||||
|
||||
if (profile.UserId == ViewModel.SelectedUserId)
|
||||
{
|
||||
|
||||
@@ -146,7 +146,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
DirectoryInfo mainDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "0"));
|
||||
DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "cpu", "1"));
|
||||
|
||||
List<FileInfo> cacheFiles = new();
|
||||
List<FileInfo> cacheFiles = [];
|
||||
|
||||
if (mainDir.Exists)
|
||||
{
|
||||
@@ -189,8 +189,8 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
{
|
||||
DirectoryInfo shaderCacheDir = new(Path.Combine(AppDataManager.GamesDirPath, viewModel.SelectedApplication.IdString, "cache", "shader"));
|
||||
|
||||
List<DirectoryInfo> oldCacheDirectories = new();
|
||||
List<FileInfo> newCacheFiles = new();
|
||||
List<DirectoryInfo> oldCacheDirectories = [];
|
||||
List<FileInfo> newCacheFiles = [];
|
||||
|
||||
if (shaderCacheDir.Exists)
|
||||
{
|
||||
|
||||
@@ -108,13 +108,13 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
|
||||
SaveDataFilter saveDataFilter = SaveDataFilter.Make(programId: default, saveType: SaveDataType.Account, default, saveDataId: default, index: default);
|
||||
|
||||
using UniqueRef<SaveDataIterator> saveDataIterator = new UniqueRef<SaveDataIterator>();
|
||||
using UniqueRef<SaveDataIterator> saveDataIterator = new();
|
||||
|
||||
HorizonClient.Fs.OpenSaveDataIterator(ref saveDataIterator.Ref, SaveDataSpaceId.User, in saveDataFilter).ThrowIfFailure();
|
||||
|
||||
Span<SaveDataInfo> saveDataInfo = stackalloc SaveDataInfo[10];
|
||||
|
||||
HashSet<UserId> lostAccounts = new();
|
||||
HashSet<UserId> lostAccounts = [];
|
||||
|
||||
while (true)
|
||||
{
|
||||
@@ -128,7 +128,7 @@ namespace Ryujinx.Ava.UI.Controls
|
||||
for (int i = 0; i < readCount; i++)
|
||||
{
|
||||
SaveDataInfo save = saveDataInfo[i];
|
||||
UserId id = new UserId((long)save.UserId.Id.Low, (long)save.UserId.Id.High);
|
||||
UserId id = new((long)save.UserId.Id.Low, (long)save.UserId.Id.High);
|
||||
if (ViewModel.Profiles.Cast<UserProfile>().FirstOrDefault(x => x.UserId == id) == null)
|
||||
{
|
||||
lostAccounts.Add(id);
|
||||
|
||||
@@ -50,8 +50,8 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
|
||||
private static string Format(AvaLogLevel level, string area, string template, object source, object[] v)
|
||||
{
|
||||
StringBuilder result = new StringBuilder();
|
||||
CharacterReader r = new CharacterReader(template.AsSpan());
|
||||
StringBuilder result = new();
|
||||
CharacterReader r = new(template.AsSpan());
|
||||
int i = 0;
|
||||
|
||||
result.Append('[');
|
||||
|
||||
@@ -28,7 +28,7 @@ namespace Ryujinx.Ava.UI.Helpers
|
||||
Margin = new Thickness(0, 0, 15, 40),
|
||||
};
|
||||
|
||||
Lazy<AsyncWorkQueue<Notification>> maybeAsyncWorkQueue = new Lazy<AsyncWorkQueue<Notification>>(
|
||||
Lazy<AsyncWorkQueue<Notification>> maybeAsyncWorkQueue = new(
|
||||
() => new AsyncWorkQueue<Notification>(notification =>
|
||||
{
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Ryujinx.Ava.UI.Models
|
||||
public class CheatNode : BaseModel
|
||||
{
|
||||
private bool _isEnabled = false;
|
||||
public ObservableCollection<CheatNode> SubNodes { get; } = new();
|
||||
public ObservableCollection<CheatNode> SubNodes { get; } = [];
|
||||
public string CleanName => Name[1..^7];
|
||||
public string BuildIdKey => $"{BuildId}-{Name}";
|
||||
public bool IsRootNode { get; }
|
||||
|
||||
@@ -367,7 +367,7 @@ namespace Ryujinx.Ava.UI.Models.Input
|
||||
|
||||
public InputConfig GetConfig()
|
||||
{
|
||||
StandardKeyboardInputConfig config = new StandardKeyboardInputConfig
|
||||
StandardKeyboardInputConfig config = new()
|
||||
{
|
||||
Id = Id,
|
||||
Backend = InputBackendType.WindowKeyboard,
|
||||
|
||||
@@ -64,9 +64,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
Directory.CreateDirectory(Path.Join(AppDataManager.BaseDirPath, "system", "amiibo"));
|
||||
|
||||
_amiiboJsonPath = Path.Join(AppDataManager.BaseDirPath, "system", "amiibo", "Amiibo.json");
|
||||
_amiiboList = new List<AmiiboApi>();
|
||||
_amiiboSeries = new ObservableCollection<string>();
|
||||
_amiibos = new AvaloniaList<AmiiboApi>();
|
||||
_amiiboList = [];
|
||||
_amiiboSeries = [];
|
||||
_amiibos = [];
|
||||
|
||||
_amiiboLogoBytes = EmbeddedResources.Read("Ryujinx/Assets/UIImages/Logo_Amiibo.png");
|
||||
|
||||
|
||||
@@ -22,9 +22,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
public partial class DownloadableContentManagerViewModel : BaseModel
|
||||
{
|
||||
private readonly ApplicationLibrary _applicationLibrary;
|
||||
private AvaloniaList<DownloadableContentModel> _downloadableContents = new();
|
||||
[ObservableProperty] private AvaloniaList<DownloadableContentModel> _selectedDownloadableContents = new();
|
||||
[ObservableProperty] private AvaloniaList<DownloadableContentModel> _views = new();
|
||||
private AvaloniaList<DownloadableContentModel> _downloadableContents = [];
|
||||
[ObservableProperty] private AvaloniaList<DownloadableContentModel> _selectedDownloadableContents = [];
|
||||
[ObservableProperty] private AvaloniaList<DownloadableContentModel> _views = [];
|
||||
[ObservableProperty] private bool _showBundledContentNotice = false;
|
||||
|
||||
private string _search;
|
||||
@@ -139,9 +139,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
new("NSP")
|
||||
{
|
||||
Patterns = new[] { "*.nsp" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" },
|
||||
MimeTypes = new[] { "application/x-nx-nsp" },
|
||||
Patterns = ["*.nsp"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.nsp"],
|
||||
MimeTypes = ["application/x-nx-nsp"],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -6,6 +6,7 @@ using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.Input;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.Views.Input;
|
||||
using Ryujinx.UI.Views.Input;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
@@ -84,15 +85,10 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
await RumbleInputView.Show(this);
|
||||
}
|
||||
|
||||
public RelayCommand LedDisabledChanged => Commands.Create(() =>
|
||||
public async void ShowLedConfig()
|
||||
{
|
||||
if (!Config.EnableLedChanging) return;
|
||||
|
||||
if (Config.TurnOffLed)
|
||||
ParentModel.SelectedGamepad.ClearLed();
|
||||
else
|
||||
ParentModel.SelectedGamepad.SetLed(Config.LedColor.ToUInt32());
|
||||
});
|
||||
await LedInputView.Show(this);
|
||||
}
|
||||
|
||||
public void OnParentModelChanged()
|
||||
{
|
||||
|
||||
@@ -271,11 +271,11 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
|
||||
public InputViewModel()
|
||||
{
|
||||
PlayerIndexes = new ObservableCollection<PlayerModel>();
|
||||
Controllers = new ObservableCollection<ControllerModel>();
|
||||
Devices = new ObservableCollection<(DeviceType Type, string Id, string Name)>();
|
||||
ProfilesList = new AvaloniaList<string>();
|
||||
DeviceList = new AvaloniaList<string>();
|
||||
PlayerIndexes = [];
|
||||
Controllers = [];
|
||||
Devices = [];
|
||||
ProfilesList = [];
|
||||
DeviceList = [];
|
||||
VisualStick = new StickVisualizer(this);
|
||||
|
||||
ControllerImage = ProControllerResource;
|
||||
@@ -825,7 +825,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
IsModified = false;
|
||||
|
||||
List<InputConfig> newConfig = new();
|
||||
List<InputConfig> newConfig = [];
|
||||
|
||||
newConfig.AddRange(ConfigurationState.Instance.Hid.InputConfig.Value);
|
||||
|
||||
|
||||
53
src/Ryujinx/UI/ViewModels/Input/LedInputViewModel.cs
Normal file
53
src/Ryujinx/UI/ViewModels/Input/LedInputViewModel.cs
Normal file
@@ -0,0 +1,53 @@
|
||||
using Avalonia.Media;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using CommunityToolkit.Mvvm.Input;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
|
||||
namespace Ryujinx.Ava.UI.ViewModels.Input
|
||||
{
|
||||
public partial class LedInputViewModel : BaseModel
|
||||
{
|
||||
public required InputViewModel ParentModel { get; init; }
|
||||
|
||||
public RelayCommand LedDisabledChanged => Commands.Create(() =>
|
||||
{
|
||||
if (!EnableLedChanging) return;
|
||||
|
||||
if (TurnOffLed)
|
||||
ParentModel.SelectedGamepad.ClearLed();
|
||||
else
|
||||
ParentModel.SelectedGamepad.SetLed(LedColor.ToUInt32());
|
||||
});
|
||||
|
||||
[ObservableProperty] private bool _enableLedChanging;
|
||||
[ObservableProperty] private Color _ledColor;
|
||||
|
||||
public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed;
|
||||
|
||||
private bool _turnOffLed;
|
||||
|
||||
public bool TurnOffLed
|
||||
{
|
||||
get => _turnOffLed;
|
||||
set
|
||||
{
|
||||
_turnOffLed = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(ShowLedColorPicker));
|
||||
}
|
||||
}
|
||||
|
||||
private bool _useRainbowLed;
|
||||
|
||||
public bool UseRainbowLed
|
||||
{
|
||||
get => _useRainbowLed;
|
||||
set
|
||||
{
|
||||
_useRainbowLed = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(ShowLedColorPicker));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1245,21 +1245,21 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
new(LocaleManager.Instance[LocaleKeys.FileDialogAllTypes])
|
||||
{
|
||||
Patterns = new[] { "*.xci", "*.zip" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci", "public.zip-archive" },
|
||||
MimeTypes = new[] { "application/x-nx-xci", "application/zip" },
|
||||
Patterns = ["*.xci", "*.zip"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.xci", "public.zip-archive"],
|
||||
MimeTypes = ["application/x-nx-xci", "application/zip"],
|
||||
},
|
||||
new("XCI")
|
||||
{
|
||||
Patterns = new[] { "*.xci" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" },
|
||||
MimeTypes = new[] { "application/x-nx-xci" },
|
||||
Patterns = ["*.xci"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.xci"],
|
||||
MimeTypes = ["application/x-nx-xci"],
|
||||
},
|
||||
new("ZIP")
|
||||
{
|
||||
Patterns = new[] { "*.zip" },
|
||||
AppleUniformTypeIdentifiers = new[] { "public.zip-archive" },
|
||||
MimeTypes = new[] { "application/zip" },
|
||||
Patterns = ["*.zip"],
|
||||
AppleUniformTypeIdentifiers = ["public.zip-archive"],
|
||||
MimeTypes = ["application/zip"],
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1292,21 +1292,21 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
new(LocaleManager.Instance[LocaleKeys.FileDialogAllTypes])
|
||||
{
|
||||
Patterns = new[] { "*.keys", "*.zip" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci", "public.zip-archive" },
|
||||
MimeTypes = new[] { "application/keys", "application/zip" },
|
||||
Patterns = ["*.keys", "*.zip"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.xci", "public.zip-archive"],
|
||||
MimeTypes = ["application/keys", "application/zip"],
|
||||
},
|
||||
new("KEYS")
|
||||
{
|
||||
Patterns = new[] { "*.keys" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" },
|
||||
MimeTypes = new[] { "application/keys" },
|
||||
Patterns = ["*.keys"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.xci"],
|
||||
MimeTypes = ["application/keys"],
|
||||
},
|
||||
new("ZIP")
|
||||
{
|
||||
Patterns = new[] { "*.zip" },
|
||||
AppleUniformTypeIdentifiers = new[] { "public.zip-archive" },
|
||||
MimeTypes = new[] { "application/zip" },
|
||||
Patterns = ["*.zip"],
|
||||
AppleUniformTypeIdentifiers = ["public.zip-archive"],
|
||||
MimeTypes = ["application/zip"],
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1418,53 +1418,53 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats])
|
||||
{
|
||||
Patterns = new[] { "*.nsp", "*.xci", "*.nca", "*.nro", "*.nso" },
|
||||
AppleUniformTypeIdentifiers = new[]
|
||||
{
|
||||
Patterns = ["*.nsp", "*.xci", "*.nca", "*.nro", "*.nso"],
|
||||
AppleUniformTypeIdentifiers =
|
||||
[
|
||||
"com.ryujinx.nsp",
|
||||
"com.ryujinx.xci",
|
||||
"com.ryujinx.nca",
|
||||
"com.ryujinx.nro",
|
||||
"com.ryujinx.nso",
|
||||
},
|
||||
MimeTypes = new[]
|
||||
{
|
||||
"com.ryujinx.nso"
|
||||
],
|
||||
MimeTypes =
|
||||
[
|
||||
"application/x-nx-nsp",
|
||||
"application/x-nx-xci",
|
||||
"application/x-nx-nca",
|
||||
"application/x-nx-nro",
|
||||
"application/x-nx-nso",
|
||||
},
|
||||
"application/x-nx-nso"
|
||||
],
|
||||
},
|
||||
new("NSP")
|
||||
{
|
||||
Patterns = new[] { "*.nsp" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" },
|
||||
MimeTypes = new[] { "application/x-nx-nsp" },
|
||||
Patterns = ["*.nsp"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.nsp"],
|
||||
MimeTypes = ["application/x-nx-nsp"],
|
||||
},
|
||||
new("XCI")
|
||||
{
|
||||
Patterns = new[] { "*.xci" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.xci" },
|
||||
MimeTypes = new[] { "application/x-nx-xci" },
|
||||
Patterns = ["*.xci"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.xci"],
|
||||
MimeTypes = ["application/x-nx-xci"],
|
||||
},
|
||||
new("NCA")
|
||||
{
|
||||
Patterns = new[] { "*.nca" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nca" },
|
||||
MimeTypes = new[] { "application/x-nx-nca" },
|
||||
Patterns = ["*.nca"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.nca"],
|
||||
MimeTypes = ["application/x-nx-nca"],
|
||||
},
|
||||
new("NRO")
|
||||
{
|
||||
Patterns = new[] { "*.nro" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nro" },
|
||||
MimeTypes = new[] { "application/x-nx-nro" },
|
||||
Patterns = ["*.nro"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.nro"],
|
||||
MimeTypes = ["application/x-nx-nro"],
|
||||
},
|
||||
new("NSO")
|
||||
{
|
||||
Patterns = new[] { "*.nso" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nso" },
|
||||
MimeTypes = new[] { "application/x-nx-nso" },
|
||||
Patterns = ["*.nso"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.nso"],
|
||||
MimeTypes = ["application/x-nx-nso"],
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1690,7 +1690,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats])
|
||||
{
|
||||
Patterns = new[] { "*.bin" },
|
||||
Patterns = ["*.bin"],
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1802,7 +1802,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
return;
|
||||
}
|
||||
|
||||
XCIFileTrimmer trimmer = new XCIFileTrimmer(filename, new XCITrimmerLog.MainWindow(this));
|
||||
XCIFileTrimmer trimmer = new(filename, new XCITrimmerLog.MainWindow(this));
|
||||
|
||||
if (trimmer.CanBeTrimmed)
|
||||
{
|
||||
|
||||
@@ -23,9 +23,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
private readonly string _modJsonPath;
|
||||
|
||||
private AvaloniaList<ModModel> _mods = new();
|
||||
[ObservableProperty] private AvaloniaList<ModModel> _views = new();
|
||||
[ObservableProperty] private AvaloniaList<ModModel> _selectedMods = new();
|
||||
private AvaloniaList<ModModel> _mods = [];
|
||||
[ObservableProperty] private AvaloniaList<ModModel> _views = [];
|
||||
[ObservableProperty] private AvaloniaList<ModModel> _selectedMods = [];
|
||||
|
||||
private string _search;
|
||||
private readonly ulong _applicationId;
|
||||
@@ -82,13 +82,13 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
foreach (string path in modsBasePaths)
|
||||
{
|
||||
bool inSd = path == ModLoader.GetSdModsBasePath();
|
||||
ModLoader.ModCache modCache = new ModLoader.ModCache();
|
||||
ModLoader.ModCache modCache = new();
|
||||
|
||||
ModLoader.QueryContentsDir(modCache, new DirectoryInfo(Path.Combine(path, "contents")), applicationId);
|
||||
|
||||
foreach (ModLoader.Mod<DirectoryInfo> mod in modCache.RomfsDirs)
|
||||
{
|
||||
ModModel modModel = new ModModel(mod.Path.Parent.FullName, mod.Name, mod.Enabled, inSd);
|
||||
ModModel modModel = new(mod.Path.Parent.FullName, mod.Name, mod.Enabled, inSd);
|
||||
if (Mods.All(x => x.Path != mod.Path.Parent.FullName))
|
||||
{
|
||||
Mods.Add(modModel);
|
||||
@@ -102,7 +102,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
foreach (ModLoader.Mod<DirectoryInfo> mod in modCache.ExefsDirs)
|
||||
{
|
||||
ModModel modModel = new ModModel(mod.Path.Parent.FullName, mod.Name, mod.Enabled, inSd);
|
||||
ModModel modModel = new(mod.Path.Parent.FullName, mod.Name, mod.Enabled, inSd);
|
||||
if (Mods.All(x => x.Path != mod.Path.Parent.FullName))
|
||||
{
|
||||
Mods.Add(modModel);
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
[ObservableProperty] private bool _isVulkanAvailable = true;
|
||||
[ObservableProperty] private bool _gameDirectoryChanged;
|
||||
[ObservableProperty] private bool _autoloadDirectoryChanged;
|
||||
private readonly List<string> _gpuIds = new();
|
||||
private readonly List<string> _gpuIds = [];
|
||||
private int _graphicsBackendIndex;
|
||||
private int _scalingFilter;
|
||||
private int _scalingFilterLevel;
|
||||
|
||||
@@ -21,8 +21,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private ApplicationLibrary ApplicationLibrary { get; }
|
||||
private ApplicationData ApplicationData { get; }
|
||||
|
||||
[ObservableProperty] private AvaloniaList<TitleUpdateModel> _titleUpdates = new();
|
||||
[ObservableProperty] private AvaloniaList<object> _views = new();
|
||||
[ObservableProperty] private AvaloniaList<TitleUpdateModel> _titleUpdates = [];
|
||||
[ObservableProperty] private AvaloniaList<object> _views = [];
|
||||
[ObservableProperty] private object _selectedUpdate = new TitleUpdateViewModelNoUpdate();
|
||||
[ObservableProperty] private bool _showBundledContentNotice;
|
||||
|
||||
@@ -149,9 +149,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats])
|
||||
{
|
||||
Patterns = new[] { "*.nsp" },
|
||||
AppleUniformTypeIdentifiers = new[] { "com.ryujinx.nsp" },
|
||||
MimeTypes = new[] { "application/x-nx-nsp" },
|
||||
Patterns = ["*.nsp"],
|
||||
AppleUniformTypeIdentifiers = ["com.ryujinx.nsp"],
|
||||
MimeTypes = ["application/x-nx-nsp"],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
|
||||
public UserFirmwareAvatarSelectorViewModel()
|
||||
{
|
||||
_images = new ObservableCollection<ProfileImageModel>();
|
||||
_images = [];
|
||||
|
||||
LoadImagesFromStore();
|
||||
PropertyChanged += (_, args) =>
|
||||
@@ -104,7 +104,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
// TODO: Parse DatabaseInfo.bin and table.bin files for more accuracy.
|
||||
if (item.Type == DirectoryEntryType.File && item.FullPath.Contains("chara") && item.FullPath.Contains("szs"))
|
||||
{
|
||||
using UniqueRef<IFile> file = new UniqueRef<IFile>();
|
||||
using UniqueRef<IFile> file = new();
|
||||
|
||||
romfs.OpenFile(ref file.Ref, ("/" + item.FullPath).ToU8Span(), OpenMode.Read).ThrowIfFailure();
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
{
|
||||
public UserProfileViewModel()
|
||||
{
|
||||
Profiles = new ObservableCollection<BaseModel>();
|
||||
LostProfiles = new ObservableCollection<UserProfile>();
|
||||
Profiles = [];
|
||||
LostProfiles = [];
|
||||
IsEmpty = !LostProfiles.Any();
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,8 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
[ObservableProperty] private int _sortIndex;
|
||||
[ObservableProperty] private int _orderIndex;
|
||||
[ObservableProperty] private string _search;
|
||||
[ObservableProperty] private ObservableCollection<SaveModel> _saves = new();
|
||||
[ObservableProperty] private ObservableCollection<SaveModel> _views = new();
|
||||
[ObservableProperty] private ObservableCollection<SaveModel> _saves = [];
|
||||
[ObservableProperty] private ObservableCollection<SaveModel> _views = [];
|
||||
private readonly AccountManager _accountManager;
|
||||
|
||||
public string SaveManagerHeading => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SaveManagerHeading, _accountManager.LastOpenedUser.Name, _accountManager.LastOpenedUser.UserId);
|
||||
|
||||
@@ -36,9 +36,9 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
private readonly Ryujinx.Common.Logging.XCIFileTrimmerLog _logger;
|
||||
private ApplicationLibrary ApplicationLibrary => _mainWindowViewModel.ApplicationLibrary;
|
||||
private Optional<XCITrimmerFileModel> _processingApplication = null;
|
||||
private AvaloniaList<XCITrimmerFileModel> _allXCIFiles = new();
|
||||
private AvaloniaList<XCITrimmerFileModel> _selectedXCIFiles = new();
|
||||
private AvaloniaList<XCITrimmerFileModel> _displayedXCIFiles = new();
|
||||
private AvaloniaList<XCITrimmerFileModel> _allXCIFiles = [];
|
||||
private AvaloniaList<XCITrimmerFileModel> _selectedXCIFiles = [];
|
||||
private AvaloniaList<XCITrimmerFileModel> _displayedXCIFiles = [];
|
||||
private MainWindowViewModel _mainWindowViewModel;
|
||||
private CancellationTokenSource _cancellationTokenSource;
|
||||
private string _search;
|
||||
@@ -183,7 +183,7 @@ namespace Ryujinx.Ava.UI.ViewModels
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
break;
|
||||
|
||||
XCIFileTrimmer trimmer = new XCIFileTrimmer(xciApp.Path, _logger);
|
||||
XCIFileTrimmer trimmer = new(xciApp.Path, _logger);
|
||||
|
||||
Dispatcher.UIThread.Post(() =>
|
||||
{
|
||||
|
||||
@@ -581,8 +581,6 @@
|
||||
Margin="0,-1,0,0">
|
||||
<Grid IsVisible="{Binding ParentModel.HasLed}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="*" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
</Grid.ColumnDefinitions>
|
||||
@@ -591,39 +589,14 @@
|
||||
MinWidth="0"
|
||||
Grid.Column="0"
|
||||
IsChecked="{Binding Config.EnableLedChanging, Mode=TwoWay}">
|
||||
<TextBlock Text="{ext:Locale ControllerSettingsLedColor}" />
|
||||
<TextBlock Text="{ext:Locale ControllerSettingsLed}" />
|
||||
</CheckBox>
|
||||
<CheckBox
|
||||
Margin="5, 10, 5, 10"
|
||||
MinWidth="0"
|
||||
<Button
|
||||
Margin="10"
|
||||
Grid.Column="1"
|
||||
IsVisible="{Binding ParentModel.CanClearLed}"
|
||||
IsChecked="{Binding Config.TurnOffLed, Mode=TwoWay}"
|
||||
Command="{Binding LedDisabledChanged}">
|
||||
<TextBlock Text="{ext:Locale ControllerSettingsLedColorDisable}" />
|
||||
</CheckBox>
|
||||
<CheckBox
|
||||
Margin="5, 10 5,10"
|
||||
MinWidth="0"
|
||||
Grid.Column="2"
|
||||
IsEnabled="{Binding !Config.TurnOffLed}"
|
||||
IsChecked="{Binding Config.UseRainbowLed, Mode=TwoWay}">
|
||||
<TextBlock Text="{ext:Locale ControllerSettingsLedColorRainbow}" />
|
||||
</CheckBox>
|
||||
<ui:ColorPickerButton
|
||||
Grid.Column="3"
|
||||
IsEnabled="{Binding Config.ShowLedColorPicker}"
|
||||
Margin="5, 10, 10, 10"
|
||||
IsMoreButtonVisible="False"
|
||||
UseColorPalette="False"
|
||||
UseColorTriangle="False"
|
||||
UseColorWheel="False"
|
||||
ShowAcceptDismissButtons="False"
|
||||
IsAlphaEnabled="False"
|
||||
AttachedToVisualTree="ColorPickerButton_OnAttachedToVisualTree"
|
||||
ColorChanged="ColorPickerButton_OnColorChanged"
|
||||
Color="{Binding Config.LedColor, Mode=TwoWay}">
|
||||
</ui:ColorPickerButton>
|
||||
Command="{Binding ShowLedConfig}">
|
||||
<TextBlock Text="{ext:Locale ControllerSettingsConfigureGeneral}" />
|
||||
</Button>
|
||||
</Grid>
|
||||
</Border>
|
||||
</StackPanel>
|
||||
|
||||
@@ -6,12 +6,10 @@ using Avalonia.Interactivity;
|
||||
using Avalonia.LogicalTree;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.UI.Helpers;
|
||||
using Ryujinx.Ava.UI.Models;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using Ryujinx.Common.Configuration.Hid.Controller;
|
||||
using Ryujinx.Input;
|
||||
using Ryujinx.Input.Assigner;
|
||||
using System.Linq;
|
||||
using Button = Ryujinx.Input.Button;
|
||||
using StickInputId = Ryujinx.Common.Configuration.Hid.Controller.StickInputId;
|
||||
|
||||
@@ -246,24 +244,5 @@ namespace Ryujinx.Ava.UI.Views.Input
|
||||
_currentAssigner?.Cancel();
|
||||
_currentAssigner = null;
|
||||
}
|
||||
|
||||
private void ColorPickerButton_OnColorChanged(ColorPickerButton sender, ColorButtonColorChangedEventArgs args)
|
||||
{
|
||||
if (!args.NewColor.HasValue) return;
|
||||
if (DataContext is not ControllerInputViewModel cVm) return;
|
||||
if (!cVm.Config.EnableLedChanging) return;
|
||||
if (cVm.Config.TurnOffLed) return;
|
||||
|
||||
cVm.ParentModel.SelectedGamepad.SetLed(args.NewColor.Value.ToUInt32());
|
||||
}
|
||||
|
||||
private void ColorPickerButton_OnAttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
if (DataContext is not ControllerInputViewModel cVm) return;
|
||||
if (!cVm.Config.EnableLedChanging) return;
|
||||
if (cVm.Config.TurnOffLed) return;
|
||||
|
||||
cVm.ParentModel.SelectedGamepad.SetLed(cVm.Config.LedColor.ToUInt32());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
46
src/Ryujinx/UI/Views/Input/LedInputView.axaml
Normal file
46
src/Ryujinx/UI/Views/Input/LedInputView.axaml
Normal file
@@ -0,0 +1,46 @@
|
||||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:controls="clr-namespace:Ryujinx.Ava.UI.Controls"
|
||||
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia"
|
||||
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup"
|
||||
xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels.Input"
|
||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||
x:DataType="viewModels:LedInputViewModel"
|
||||
x:Class="Ryujinx.UI.Views.Input.LedInputView">
|
||||
<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
|
||||
<StackPanel Orientation="Horizontal" IsVisible="{Binding ParentModel.CanClearLed}">
|
||||
<TextBlock MinWidth="75" MaxWidth="150" Text="{ext:Locale ControllerSettingsLedColorDisable}" />
|
||||
<CheckBox
|
||||
Margin="5"
|
||||
MinWidth="0"
|
||||
IsChecked="{Binding TurnOffLed, Mode=TwoWay}"
|
||||
Command="{Binding LedDisabledChanged}">
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" IsEnabled="{Binding !TurnOffLed}">
|
||||
<TextBlock MinWidth="75" MaxWidth="150" Text="{ext:Locale ControllerSettingsLedColorRainbow}" />
|
||||
<CheckBox
|
||||
Margin="5"
|
||||
MinWidth="0"
|
||||
IsChecked="{Binding UseRainbowLed, Mode=TwoWay}">
|
||||
</CheckBox>
|
||||
</StackPanel>
|
||||
<StackPanel Orientation="Horizontal" IsEnabled="{Binding ShowLedColorPicker}">
|
||||
<TextBlock MinWidth="75" MaxWidth="150" Text="{ext:Locale ControllerSettingsLedColor}" />
|
||||
<ui:ColorPickerButton
|
||||
Margin="5"
|
||||
IsMoreButtonVisible="False"
|
||||
UseColorPalette="False"
|
||||
UseColorTriangle="False"
|
||||
UseColorWheel="False"
|
||||
ShowAcceptDismissButtons="False"
|
||||
IsAlphaEnabled="False"
|
||||
AttachedToVisualTree="ColorPickerButton_OnAttachedToVisualTree"
|
||||
ColorChanged="ColorPickerButton_OnColorChanged"
|
||||
Color="{Binding LedColor, Mode=TwoWay}">
|
||||
</ui:ColorPickerButton>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
75
src/Ryujinx/UI/Views/Input/LedInputView.axaml.cs
Normal file
75
src/Ryujinx/UI/Views/Input/LedInputView.axaml.cs
Normal file
@@ -0,0 +1,75 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using FluentAvalonia.UI.Controls;
|
||||
using Ryujinx.Ava.Common.Locale;
|
||||
using Ryujinx.Ava.UI.Models.Input;
|
||||
using Ryujinx.Ava.UI.ViewModels.Input;
|
||||
using Ryujinx.Ava.UI.Views.Input;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Ryujinx.UI.Views.Input
|
||||
{
|
||||
public partial class LedInputView : UserControl
|
||||
{
|
||||
private readonly LedInputViewModel _viewModel;
|
||||
|
||||
public LedInputView(ControllerInputViewModel viewModel)
|
||||
{
|
||||
DataContext = _viewModel = new LedInputViewModel
|
||||
{
|
||||
ParentModel = viewModel.ParentModel,
|
||||
TurnOffLed = viewModel.Config.TurnOffLed,
|
||||
EnableLedChanging = viewModel.Config.EnableLedChanging,
|
||||
LedColor = viewModel.Config.LedColor,
|
||||
UseRainbowLed = viewModel.Config.UseRainbowLed,
|
||||
};
|
||||
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void ColorPickerButton_OnColorChanged(ColorPickerButton sender, ColorButtonColorChangedEventArgs args)
|
||||
{
|
||||
if (!args.NewColor.HasValue) return;
|
||||
if (DataContext is not LedInputViewModel lvm) return;
|
||||
if (!lvm.EnableLedChanging) return;
|
||||
if (lvm.TurnOffLed) return;
|
||||
|
||||
lvm.ParentModel.SelectedGamepad.SetLed(args.NewColor.Value.ToUInt32());
|
||||
}
|
||||
|
||||
private void ColorPickerButton_OnAttachedToVisualTree(object sender, VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
if (DataContext is not LedInputViewModel lvm) return;
|
||||
if (!lvm.EnableLedChanging) return;
|
||||
if (lvm.TurnOffLed) return;
|
||||
|
||||
lvm.ParentModel.SelectedGamepad.SetLed(lvm.LedColor.ToUInt32());
|
||||
}
|
||||
|
||||
public static async Task Show(ControllerInputViewModel viewModel)
|
||||
{
|
||||
LedInputView content = new(viewModel);
|
||||
|
||||
ContentDialog contentDialog = new()
|
||||
{
|
||||
Title = LocaleManager.Instance[LocaleKeys.ControllerLedTitle],
|
||||
PrimaryButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsSave],
|
||||
SecondaryButtonText = string.Empty,
|
||||
CloseButtonText = LocaleManager.Instance[LocaleKeys.ControllerSettingsClose],
|
||||
Content = content,
|
||||
};
|
||||
contentDialog.PrimaryButtonClick += (sender, args) =>
|
||||
{
|
||||
GamepadInputConfig config = viewModel.Config;
|
||||
config.EnableLedChanging = content._viewModel.EnableLedChanging;
|
||||
config.LedColor = content._viewModel.LedColor;
|
||||
config.UseRainbowLed = content._viewModel.UseRainbowLed;
|
||||
config.TurnOffLed = content._viewModel.TurnOffLed;
|
||||
};
|
||||
|
||||
await contentDialog.ShowAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,11 +66,11 @@ namespace Ryujinx.Ava.UI.Views.User
|
||||
{
|
||||
if (ViewModel.SelectedImage != null)
|
||||
{
|
||||
using MemoryStream streamJpg = new MemoryStream();
|
||||
using MemoryStream streamJpg = new();
|
||||
using SKBitmap bitmap = SKBitmap.Decode(ViewModel.SelectedImage);
|
||||
using SKBitmap newBitmap = new SKBitmap(bitmap.Width, bitmap.Height);
|
||||
using SKBitmap newBitmap = new(bitmap.Width, bitmap.Height);
|
||||
|
||||
using (SKCanvas canvas = new SKCanvas(newBitmap))
|
||||
using (SKCanvas canvas = new(newBitmap))
|
||||
{
|
||||
canvas.Clear(new SKColor(
|
||||
ViewModel.BackgroundColor.R,
|
||||
|
||||
@@ -70,9 +70,9 @@ namespace Ryujinx.Ava.UI.Views.User
|
||||
{
|
||||
new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats])
|
||||
{
|
||||
Patterns = new[] { "*.jpg", "*.jpeg", "*.png", "*.bmp" },
|
||||
AppleUniformTypeIdentifiers = new[] { "public.jpeg", "public.png", "com.microsoft.bmp" },
|
||||
MimeTypes = new[] { "image/jpeg", "image/png", "image/bmp" },
|
||||
Patterns = ["*.jpg", "*.jpeg", "*.png", "*.bmp"],
|
||||
AppleUniformTypeIdentifiers = ["public.jpeg", "public.png", "com.microsoft.bmp"],
|
||||
MimeTypes = ["image/jpeg", "image/png", "image/bmp"],
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -103,7 +103,7 @@ namespace Ryujinx.Ava.UI.Views.User
|
||||
|
||||
SKBitmap resizedBitmap = bitmap.Resize(new SKImageInfo(256, 256), SKFilterQuality.High);
|
||||
|
||||
using MemoryStream streamJpg = new MemoryStream();
|
||||
using MemoryStream streamJpg = new();
|
||||
|
||||
if (resizedBitmap != null)
|
||||
{
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace Ryujinx.Ava.UI.Views.User
|
||||
public void LoadSaves()
|
||||
{
|
||||
ViewModel.Saves.Clear();
|
||||
ObservableCollection<SaveModel> saves = new ObservableCollection<SaveModel>();
|
||||
ObservableCollection<SaveModel> saves = [];
|
||||
SaveDataFilter saveDataFilter = SaveDataFilter.Make(
|
||||
programId: default,
|
||||
saveType: SaveDataType.Account,
|
||||
@@ -75,7 +75,7 @@ namespace Ryujinx.Ava.UI.Views.User
|
||||
saveDataId: default,
|
||||
index: default);
|
||||
|
||||
using UniqueRef<SaveDataIterator> saveDataIterator = new UniqueRef<SaveDataIterator>();
|
||||
using UniqueRef<SaveDataIterator> saveDataIterator = new();
|
||||
|
||||
_horizonClient.Fs.OpenSaveDataIterator(ref saveDataIterator.Ref, SaveDataSpaceId.User, in saveDataFilter).ThrowIfFailure();
|
||||
|
||||
@@ -95,7 +95,7 @@ namespace Ryujinx.Ava.UI.Views.User
|
||||
SaveDataInfo save = saveDataInfo[i];
|
||||
if (save.ProgramId.Value != 0)
|
||||
{
|
||||
SaveModel saveModel = new SaveModel(save);
|
||||
SaveModel saveModel = new(save);
|
||||
saves.Add(saveModel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
public CheatWindow(VirtualFileSystem virtualFileSystem, string titleId, string titleName, string titlePath)
|
||||
{
|
||||
LoadedCheats = new AvaloniaList<CheatNode>();
|
||||
LoadedCheats = [];
|
||||
IntegrityCheckLevel checkLevel = ConfigurationState.Instance.System.EnableFsIntegrityChecks
|
||||
? IntegrityCheckLevel.ErrorOnInvalid
|
||||
: IntegrityCheckLevel.None;
|
||||
@@ -59,7 +59,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
int cheatAdded = 0;
|
||||
|
||||
ModLoader.ModCache mods = new ModLoader.ModCache();
|
||||
ModLoader.ModCache mods = new();
|
||||
|
||||
ModLoader.QueryContentsDir(mods, new DirectoryInfo(Path.Combine(modsBasePath, "contents")), titleIdValue);
|
||||
|
||||
@@ -81,7 +81,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
LoadedCheats.Add(currentGroup);
|
||||
}
|
||||
|
||||
CheatNode model = new CheatNode(cheat.Name, buildId, string.Empty, false, enabled.Contains($"{buildId}-{cheat.Name}"));
|
||||
CheatNode model = new(cheat.Name, buildId, string.Empty, false, enabled.Contains($"{buildId}-{cheat.Name}"));
|
||||
currentGroup?.SubNodes.Add(model);
|
||||
|
||||
cheatAdded++;
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
public static SKColor GetColor(SKBitmap image)
|
||||
{
|
||||
PaletteColor[] colors = new PaletteColor[TotalColors];
|
||||
Dictionary<int, int> dominantColorBin = new Dictionary<int, int>();
|
||||
Dictionary<int, int> dominantColorBin = new();
|
||||
|
||||
SKColor[] buffer = GetBuffer(image);
|
||||
|
||||
|
||||
@@ -712,12 +712,13 @@ namespace Ryujinx.Ava.UI.Windows
|
||||
|
||||
private void ShowNewContentAddedDialog(int numDlcAdded, int numDlcRemoved, int numUpdatesAdded, int numUpdatesRemoved)
|
||||
{
|
||||
string[] messages = {
|
||||
string[] messages =
|
||||
[
|
||||
numDlcRemoved > 0 ? string.Format(LocaleManager.Instance[LocaleKeys.AutoloadDlcRemovedMessage], numDlcRemoved): null,
|
||||
numDlcAdded > 0 ? string.Format(LocaleManager.Instance[LocaleKeys.AutoloadDlcAddedMessage], numDlcAdded): null,
|
||||
numUpdatesRemoved > 0 ? string.Format(LocaleManager.Instance[LocaleKeys.AutoloadUpdateRemovedMessage], numUpdatesRemoved): null,
|
||||
numUpdatesAdded > 0 ? string.Format(LocaleManager.Instance[LocaleKeys.AutoloadUpdateAddedMessage], numUpdatesAdded) : null
|
||||
};
|
||||
];
|
||||
|
||||
string msg = String.Join("\r\n", messages);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user