From aef114c3092c08b7707f14857dc845fb30ce604b Mon Sep 17 00:00:00 2001 From: xam <87-xam@users.noreply.git.ryujinx.app> Date: Mon, 20 Oct 2025 00:06:37 +0200 Subject: [PATCH 1/2] Settings: Debug: add purge all caches button --- assets/locales.json | 75 +++++++++++++++++++ .../UI/Views/Settings/SettingsDebugView.axaml | 7 ++ .../Views/Settings/SettingsDebugView.axaml.cs | 60 ++++++++++++++- 3 files changed, 141 insertions(+), 1 deletion(-) diff --git a/assets/locales.json b/assets/locales.json index 8899bf692..45914a6d1 100644 --- a/assets/locales.json +++ b/assets/locales.json @@ -13717,6 +13717,56 @@ "zh_TW": "警告" } }, + { + "ID": "DialogDeleteAllCaches", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "You are about to clear all caches for all games.\n\nAre you sure you want to proceed?", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "DialogDeleteAllCachesErrorMessage", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Failed to purge some caches, check log file.", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, { "ID": "DialogPPTCDeletionMessage", "Translations": { @@ -24217,6 +24267,31 @@ "zh_TW": "在執行首項指令前暫停應用程式,以便從最早的點開始偵錯。" } }, + { + "ID": "SettingsTabDebugPurgeAllCaches", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Purge All Caches", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, { "ID": "LdnGameListOpen", "Translations": { diff --git a/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml index f491dda24..f1ff9c5ea 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml @@ -53,12 +53,19 @@ + diff --git a/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml.cs index 14a65b8b2..d7924ab52 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml.cs @@ -1,4 +1,11 @@ using Avalonia.Controls; +using Avalonia.Interactivity; +using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.UI.Helpers; +using Ryujinx.Common.Configuration; +using Ryujinx.Common.Logging; +using System; +using System.IO; namespace Ryujinx.Ava.UI.Views.Settings { @@ -8,6 +15,57 @@ namespace Ryujinx.Ava.UI.Views.Settings { InitializeComponent(); } + + private async void PurgeAllSharedCaches_OnClick(object sender, RoutedEventArgs routedEventArgs) + { + var appList = RyujinxApp.MainWindow.ViewModel.Applications; + + if (appList.Count == 0) + { + return; + } + + UserResult result = await ContentDialogHelper.CreateConfirmationDialog( + LocaleManager.Instance[LocaleKeys.DialogWarning], + LocaleManager.Instance[LocaleKeys.DialogDeleteAllCaches], + LocaleManager.Instance[LocaleKeys.InputDialogYes], + LocaleManager.Instance[LocaleKeys.InputDialogNo], + LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); + bool hasErrors = false; + + if (result != UserResult.Yes) + { + return; + } + + foreach (var application in appList) + { + DirectoryInfo cacheDir = new(Path.Combine(AppDataManager.GamesDirPath, application.IdString, "cache")); + + if (!cacheDir.Exists) + { + continue; + } + + foreach (var finfo in cacheDir.EnumerateDirectories()) + { + try + { + finfo.Delete(true); + + } + catch (Exception ex) + { + Logger.Error?.Print(LogClass.Application, $"Failed to purge shader cache for {application.Name}({application.IdString}): {ex}"); + hasErrors = true; + } + } + } + + if (hasErrors) + { + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogDeleteAllCachesErrorMessage]); + } + } } } - From 71ad102f7332f63df8f5a36dc31d234690fc8ac3 Mon Sep 17 00:00:00 2001 From: GreemDev Date: Sun, 16 Nov 2025 18:51:10 -0600 Subject: [PATCH 2/2] Cleanup & successful deletion feedback --- assets/locales.json | 52 +++++++++++++- .../UI/ViewModels/SettingsViewModel.cs | 71 +++++++++++++++++-- .../UI/Views/Settings/SettingsDebugView.axaml | 4 +- .../Views/Settings/SettingsDebugView.axaml.cs | 59 --------------- 4 files changed, 118 insertions(+), 68 deletions(-) diff --git a/assets/locales.json b/assets/locales.json index 45914a6d1..afb2ecf11 100644 --- a/assets/locales.json +++ b/assets/locales.json @@ -24292,6 +24292,56 @@ "zh_TW": "" } }, + { + "ID": "SettingsTabDebugPurgeAllCachesSuccessTitle", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "All Shader & CPU caches deleted", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "SettingsTabDebugPurgeAllCachesSuccessText", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Destroyed the caches of {0} applications.", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, { "ID": "LdnGameListOpen", "Translations": { @@ -24918,4 +24968,4 @@ } } ] -} \ No newline at end of file +} diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index 233c30bad..071d83f86 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -4,11 +4,13 @@ using Avalonia.Media.Imaging; using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; +using DynamicData.Binding; using LibHac.Tools.FsSystem; using Ryujinx.Audio.Backends.OpenAL; using Ryujinx.Audio.Backends.SDL3; using Ryujinx.Audio.Backends.SoundIo; using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Systems.AppLibrary; using Ryujinx.Ava.Systems.Configuration; using Ryujinx.Ava.Systems.Configuration.System; using Ryujinx.Ava.Systems.Configuration.UI; @@ -19,6 +21,7 @@ using Ryujinx.Common.Configuration; using Ryujinx.Common.Configuration.Multiplayer; using Ryujinx.Common.GraphicsDriver; using Ryujinx.Common.Helper; +using Ryujinx.Common.Logging; using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Vulkan; using Ryujinx.HLE; @@ -912,7 +915,13 @@ namespace Ryujinx.Ava.UI.ViewModels CloseWindow?.Invoke(); } - [ObservableProperty] private bool _wantsToReset; + public void CancelButton() + { + RevertIfNotSaved(); + CloseWindow?.Invoke(); + } + + [ObservableProperty] public partial bool WantsToReset { get; set; } public AsyncRelayCommand ResetButton => Commands.Create(async () => { @@ -932,10 +941,62 @@ namespace Ryujinx.Ava.UI.ViewModels "Configuration Reset"); }); - public void CancelButton() + public AsyncRelayCommand PurgeAllCaches => Commands.Create(async () => { - RevertIfNotSaved(); - CloseWindow?.Invoke(); - } + ObservableCollectionExtended appList = RyujinxApp.MainWindow.ViewModel.Applications; + + if (appList.Count == 0) + { + return; + } + + UserResult result = await ContentDialogHelper.CreateConfirmationDialog( + LocaleManager.Instance[LocaleKeys.DialogWarning], + LocaleManager.Instance[LocaleKeys.DialogDeleteAllCaches], + LocaleManager.Instance[LocaleKeys.InputDialogYes], + LocaleManager.Instance[LocaleKeys.InputDialogNo], + LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); + + bool hasErrors = false; + + if (result != UserResult.Yes) + { + return; + } + + foreach (ApplicationData application in appList) + { + DirectoryInfo cacheDir = new(Path.Combine(AppDataManager.GamesDirPath, application.IdString, "cache")); + + if (!cacheDir.Exists) + { + continue; + } + + foreach (DirectoryInfo dInfo in cacheDir.EnumerateDirectories()) + { + try + { + dInfo.Delete(recursive: true); + } + catch (Exception ex) + { + Logger.Error?.PrintMsg(LogClass.Application, $"Failed to purge shader cache for {application.Name} ({application.IdString}): {ex}"); + hasErrors = true; + } + } + } + + if (hasErrors) + { + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogDeleteAllCachesErrorMessage]); + } + else + { + NotificationHelper.ShowSuccess( + title: LocaleManager.Instance[LocaleKeys.SettingsTabDebugPurgeAllCachesSuccessTitle], + text: LocaleManager.GetFormatted(LocaleKeys.SettingsTabDebugPurgeAllCachesSuccessText, appList.Count)); + } + }); } } diff --git a/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml b/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml index f1ff9c5ea..56a049d46 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml +++ b/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml @@ -60,9 +60,7 @@ - diff --git a/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml.cs b/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml.cs index d7924ab52..d68a2444c 100644 --- a/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml.cs +++ b/src/Ryujinx/UI/Views/Settings/SettingsDebugView.axaml.cs @@ -1,11 +1,4 @@ using Avalonia.Controls; -using Avalonia.Interactivity; -using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.Helpers; -using Ryujinx.Common.Configuration; -using Ryujinx.Common.Logging; -using System; -using System.IO; namespace Ryujinx.Ava.UI.Views.Settings { @@ -15,57 +8,5 @@ namespace Ryujinx.Ava.UI.Views.Settings { InitializeComponent(); } - - private async void PurgeAllSharedCaches_OnClick(object sender, RoutedEventArgs routedEventArgs) - { - var appList = RyujinxApp.MainWindow.ViewModel.Applications; - - if (appList.Count == 0) - { - return; - } - - UserResult result = await ContentDialogHelper.CreateConfirmationDialog( - LocaleManager.Instance[LocaleKeys.DialogWarning], - LocaleManager.Instance[LocaleKeys.DialogDeleteAllCaches], - LocaleManager.Instance[LocaleKeys.InputDialogYes], - LocaleManager.Instance[LocaleKeys.InputDialogNo], - LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); - bool hasErrors = false; - - if (result != UserResult.Yes) - { - return; - } - - foreach (var application in appList) - { - DirectoryInfo cacheDir = new(Path.Combine(AppDataManager.GamesDirPath, application.IdString, "cache")); - - if (!cacheDir.Exists) - { - continue; - } - - foreach (var finfo in cacheDir.EnumerateDirectories()) - { - try - { - finfo.Delete(true); - - } - catch (Exception ex) - { - Logger.Error?.Print(LogClass.Application, $"Failed to purge shader cache for {application.Name}({application.IdString}): {ex}"); - hasErrors = true; - } - } - } - - if (hasErrors) - { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogDeleteAllCachesErrorMessage]); - } - } } }