diff options
| author | Mary Guillemard <mary@mary.zone> | 2024-03-02 12:51:05 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-02 12:51:05 +0100 |
| commit | ec6cb0abb4b7669895b6e96fd7581c93b5abd691 (patch) | |
| tree | 128c862ff5faea0b219467656d4023bee7faefb5 /src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs | |
| parent | 53b5985da6b9d7b281d9fc25b93bfd1d1918a107 (diff) | |
infra: Make Avalonia the default UI (#6375)
* misc: Move Ryujinx project to Ryujinx.Gtk3
This breaks release CI for now but that's fine.
Signed-off-by: Mary Guillemard <mary@mary.zone>
* misc: Move Ryujinx.Ava project to Ryujinx
This breaks CI for now, but it's fine.
Signed-off-by: Mary Guillemard <mary@mary.zone>
* infra: Make Avalonia the default UI
Should fix CI after the previous changes.
GTK3 isn't build by the release job anymore, only by PR CI.
This also ensure that the test-ava update package is still generated to
allow update from the old testing channel.
Signed-off-by: Mary Guillemard <mary@mary.zone>
* Fix missing copy in create_app_bundle.sh
Signed-off-by: Mary Guillemard <mary@mary.zone>
* Fix syntax error
Signed-off-by: Mary Guillemard <mary@mary.zone>
---------
Signed-off-by: Mary Guillemard <mary@mary.zone>
Diffstat (limited to 'src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs')
| -rw-r--r-- | src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs | 518 |
1 files changed, 0 insertions, 518 deletions
diff --git a/src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs b/src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs deleted file mode 100644 index 8f09568a..00000000 --- a/src/Ryujinx.Ava/UI/ViewModels/AmiiboWindowViewModel.cs +++ /dev/null @@ -1,518 +0,0 @@ -using Avalonia; -using Avalonia.Collections; -using Avalonia.Media.Imaging; -using Avalonia.Threading; -using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.Helpers; -using Ryujinx.Ava.UI.Windows; -using Ryujinx.Common; -using Ryujinx.Common.Configuration; -using Ryujinx.Common.Logging; -using Ryujinx.Common.Utilities; -using Ryujinx.UI.Common.Models.Amiibo; -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO; -using System.Linq; -using System.Net.Http; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; - -namespace Ryujinx.Ava.UI.ViewModels -{ - public class AmiiboWindowViewModel : BaseModel, IDisposable - { - private const string DefaultJson = "{ \"amiibo\": [] }"; - private const float AmiiboImageSize = 350f; - - private readonly string _amiiboJsonPath; - private readonly byte[] _amiiboLogoBytes; - private readonly HttpClient _httpClient; - private readonly StyleableWindow _owner; - - private Bitmap _amiiboImage; - private List<AmiiboApi> _amiiboList; - private AvaloniaList<AmiiboApi> _amiibos; - private ObservableCollection<string> _amiiboSeries; - - private int _amiiboSelectedIndex; - private int _seriesSelectedIndex; - private bool _enableScanning; - private bool _showAllAmiibo; - private bool _useRandomUuid; - private string _usage; - - private static readonly AmiiboJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); - - public AmiiboWindowViewModel(StyleableWindow owner, string lastScannedAmiiboId, string titleId) - { - _owner = owner; - - _httpClient = new HttpClient - { - Timeout = TimeSpan.FromSeconds(30), - }; - - LastScannedAmiiboId = lastScannedAmiiboId; - TitleId = titleId; - - 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>(); - - _amiiboLogoBytes = EmbeddedResources.Read("Ryujinx.UI.Common/Resources/Logo_Amiibo.png"); - - _ = LoadContentAsync(); - } - - public AmiiboWindowViewModel() { } - - public string TitleId { get; set; } - public string LastScannedAmiiboId { get; set; } - - public UserResult Response { get; private set; } - - public bool UseRandomUuid - { - get => _useRandomUuid; - set - { - _useRandomUuid = value; - - OnPropertyChanged(); - } - } - - public bool ShowAllAmiibo - { - get => _showAllAmiibo; - set - { - _showAllAmiibo = value; - - ParseAmiiboData(); - - OnPropertyChanged(); - } - } - - public AvaloniaList<AmiiboApi> AmiiboList - { - get => _amiibos; - set - { - _amiibos = value; - - OnPropertyChanged(); - } - } - - public ObservableCollection<string> AmiiboSeries - { - get => _amiiboSeries; - set - { - _amiiboSeries = value; - OnPropertyChanged(); - } - } - - public int SeriesSelectedIndex - { - get => _seriesSelectedIndex; - set - { - _seriesSelectedIndex = value; - - FilterAmiibo(); - - OnPropertyChanged(); - } - } - - public int AmiiboSelectedIndex - { - get => _amiiboSelectedIndex; - set - { - _amiiboSelectedIndex = value; - - EnableScanning = _amiiboSelectedIndex >= 0 && _amiiboSelectedIndex < _amiibos.Count; - - SetAmiiboDetails(); - - OnPropertyChanged(); - } - } - - public Bitmap AmiiboImage - { - get => _amiiboImage; - set - { - _amiiboImage = value; - - OnPropertyChanged(); - } - } - - public string Usage - { - get => _usage; - set - { - _usage = value; - - OnPropertyChanged(); - } - } - - public bool EnableScanning - { - get => _enableScanning; - set - { - _enableScanning = value; - - OnPropertyChanged(); - } - } - - public void Dispose() - { - GC.SuppressFinalize(this); - _httpClient.Dispose(); - } - - private static bool TryGetAmiiboJson(string json, out AmiiboJson amiiboJson) - { - if (string.IsNullOrEmpty(json)) - { - amiiboJson = JsonHelper.Deserialize(DefaultJson, _serializerContext.AmiiboJson); - - return false; - } - - try - { - amiiboJson = JsonHelper.Deserialize(json, _serializerContext.AmiiboJson); - - return true; - } - catch (JsonException exception) - { - Logger.Error?.Print(LogClass.Application, $"Unable to deserialize amiibo data: {exception}"); - amiiboJson = JsonHelper.Deserialize(DefaultJson, _serializerContext.AmiiboJson); - - return false; - } - } - - private async Task<AmiiboJson> GetMostRecentAmiiboListOrDefaultJson() - { - bool localIsValid = false; - bool remoteIsValid = false; - AmiiboJson amiiboJson = new(); - - try - { - try - { - if (File.Exists(_amiiboJsonPath)) - { - localIsValid = TryGetAmiiboJson(await File.ReadAllTextAsync(_amiiboJsonPath), out amiiboJson); - } - } - catch (Exception exception) - { - Logger.Warning?.Print(LogClass.Application, $"Unable to read data from '{_amiiboJsonPath}': {exception}"); - } - - if (!localIsValid || await NeedsUpdate(amiiboJson.LastUpdated)) - { - remoteIsValid = TryGetAmiiboJson(await DownloadAmiiboJson(), out amiiboJson); - } - } - catch (Exception exception) - { - if (!(localIsValid || remoteIsValid)) - { - Logger.Error?.Print(LogClass.Application, $"Couldn't get valid amiibo data: {exception}"); - - // Neither local or remote files are valid JSON, close window. - ShowInfoDialog(); - Close(); - } - else if (!remoteIsValid) - { - Logger.Warning?.Print(LogClass.Application, $"Couldn't update amiibo data: {exception}"); - - // Only the local file is valid, the local one should be used - // but the user should be warned. - ShowInfoDialog(); - } - } - - return amiiboJson; - } - - private async Task LoadContentAsync() - { - AmiiboJson amiiboJson = await GetMostRecentAmiiboListOrDefaultJson(); - - _amiiboList = amiiboJson.Amiibo.OrderBy(amiibo => amiibo.AmiiboSeries).ToList(); - - ParseAmiiboData(); - } - - private void ParseAmiiboData() - { - _amiiboSeries.Clear(); - _amiibos.Clear(); - - for (int i = 0; i < _amiiboList.Count; i++) - { - if (!_amiiboSeries.Contains(_amiiboList[i].AmiiboSeries)) - { - if (!ShowAllAmiibo) - { - foreach (AmiiboApiGamesSwitch game in _amiiboList[i].GamesSwitch) - { - if (game != null) - { - if (game.GameId.Contains(TitleId)) - { - AmiiboSeries.Add(_amiiboList[i].AmiiboSeries); - - break; - } - } - } - } - else - { - AmiiboSeries.Add(_amiiboList[i].AmiiboSeries); - } - } - } - - if (LastScannedAmiiboId != "") - { - SelectLastScannedAmiibo(); - } - else - { - SeriesSelectedIndex = 0; - } - } - - private void SelectLastScannedAmiibo() - { - AmiiboApi scanned = _amiiboList.Find(amiibo => amiibo.GetId() == LastScannedAmiiboId); - - SeriesSelectedIndex = AmiiboSeries.IndexOf(scanned.AmiiboSeries); - AmiiboSelectedIndex = AmiiboList.IndexOf(scanned); - } - - private void FilterAmiibo() - { - _amiibos.Clear(); - - if (_seriesSelectedIndex < 0) - { - return; - } - - List<AmiiboApi> amiiboSortedList = _amiiboList - .Where(amiibo => amiibo.AmiiboSeries == _amiiboSeries[SeriesSelectedIndex]) - .OrderBy(amiibo => amiibo.Name).ToList(); - - for (int i = 0; i < amiiboSortedList.Count; i++) - { - if (!_amiibos.Contains(amiiboSortedList[i])) - { - if (!_showAllAmiibo) - { - foreach (AmiiboApiGamesSwitch game in amiiboSortedList[i].GamesSwitch) - { - if (game != null) - { - if (game.GameId.Contains(TitleId)) - { - _amiibos.Add(amiiboSortedList[i]); - - break; - } - } - } - } - else - { - _amiibos.Add(amiiboSortedList[i]); - } - } - } - - AmiiboSelectedIndex = 0; - } - - private void SetAmiiboDetails() - { - ResetAmiiboPreview(); - - Usage = string.Empty; - - if (_amiiboSelectedIndex < 0) - { - return; - } - - AmiiboApi selected = _amiibos[_amiiboSelectedIndex]; - - string imageUrl = _amiiboList.Find(amiibo => amiibo.Equals(selected)).Image; - - StringBuilder usageStringBuilder = new(); - - for (int i = 0; i < _amiiboList.Count; i++) - { - if (_amiiboList[i].Equals(selected)) - { - bool writable = false; - - foreach (AmiiboApiGamesSwitch item in _amiiboList[i].GamesSwitch) - { - if (item.GameId.Contains(TitleId)) - { - foreach (AmiiboApiUsage usageItem in item.AmiiboUsage) - { - usageStringBuilder.Append($"{Environment.NewLine}- {usageItem.Usage.Replace("/", Environment.NewLine + "-")}"); - - writable = usageItem.Write; - } - } - } - - if (usageStringBuilder.Length == 0) - { - usageStringBuilder.Append($"{LocaleManager.Instance[LocaleKeys.Unknown]}."); - } - - Usage = $"{LocaleManager.Instance[LocaleKeys.Usage]} {(writable ? $" ({LocaleManager.Instance[LocaleKeys.Writable]})" : "")} : {usageStringBuilder}"; - } - } - - _ = UpdateAmiiboPreview(imageUrl); - } - - private async Task<bool> NeedsUpdate(DateTime oldLastModified) - { - try - { - HttpResponseMessage response = await _httpClient.SendAsync(new HttpRequestMessage(HttpMethod.Head, "https://amiibo.ryujinx.org/")); - - if (response.IsSuccessStatusCode) - { - return response.Content.Headers.LastModified != oldLastModified; - } - } - catch (HttpRequestException exception) - { - Logger.Error?.Print(LogClass.Application, $"Unable to check for amiibo data updates: {exception}"); - } - - return false; - } - - private async Task<string> DownloadAmiiboJson() - { - try - { - HttpResponseMessage response = await _httpClient.GetAsync("https://amiibo.ryujinx.org/"); - - if (response.IsSuccessStatusCode) - { - string amiiboJsonString = await response.Content.ReadAsStringAsync(); - - try - { - using FileStream dlcJsonStream = File.Create(_amiiboJsonPath, 4096, FileOptions.WriteThrough); - dlcJsonStream.Write(Encoding.UTF8.GetBytes(amiiboJsonString)); - } - catch (Exception exception) - { - Logger.Warning?.Print(LogClass.Application, $"Couldn't write amiibo data to file '{_amiiboJsonPath}: {exception}'"); - } - - return amiiboJsonString; - } - - Logger.Error?.Print(LogClass.Application, $"Failed to download amiibo data. Response status code: {response.StatusCode}"); - } - catch (HttpRequestException exception) - { - Logger.Error?.Print(LogClass.Application, $"Failed to request amiibo data: {exception}"); - } - - await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogAmiiboApiTitle], - LocaleManager.Instance[LocaleKeys.DialogAmiiboApiFailFetchMessage], - LocaleManager.Instance[LocaleKeys.InputDialogOk], - "", - LocaleManager.Instance[LocaleKeys.RyujinxInfo]); - - return null; - } - - private void Close() - { - Dispatcher.UIThread.Post(_owner.Close); - } - - private async Task UpdateAmiiboPreview(string imageUrl) - { - HttpResponseMessage response = await _httpClient.GetAsync(imageUrl); - - if (response.IsSuccessStatusCode) - { - byte[] amiiboPreviewBytes = await response.Content.ReadAsByteArrayAsync(); - using MemoryStream memoryStream = new(amiiboPreviewBytes); - - Bitmap bitmap = new(memoryStream); - - double ratio = Math.Min(AmiiboImageSize / bitmap.Size.Width, - AmiiboImageSize / bitmap.Size.Height); - - int resizeHeight = (int)(bitmap.Size.Height * ratio); - int resizeWidth = (int)(bitmap.Size.Width * ratio); - - AmiiboImage = bitmap.CreateScaledBitmap(new PixelSize(resizeWidth, resizeHeight)); - } - else - { - Logger.Error?.Print(LogClass.Application, $"Failed to get amiibo preview. Response status code: {response.StatusCode}"); - } - } - - private void ResetAmiiboPreview() - { - using MemoryStream memoryStream = new(_amiiboLogoBytes); - - Bitmap bitmap = new(memoryStream); - - AmiiboImage = bitmap; - } - - private static async void ShowInfoDialog() - { - await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogAmiiboApiTitle], - LocaleManager.Instance[LocaleKeys.DialogAmiiboApiConnectErrorMessage], - LocaleManager.Instance[LocaleKeys.InputDialogOk], - "", - LocaleManager.Instance[LocaleKeys.RyujinxInfo]); - } - } -} |
