From b15a26c3d56aae0dfeed342a7ba5ecf5e22ff905 Mon Sep 17 00:00:00 2001
From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com>
Date: Mon, 23 Jun 2025 11:24:18 +0900
Subject: [PATCH] [bugfix] Plugins: Add error handling. when error occurred
while rendering a plugin, set status disabled and an error.
---
locales/en.yml | 3 +-
locales/ja.yml | 1 +
.../setting_box/plugins/Plugins.jsx | 7 +-
.../setting_box/plugins/Plugins.module.scss | 1 +
.../app/main_page/main_section/PluginHost.jsx | 28 ++++++--
.../SnackbarController.jsx | 4 +-
src-ui/logics/configs/plugins/usePlugins.js | 64 +++++++++++++------
7 files changed, 78 insertions(+), 30 deletions(-)
diff --git a/locales/en.yml b/locales/en.yml
index 9e133bed..05e5601d 100644
--- a/locales/en.yml
+++ b/locales/en.yml
@@ -270,7 +270,7 @@ config_page:
label: "WebSocket Port"
notifications:
- save_success: "Settings have been saved"
+ save_success: "Settings have been saved."
plugin_notifications:
downloading: Downloading the plugin.
@@ -282,6 +282,7 @@ plugin_notifications:
updated_error: Update failed.
disabled_out_of_support: The plugin has been disabled. It's not supported on this VRCT version.
+ disabled_due_to_an_error: "An error was detected while running the plugin. Please report this to the plugin developer."
is_enabled: The plugin has enabled.
is_disabled: The plugin has disabled.
\ No newline at end of file
diff --git a/locales/ja.yml b/locales/ja.yml
index b2ff2ad8..d36bec89 100644
--- a/locales/ja.yml
+++ b/locales/ja.yml
@@ -282,6 +282,7 @@ plugin_notifications:
updated_error: プラグインのアップデートに失敗しました。
disabled_out_of_support: 現在のバージョンとの互換性がありません。プラグインを無効にしました。
+ disabled_due_to_an_error: プラグイン実行中にエラーを検知しました。プラグイン開発者に報告してください。
is_enabled: プラグインを有効にしました。
is_disabled: プラグインを無効にしました。
\ No newline at end of file
diff --git a/src-ui/app/config_page/setting_section/setting_box/plugins/Plugins.jsx b/src-ui/app/config_page/setting_section/setting_box/plugins/Plugins.jsx
index aa4cdf75..6c80beb2 100644
--- a/src-ui/app/config_page/setting_section/setting_box/plugins/Plugins.jsx
+++ b/src-ui/app/config_page/setting_section/setting_box/plugins/Plugins.jsx
@@ -105,7 +105,12 @@ const PluginDownloadContainer = () => {
{plugin.is_error ? (
-
Error: {plugin.error_message}
+
+
{t(`plugin_notifications.${plugin.error_message_type}`)}
+
plugin_version: {plugin.downloaded_plugin_info.plugin_version}
+
min_supported_vrct_version: {plugin.downloaded_plugin_info.min_supported_vrct_version}
+
max_supported_vrct_version: {plugin.downloaded_plugin_info.max_supported_vrct_version}
+
) : (
{
+export const PluginHost = ({ render_components }) => {
+ const { setErrorPlugin } = usePlugins();
return (
<>
- {render_components
- .map((plugin, index) => {
- const PluginComponent = plugin.component;
- return PluginComponent ? : null;
- })}
+ {render_components.map((plugin, index) => {
+ const PluginComponent = plugin.component;
+ const plugin_id = plugin.plugin_id;
+
+ return PluginComponent ? (
+ null}
+ onError={(_error, _info) => {
+ // Disable the plugin on error
+ setErrorPlugin(plugin_id, "disabled_due_to_an_error");
+ }}
+ >
+
+
+ ) : null;
+ })}
>
);
};
\ No newline at end of file
diff --git a/src-ui/app/others/snackbar_controller/SnackbarController.jsx b/src-ui/app/others/snackbar_controller/SnackbarController.jsx
index fe692c10..60edac1f 100644
--- a/src-ui/app/others/snackbar_controller/SnackbarController.jsx
+++ b/src-ui/app/others/snackbar_controller/SnackbarController.jsx
@@ -69,14 +69,14 @@ export const SnackbarController = () => {
}, 100);
};
- setContainerKey(prevKey => prevKey + 1);
+ // setContainerKey(prevKey => prevKey + 1);
asyncShowNotification();
}, [settings]);
return (
{
});
};
- const toggleSavedPluginsStatus = (target_plugin_id) => {
- const successPluginNotification = (message) => showNotification_Success(message, {
- hide_duration: 1000,
- category_id: "to_enable_plugin"
- });
- const is_exists = currentSavedPluginsStatus.data.some(
+ const setSavedPluginEnabled = (target_plugin_id, is_enabled) => {
+ const notify = () => {
+ const msg_key = is_enabled
+ ? "plugin_notifications.is_enabled"
+ : "plugin_notifications.is_disabled";
+ showNotification_Success(t(msg_key), {
+ hide_duration: 1000,
+ category_id: "switch_enable_plugin",
+ });
+ }
+
+ const exists = currentSavedPluginsStatus.data.some(
(d) => d.plugin_id === target_plugin_id
);
+
let new_value = [];
- if (is_exists) {
+
+ if (exists) {
new_value = currentSavedPluginsStatus.data.map((d) => {
if (d.plugin_id === target_plugin_id) {
- d.is_enabled = !d.is_enabled;
- (d.is_enabled)
- ? successPluginNotification(t("plugin_notifications.is_enabled"))
- : successPluginNotification(t("plugin_notifications.is_disabled"));
+ d.is_enabled = is_enabled;
+ notify();
}
return d;
});
} else {
- new_value.push(...currentSavedPluginsStatus.data);
- new_value.push({
- plugin_id: target_plugin_id,
- is_enabled: true,
- });
- successPluginNotification(t("plugin_notifications.is_enabled"))
+ // 存在しない場合は追加
+ new_value = [
+ ...currentSavedPluginsStatus.data,
+ { plugin_id: target_plugin_id, is_enabled: is_enabled }
+ ];
+ notify();
}
- // 「currentPluginsData.data」でis_downloadedがtrueのものだけ残す
+ // ダウンロード済みプラグインのみ残す
new_value = new_value.filter((item) =>
currentPluginsData.data.some(
- (plugin) => plugin.plugin_id === item.plugin_id && plugin.is_downloaded
+ (p) => p.plugin_id === item.plugin_id && p.is_downloaded
)
);
setSavedPluginsStatus(new_value);
};
+ const toggleSavedPluginsStatus = (plugin_id) => {
+ // 現在の状態を探す(未登録なら false とみなす)
+ const current = currentSavedPluginsStatus.data.find(
+ (d) => d.plugin_id === plugin_id
+ )?.is_enabled ?? false;
+ setSavedPluginEnabled(plugin_id, !current);
+ };
// Init時の処理 非対応のものを無効化する際に、savedDPluginsStatusから不要なものを削除する処理が邪魔になるので該当コードを削除したバージョン。Init以外で使用する時にはリファクタが必要になる。
const setTargetSavedPluginsStatus_Init = (target_plugin_id, is_enabled) => {
@@ -380,6 +393,15 @@ export const usePlugins = () => {
showNotification_SaveSuccess();
};
+ const setErrorPlugin = (plugin_id, error_message_type) => {
+ const error_message = t("plugin_notifications.disabled_due_to_an_error");
+
+ setSavedPluginEnabled(plugin_id, false);
+ updateTargetPluginData(plugin_id, "is_error", true);
+ updateTargetPluginData(plugin_id, "error_message_type", error_message_type);
+ showNotification_Error(error_message);
+ };
+
return {
asyncFetchPluginsInfo,
@@ -406,11 +428,15 @@ export const usePlugins = () => {
currentLoadedPlugins,
updateLoadedPlugins,
+ setSavedPluginEnabled,
toggleSavedPluginsStatus,
setTargetSavedPluginsStatus_Init,
setSavedPluginsStatus,
+
handlePendingPlugin,
+
+ setErrorPlugin,
};
};