0
0
Fork 0
mirror of https://github.com/GreemDev/Ryujinx.git synced 2025-01-09 10:01:59 +00:00

misc: More Mvvm usage instead of writing out the observable properties

This commit is contained in:
Evan Husted 2024-12-31 21:11:57 -06:00
parent 3525d5ecd4
commit 27c5cba10b
11 changed files with 72 additions and 277 deletions

View file

@ -1,6 +1,7 @@
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
using Avalonia.Styling; using Avalonia.Styling;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using Ryujinx.Ava.Common; using Ryujinx.Ava.Common;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Utilities.Configuration; using Ryujinx.Ava.Utilities.Configuration;
@ -8,42 +9,11 @@ using System;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class AboutWindowViewModel : BaseModel, IDisposable public partial class AboutWindowViewModel : BaseModel, IDisposable
{ {
private Bitmap _githubLogo; [ObservableProperty] private Bitmap _githubLogo;
private Bitmap _discordLogo; [ObservableProperty] private Bitmap _discordLogo;
[ObservableProperty] private string _version;
private string _version;
public Bitmap GithubLogo
{
get => _githubLogo;
set
{
_githubLogo = value;
OnPropertyChanged();
}
}
public Bitmap DiscordLogo
{
get => _discordLogo;
set
{
_discordLogo = value;
OnPropertyChanged();
}
}
public string Version
{
get => _version;
set
{
_version = value;
OnPropertyChanged();
}
}
public string Developers => "GreemDev"; public string Developers => "GreemDev";

View file

@ -2,6 +2,7 @@ using Avalonia.Collections;
using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using DynamicData; using DynamicData;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
@ -17,13 +18,13 @@ using Application = Avalonia.Application;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class DownloadableContentManagerViewModel : BaseModel public partial class DownloadableContentManagerViewModel : BaseModel
{ {
private readonly ApplicationLibrary _applicationLibrary; private readonly ApplicationLibrary _applicationLibrary;
private AvaloniaList<DownloadableContentModel> _downloadableContents = new(); private AvaloniaList<DownloadableContentModel> _downloadableContents = new();
private AvaloniaList<DownloadableContentModel> _selectedDownloadableContents = new(); [ObservableProperty] private AvaloniaList<DownloadableContentModel> _selectedDownloadableContents = new();
private AvaloniaList<DownloadableContentModel> _views = new(); [ObservableProperty] private AvaloniaList<DownloadableContentModel> _views = new();
private bool _showBundledContentNotice = false; [ObservableProperty] private bool _showBundledContentNotice = false;
private string _search; private string _search;
private readonly ApplicationData _applicationData; private readonly ApplicationData _applicationData;
@ -41,26 +42,6 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public AvaloniaList<DownloadableContentModel> Views
{
get => _views;
set
{
_views = value;
OnPropertyChanged();
}
}
public AvaloniaList<DownloadableContentModel> SelectedDownloadableContents
{
get => _selectedDownloadableContents;
set
{
_selectedDownloadableContents = value;
OnPropertyChanged();
}
}
public string Search public string Search
{ {
get => _search; get => _search;
@ -77,16 +58,6 @@ namespace Ryujinx.Ava.UI.ViewModels
get => string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowHeading], DownloadableContents.Count); get => string.Format(LocaleManager.Instance[LocaleKeys.DlcWindowHeading], DownloadableContents.Count);
} }
public bool ShowBundledContentNotice
{
get => _showBundledContentNotice;
set
{
_showBundledContentNotice = value;
OnPropertyChanged();
}
}
public DownloadableContentManagerViewModel(ApplicationLibrary applicationLibrary, ApplicationData applicationData) public DownloadableContentManagerViewModel(ApplicationLibrary applicationLibrary, ApplicationData applicationData)
{ {
_applicationLibrary = applicationLibrary; _applicationLibrary = applicationLibrary;

View file

@ -1,8 +1,7 @@
using Avalonia;
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using DynamicData; using DynamicData;
using Gommon; using Gommon;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
@ -18,13 +17,13 @@ using System.Linq;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class ModManagerViewModel : BaseModel public partial class ModManagerViewModel : BaseModel
{ {
private readonly string _modJsonPath; private readonly string _modJsonPath;
private AvaloniaList<ModModel> _mods = new(); private AvaloniaList<ModModel> _mods = new();
private AvaloniaList<ModModel> _views = new(); [ObservableProperty] private AvaloniaList<ModModel> _views = new();
private AvaloniaList<ModModel> _selectedMods = new(); [ObservableProperty] private AvaloniaList<ModModel> _selectedMods = new();
private string _search; private string _search;
private readonly ulong _applicationId; private readonly ulong _applicationId;
@ -44,26 +43,6 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
} }
public AvaloniaList<ModModel> Views
{
get => _views;
set
{
_views = value;
OnPropertyChanged();
}
}
public AvaloniaList<ModModel> SelectedMods
{
get => _selectedMods;
set
{
_selectedMods = value;
OnPropertyChanged();
}
}
public string Search public string Search
{ {
get => _search; get => _search;
@ -143,8 +122,10 @@ namespace Ryujinx.Ava.UI.ViewModels
.Filter(Filter) .Filter(Filter)
.Bind(out var view).AsObservableList(); .Bind(out var view).AsObservableList();
#pragma warning disable MVVMTK0034 // Event to update is fired below
_views.Clear(); _views.Clear();
_views.AddRange(view); _views.AddRange(view);
#pragma warning restore MVVMTK0034
SelectedMods = new(Views.Where(x => x.Enabled)); SelectedMods = new(Views.Where(x => x.Enabled));

View file

@ -1,9 +1,10 @@
using Gommon; using CommunityToolkit.Mvvm.ComponentModel;
using Gommon;
using Ryujinx.Ava.Utilities.Configuration; using Ryujinx.Ava.Utilities.Configuration;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class SettingsHacksViewModel : BaseModel public partial class SettingsHacksViewModel : BaseModel
{ {
private readonly SettingsViewModel _baseViewModel; private readonly SettingsViewModel _baseViewModel;
@ -14,31 +15,9 @@ namespace Ryujinx.Ava.UI.ViewModels
_baseViewModel = settingsVm; _baseViewModel = settingsVm;
} }
private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix; [ObservableProperty] private bool _xc2MenuSoftlockFix = ConfigurationState.Instance.Hacks.Xc2MenuSoftlockFix;
private bool _shaderTranslationThreadSleep = ConfigurationState.Instance.Hacks.EnableShaderTranslationDelay; [ObservableProperty] private bool _shaderTranslationDelayEnabled = ConfigurationState.Instance.Hacks.EnableShaderTranslationDelay;
private int _shaderTranslationSleepDelay = ConfigurationState.Instance.Hacks.ShaderTranslationDelay; private int _shaderTranslationSleepDelay = ConfigurationState.Instance.Hacks.ShaderTranslationDelay;
public bool Xc2MenuSoftlockFixEnabled
{
get => _xc2MenuSoftlockFix;
set
{
_xc2MenuSoftlockFix = value;
OnPropertyChanged();
}
}
public bool ShaderTranslationDelayEnabled
{
get => _shaderTranslationThreadSleep;
set
{
_shaderTranslationThreadSleep = value;
OnPropertyChanged();
}
}
public string ShaderTranslationDelayValueText => $"{ShaderTranslationDelay}ms"; public string ShaderTranslationDelayValueText => $"{ShaderTranslationDelay}ms";

View file

@ -756,7 +756,7 @@ namespace Ryujinx.Ava.UI.ViewModels
config.Multiplayer.LdnServer.Value = LdnServer; config.Multiplayer.LdnServer.Value = LdnServer;
// Dirty Hacks // Dirty Hacks
config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFixEnabled; config.Hacks.Xc2MenuSoftlockFix.Value = DirtyHacks.Xc2MenuSoftlockFix;
config.Hacks.EnableShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelayEnabled; config.Hacks.EnableShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelayEnabled;
config.Hacks.ShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelay; config.Hacks.ShaderTranslationDelay.Value = DirtyHacks.ShaderTranslationDelay;

View file

@ -1,74 +1,32 @@
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading; using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using FluentAvalonia.UI.Controls; using FluentAvalonia.UI.Controls;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Common.Models; using Ryujinx.Ava.Common.Models;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.Utilities.AppLibrary; using Ryujinx.Ava.Utilities.AppLibrary;
using Ryujinx.HLE.FileSystem;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using Application = Avalonia.Application;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public record TitleUpdateViewNoUpdateSentinal(); public record TitleUpdateViewModelNoUpdate;
public class TitleUpdateViewModel : BaseModel public partial class TitleUpdateViewModel : BaseModel
{ {
private ApplicationLibrary ApplicationLibrary { get; } private ApplicationLibrary ApplicationLibrary { get; }
private ApplicationData ApplicationData { get; } private ApplicationData ApplicationData { get; }
private AvaloniaList<TitleUpdateModel> _titleUpdates = new(); [ObservableProperty] private AvaloniaList<TitleUpdateModel> _titleUpdates = new();
private AvaloniaList<object> _views = new(); [ObservableProperty] private AvaloniaList<object> _views = new();
private object _selectedUpdate = new TitleUpdateViewNoUpdateSentinal(); [ObservableProperty] private object _selectedUpdate = new TitleUpdateViewModelNoUpdate();
private bool _showBundledContentNotice = false; [ObservableProperty] private bool _showBundledContentNotice;
public AvaloniaList<TitleUpdateModel> TitleUpdates private readonly IStorageProvider _storageProvider;
{
get => _titleUpdates;
set
{
_titleUpdates = value;
OnPropertyChanged();
}
}
public AvaloniaList<object> Views
{
get => _views;
set
{
_views = value;
OnPropertyChanged();
}
}
public object SelectedUpdate
{
get => _selectedUpdate;
set
{
_selectedUpdate = value;
OnPropertyChanged();
}
}
public bool ShowBundledContentNotice
{
get => _showBundledContentNotice;
set
{
_showBundledContentNotice = value;
OnPropertyChanged();
}
}
public IStorageProvider StorageProvider;
public TitleUpdateViewModel(ApplicationLibrary applicationLibrary, ApplicationData applicationData) public TitleUpdateViewModel(ApplicationLibrary applicationLibrary, ApplicationData applicationData)
{ {
@ -76,7 +34,7 @@ namespace Ryujinx.Ava.UI.ViewModels
ApplicationData = applicationData; ApplicationData = applicationData;
StorageProvider = RyujinxApp.MainWindow.StorageProvider; _storageProvider = RyujinxApp.MainWindow.StorageProvider;
LoadUpdates(); LoadUpdates();
} }
@ -87,7 +45,7 @@ namespace Ryujinx.Ava.UI.ViewModels
.Where(it => it.TitleUpdate.TitleIdBase == ApplicationData.IdBase); .Where(it => it.TitleUpdate.TitleIdBase == ApplicationData.IdBase);
bool hasBundledContent = false; bool hasBundledContent = false;
SelectedUpdate = new TitleUpdateViewNoUpdateSentinal(); SelectedUpdate = new TitleUpdateViewModelNoUpdate();
foreach ((TitleUpdateModel update, bool isSelected) in updates) foreach ((TitleUpdateModel update, bool isSelected) in updates)
{ {
TitleUpdates.Add(update); TitleUpdates.Add(update);
@ -113,12 +71,12 @@ namespace Ryujinx.Ava.UI.ViewModels
var selected = SelectedUpdate; var selected = SelectedUpdate;
Views.Clear(); Views.Clear();
Views.Add(new TitleUpdateViewNoUpdateSentinal()); Views.Add(new TitleUpdateViewModelNoUpdate());
Views.AddRange(sortedUpdates); Views.AddRange(sortedUpdates);
SelectedUpdate = selected; SelectedUpdate = selected;
if (SelectedUpdate is TitleUpdateViewNoUpdateSentinal) if (SelectedUpdate is TitleUpdateViewModelNoUpdate)
{ {
SelectedUpdate = Views[0]; SelectedUpdate = Views[0];
} }
@ -176,7 +134,7 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
else if (update == SelectedUpdate as TitleUpdateModel) else if (update == SelectedUpdate as TitleUpdateModel)
{ {
SelectedUpdate = new TitleUpdateViewNoUpdateSentinal(); SelectedUpdate = new TitleUpdateViewModelNoUpdate();
} }
SortUpdates(); SortUpdates();
@ -184,7 +142,7 @@ namespace Ryujinx.Ava.UI.ViewModels
public async Task Add() public async Task Add()
{ {
var result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions var result = await _storageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{ {
AllowMultiple = true, AllowMultiple = true,
FileTypeFilter = new List<FilePickerFileType> FileTypeFilter = new List<FilePickerFileType>

View file

@ -1,4 +1,5 @@
using Avalonia.Media; using Avalonia.Media;
using CommunityToolkit.Mvvm.ComponentModel;
using LibHac.Common; using LibHac.Common;
using LibHac.Fs; using LibHac.Fs;
using LibHac.Fs.Fsa; using LibHac.Fs.Fsa;
@ -20,12 +21,12 @@ using Image = SkiaSharp.SKImage;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
internal class UserFirmwareAvatarSelectorViewModel : BaseModel internal partial class UserFirmwareAvatarSelectorViewModel : BaseModel
{ {
private static readonly Dictionary<string, byte[]> _avatarStore = new(); private static readonly Dictionary<string, byte[]> _avatarStore = new();
private ObservableCollection<ProfileImageModel> _images; [ObservableProperty] private ObservableCollection<ProfileImageModel> _images;
private Color _backgroundColor = Colors.White; [ObservableProperty] private Color _backgroundColor = Colors.White;
private int _selectedIndex; private int _selectedIndex;
@ -34,27 +35,11 @@ namespace Ryujinx.Ava.UI.ViewModels
_images = new ObservableCollection<ProfileImageModel>(); _images = new ObservableCollection<ProfileImageModel>();
LoadImagesFromStore(); LoadImagesFromStore();
} PropertyChanged += (_, args) =>
public Color BackgroundColor
{
get => _backgroundColor;
set
{ {
_backgroundColor = value; if (args.PropertyName == nameof(BackgroundColor))
OnPropertyChanged(); ChangeImageBackground();
ChangeImageBackground(); };
}
}
public ObservableCollection<ProfileImageModel> Images
{
get => _images;
set
{
_images = value;
OnPropertyChanged();
}
} }
public int SelectedIndex public int SelectedIndex
@ -70,7 +55,7 @@ namespace Ryujinx.Ava.UI.ViewModels
} }
else else
{ {
SelectedImage = _images[_selectedIndex].Data; SelectedImage = Images[_selectedIndex].Data;
} }
OnPropertyChanged(); OnPropertyChanged();

View file

@ -1,18 +1,9 @@
using CommunityToolkit.Mvvm.ComponentModel;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
internal class UserProfileImageSelectorViewModel : BaseModel internal partial class UserProfileImageSelectorViewModel : BaseModel
{ {
private bool _firmwareFound; [ObservableProperty] private bool _firmwareFound;
public bool FirmwareFound
{
get => _firmwareFound;
set
{
_firmwareFound = value;
OnPropertyChanged();
}
}
} }
} }

View file

@ -1,3 +1,4 @@
using CommunityToolkit.Mvvm.ComponentModel;
using DynamicData; using DynamicData;
using DynamicData.Binding; using DynamicData.Binding;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
@ -8,74 +9,31 @@ using System.Collections.ObjectModel;
namespace Ryujinx.Ava.UI.ViewModels namespace Ryujinx.Ava.UI.ViewModels
{ {
public class UserSaveManagerViewModel : BaseModel public partial class UserSaveManagerViewModel : BaseModel
{ {
private int _sortIndex; [ObservableProperty] private int _sortIndex;
private int _orderIndex; [ObservableProperty] private int _orderIndex;
private string _search; [ObservableProperty] private string _search;
private ObservableCollection<SaveModel> _saves = new(); [ObservableProperty] private ObservableCollection<SaveModel> _saves = new();
private ObservableCollection<SaveModel> _views = new(); [ObservableProperty] private ObservableCollection<SaveModel> _views = new();
private readonly AccountManager _accountManager; private readonly AccountManager _accountManager;
public string SaveManagerHeading => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SaveManagerHeading, _accountManager.LastOpenedUser.Name, _accountManager.LastOpenedUser.UserId); public string SaveManagerHeading => LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.SaveManagerHeading, _accountManager.LastOpenedUser.Name, _accountManager.LastOpenedUser.UserId);
public int SortIndex
{
get => _sortIndex;
set
{
_sortIndex = value;
OnPropertyChanged();
Sort();
}
}
public int OrderIndex
{
get => _orderIndex;
set
{
_orderIndex = value;
OnPropertyChanged();
Sort();
}
}
public string Search
{
get => _search;
set
{
_search = value;
OnPropertyChanged();
Sort();
}
}
public ObservableCollection<SaveModel> Saves
{
get => _saves;
set
{
_saves = value;
OnPropertyChanged();
Sort();
}
}
public ObservableCollection<SaveModel> Views
{
get => _views;
set
{
_views = value;
OnPropertyChanged();
}
}
public UserSaveManagerViewModel(AccountManager accountManager) public UserSaveManagerViewModel(AccountManager accountManager)
{ {
_accountManager = accountManager; _accountManager = accountManager;
PropertyChanged += (_, evt) =>
{
if (evt.PropertyName is
nameof(SortIndex) or
nameof(OrderIndex) or
nameof(Search) or
nameof(Saves))
{
Sort();
}
};
} }
public void Sort() public void Sort()
@ -85,8 +43,10 @@ namespace Ryujinx.Ava.UI.ViewModels
.Sort(GetComparer()) .Sort(GetComparer())
.Bind(out var view).AsObservableList(); .Bind(out var view).AsObservableList();
#pragma warning disable MVVMTK0034
_views.Clear(); _views.Clear();
_views.AddRange(view); _views.AddRange(view);
#pragma warning restore MVVMTK0034
OnPropertyChanged(nameof(Views)); OnPropertyChanged(nameof(Views));
} }
@ -94,7 +54,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
if (arg is SaveModel save) if (arg is SaveModel save)
{ {
return string.IsNullOrWhiteSpace(_search) || save.Title.ToLower().Contains(_search.ToLower()); return string.IsNullOrWhiteSpace(Search) || save.Title.ToLower().Contains(Search.ToLower());
} }
return false; return false;

View file

@ -37,7 +37,7 @@
ToolTip.Tip="{Binding DirtyHacks.Xc2MenuFixTooltip}"> ToolTip.Tip="{Binding DirtyHacks.Xc2MenuFixTooltip}">
<CheckBox <CheckBox
Margin="0" Margin="0"
IsChecked="{Binding DirtyHacks.Xc2MenuSoftlockFixEnabled}"/> IsChecked="{Binding DirtyHacks.Xc2MenuSoftlockFix}"/>
<TextBlock <TextBlock
VerticalAlignment="Center" VerticalAlignment="Center"
Text="Xenoblade Chronicles 2 Menu Softlock Fix" /> Text="Xenoblade Chronicles 2 Menu Softlock Fix" />

View file

@ -95,7 +95,7 @@
</Panel> </Panel>
</DataTemplate> </DataTemplate>
<DataTemplate <DataTemplate
DataType="viewModels:TitleUpdateViewNoUpdateSentinal"> DataType="viewModels:TitleUpdateViewModelNoUpdate">
<Panel <Panel
Height="33" Height="33"
Margin="10"> Margin="10">