From 65ee75b49e50deb669ffbe2b17fc614978ad2b5f Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Wed, 12 Feb 2025 14:32:48 +0900 Subject: [PATCH 01/47] [Update/TMP] Add feature Scheduled message send. --- src-ui/app/main_page/MainPage.jsx | 2 + .../plugins_section/PluginsSection.jsx | 349 ++++++++++++++++++ .../PluginsSection.module.scss | 159 ++++++++ 3 files changed, 510 insertions(+) create mode 100644 src-ui/app/main_page/plugins_section/PluginsSection.jsx create mode 100644 src-ui/app/main_page/plugins_section/PluginsSection.module.scss diff --git a/src-ui/app/main_page/MainPage.jsx b/src-ui/app/main_page/MainPage.jsx index a83ef09a..324bc463 100644 --- a/src-ui/app/main_page/MainPage.jsx +++ b/src-ui/app/main_page/MainPage.jsx @@ -2,6 +2,7 @@ import clsx from "clsx"; import styles from "./MainPage.module.scss"; import { SidebarSection } from "./sidebar_section/SidebarSection"; import { MainSection } from "./main_section/MainSection"; +import { PluginsSection } from "./plugins_section/PluginsSection"; import { useIsOpenedConfigPage } from "@logics_common"; export const MainPage = () => { @@ -15,6 +16,7 @@ export const MainPage = () => {
| 番号 | +開始 | +終了 | +テキスト | +
|---|---|---|---|
| {cue.index} | +{formatTime(cue.startTime)} | +{formatTime(cue.endTime)} | +{cue.text} | +
+ ※ 行をクリックすると、その字幕の位置にジャンプします。(相対モードのみ) +
+Dev Plugin Count: {currentCountPluginState?.data?.count}
-1 Zipped Dev Plugin Count: {currentCountPluginState?.data?.count}
+1 Zipped Dev Plugin Count: {currentCountPluginState?.data?.count}
diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 6e6fca0c..b36e8ce4 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -36,11 +36,12 @@ "exists": true, "writeFile": true, "createDir": true, + "removeDir": true, "scope": ["$RESOURCE/**", "**/src-tauri/target/debug/plugins/**"] }, "http": { "request": true, - "scope": ["https://api.github.com/repos/**", "https://github.com/**"] + "scope": ["https://api.github.com/repos/**", "https://github.com/**", "https://raw.githubusercontent.com/ShiinaSakamoto/vrct_plugins_list/main/vrct_plugins_list.json"] }, "shell": { "all": false, diff --git a/src-ui/app/_app_controllers/PluginsController.jsx b/src-ui/app/_app_controllers/PluginsController.jsx index 6ccc231b..82abb5d2 100644 --- a/src-ui/app/_app_controllers/PluginsController.jsx +++ b/src-ui/app/_app_controllers/PluginsController.jsx @@ -1,10 +1,9 @@ -import { useEffect } from "react"; import { usePlugins } from "@logics_configs"; -// ホスト側でReactやjotaiをグローバル変数として提供 -import ReactModule from "react"; + +import React, { useEffect } from "react"; if (typeof window !== "undefined") { - window.React = ReactModule; + window.React = React; } export const PluginsController = () => { 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 954e4b33..e290f292 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 @@ -1,6 +1,12 @@ import React, { useState, useEffect } from "react"; +import semver from "semver"; import { usePlugins } from "@logics_configs"; import styles from "./Plugins.module.scss"; +import { fetch as tauriFetch, ResponseType } from "@tauri-apps/api/http"; + +const MAIN_VRCT_VERSION = "3.0.5"; +// PLUGIN_LIST_URL は中央リポジトリにある、各プラグインの plugin_info.json への URL の配列を保持する JSON の URL +const PLUGIN_LIST_URL = "https://raw.githubusercontent.com/ShiinaSakamoto/vrct_plugins_list/main/vrct_plugins_list.json"; export const Plugins = () => { return ( @@ -13,26 +19,45 @@ export const Plugins = () => { const PluginDownloadContainer = () => { const [plugin_list, set_plugin_list] = useState([]); const [download_progress, set_download_progress] = useState({}); - const { downloadAndExtractPlugin } = usePlugins(); useEffect(() => { - // GitHub上のJSONファイルからプラグインリストを取得 - const fetchPluginList = async () => { + async function asyncFetchPluginInfoList() { try { - const response = await fetch( - "https://raw.githubusercontent.com/ShiinaSakamoto/vrct_plugins_list/main/vrct_plugins_list.json" - ); - if (!response.ok) { - throw new Error("Failed to fetch plugin list"); + // tauriFetch を使用して vrct_plugins_list.json を取得(CORS 対策) + const response = await tauriFetch(PLUGIN_LIST_URL, { + method: "GET", + responseType: ResponseType.Json, + headers: { "Cache-Control": "no-cache" } + }); + if (response.status !== 200) { + throw new Error("Failed to fetch plugin list, status: " + response.status); } - const data = await response.json(); - set_plugin_list(data); + // 取得される plugin_list.json は各プラグインの plugin_info.json への raw URL の配列とする + const plugins_data = response.data; + const updated_list = await Promise.all( + plugins_data.map(async (plugin_data) => { + try { + const plugin_manifest = await asyncFetchPluginManifest(plugin_data.url); + return { ...plugin_manifest }; + } catch (error) { + console.error("Error fetching manifest for URL:", plugin_data.url, error); + // エラー発生時は、plugin_data.title とエラーメッセージを返す + return { + title: plugin_data.title, + plugin_id: plugin_data.plugin_id || plugin_data.title, + error: error.message, + url: plugin_data.url + }; + } + }) + ); + set_plugin_list(updated_list); } catch (error) { - console.error("Error fetching plugin list:", error); + console.error("Error fetching plugin info list:", error); } - }; - fetchPluginList(); + } + asyncFetchPluginInfoList(); }, []); const handleDownload = async (plugin) => { @@ -44,14 +69,24 @@ const PluginDownloadContainer = () => { {plugin_list.map((plugin) => (Error: {plugin.error}
+ ) : ( + <> +Version: {plugin.plugin_version}
++ Compatible: {plugin.min_compatible_version} ~ {plugin.max_compatible_version} +
+{`${Math.round(option.progress)}%`}
+ > + ); + case option.is_pending: + return{t("config_page.model_download_button_label")}
+{`${Math.round(option.progress)}%`}
- > - ); - case option.is_pending: - return{t("config_page.model_download_button_label")}
-{plugin.title}
+{plugin.plugin_id}
{plugin.error ? (Error: {plugin.error}
) : ( - <> -Version: {plugin.plugin_version}
-- Compatible: {plugin.min_compatible_version} ~ {plugin.max_compatible_version} -
-Version: {plugin.plugin_version}
++ Compatible: {plugin.min_supported_vrct_version} ~ {plugin.max_supported_vrct_version} +
+{plugin.title}
{plugin.plugin_id}
@@ -113,9 +93,10 @@ const PluginDownloadContainer = () => { Compatible: {plugin.min_supported_vrct_version} ~ {plugin.max_supported_vrct_version}1 Zipped Dev Plugin Count: {currentCountPluginState?.data?.count}
-{t("config_page.model_download_button_label")}
); + case option.update_button: + return ( +Update
+Version: {plugin.plugin_version}
+Downloaded Version: {plugin.downloaded_plugin_version}
+Latest Version: {plugin.latest_plugin_version}
Compatible: {plugin.min_supported_vrct_version} ~ {plugin.max_supported_vrct_version}
diff --git a/src-ui/logics/configs/plugins/usePlugins.js b/src-ui/logics/configs/plugins/usePlugins.js index 9031bc57..22137654 100644 --- a/src-ui/logics/configs/plugins/usePlugins.js +++ b/src-ui/logics/configs/plugins/usePlugins.js @@ -47,17 +47,19 @@ export const usePlugins = () => { return console.error("An invalid plugin was detected.", plugin_info.plugin_id, plugin_info.location, component); } updatePluginsData(prev => { - const is_already_registered = prev.data.some(old_value => old_value.plugin_id === plugin_info.plugin_id); - const new_value = prev.data.map(old_value => old_value.plugin_id === plugin_info.plugin_id - ? { ...old_value, ...plugin_info, location: plugin_info.location, component, is_downloaded: true } - : old_value + ? { + ...old_value, + ...plugin_info, + downloaded_plugin_version: plugin_info.plugin_version, + component: component, + is_downloaded: true, + is_latest_version_available: false, + } : old_value ); - return is_already_registered - ? new_value - : [...new_value, { plugin_id: plugin_info.plugin_id, location: plugin_info.location, component, is_downloaded: true }]; + return new_value; }); }, createAtomWithHook: (...args) => createAtomWithHook(...args), From 7e637b795d627300aafbb6b7b7f0a409d6f419da Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Wed, 9 Apr 2025 17:29:31 +0900 Subject: [PATCH 22/47] [Update/Refactor/bugfix] Update: Add functions and test ui. Update, backend: send latest vrct version to frontend. Refactor: Change the plugins data structure. bugfix: fix endless showing update button. --- src-python/controller.py | 6 +- src-python/mainloop.py | 2 +- src-python/model.py | 6 +- .../_app_controllers/PluginsController.jsx | 72 +++++---- .../PluginsControlComponent.jsx | 145 +++++++++++++++--- .../setting_box/plugins/Plugins.jsx | 81 +++++----- .../version_label/VersionLabel.jsx | 3 +- .../main_page/main_section/MainSection.jsx | 2 +- .../RightSideComponents.jsx | 6 +- .../update_modal/UpdateModal.jsx | 35 ++++- src-ui/logics/common/index.js | 2 +- .../common/useIsSoftwareUpdateAvailable.js | 10 -- src-ui/logics/common/useSoftwareVersion.js | 40 +++++ src-ui/logics/configs/index.js | 4 +- src-ui/logics/configs/plugins/usePlugins.js | 138 ++++++++++++----- src-ui/logics/configs/useSoftwareVersion.js | 18 --- src-ui/logics/useReceiveRoutes.js | 7 +- src-ui/store.js | 7 +- 18 files changed, 404 insertions(+), 180 deletions(-) delete mode 100644 src-ui/logics/common/useIsSoftwareUpdateAvailable.js create mode 100644 src-ui/logics/common/useSoftwareVersion.js delete mode 100644 src-ui/logics/configs/useSoftwareVersion.js diff --git a/src-python/controller.py b/src-python/controller.py index 02ba5e34..faa659b2 100644 --- a/src-python/controller.py +++ b/src-python/controller.py @@ -447,11 +447,11 @@ class Controller: return {"status":200, "result":config.VERSION} def checkSoftwareUpdated(self) -> dict: - update_flag = model.checkSoftwareUpdated() + software_update_info = model.checkSoftwareUpdated() self.run( 200, - self.run_mapping["update_software_flag"], - update_flag, + self.run_mapping["software_update_info"], + software_update_info, ) @staticmethod diff --git a/src-python/mainloop.py b/src-python/mainloop.py index edd5356a..5c5fb744 100644 --- a/src-python/mainloop.py +++ b/src-python/mainloop.py @@ -38,7 +38,7 @@ run_mapping = { "mic_device_list":"/run/mic_device_list", "speaker_device_list":"/run/speaker_device_list", - "update_software_flag":"/run/update_software_flag", + "software_update_info":"/run/software_update_info", "initialization_progress":"/run/initialization_progress", "initialization_complete":"/run/initialization_complete", diff --git a/src-python/model.py b/src-python/model.py index f393314d..afe0d565 100644 --- a/src-python/model.py +++ b/src-python/model.py @@ -320,6 +320,7 @@ class Model: def checkSoftwareUpdated(): # check update update_flag = False + version = "" try: response = requests_get(config.GITHUB_URL) json_data = response.json() @@ -331,7 +332,10 @@ class Model: update_flag = True except Exception: errorLogging() - return update_flag + return { + "is_update_available": update_flag, + "new_version": version, + } @staticmethod def updateSoftware(): diff --git a/src-ui/app/_app_controllers/PluginsController.jsx b/src-ui/app/_app_controllers/PluginsController.jsx index ec181bb9..2fad4376 100644 --- a/src-ui/app/_app_controllers/PluginsController.jsx +++ b/src-ui/app/_app_controllers/PluginsController.jsx @@ -14,6 +14,7 @@ export const PluginsController = ({ fetchPluginsHasRunRef }) => { currentPluginsData, updatePluginsData, currentSavedPluginsStatus, + updateIsPluginsInitialized, } = usePlugins(); useEffect(() => { @@ -26,40 +27,55 @@ export const PluginsController = ({ fetchPluginsHasRunRef }) => { const info_map = new Map(info_array.map(info => [info.plugin_id, info])); const prev_map = new Map(prev.data.map(item => [item.plugin_id, item])); - // info_array にある各アイテムについて、prev.data に同じ plugin_id があればマージ - const merged = info_array.map(info => { - if (prev_map.has(info.plugin_id)) { - return { - ...info, - latest_plugin_version: info.plugin_version, - ...prev_map.get(info.plugin_id), + const new_data = []; + for (const info of info_array) { + let new_plugin_info = {}; + if (prev_map.has(info.plugin_id)) { // plugin_id 登録済み + const target_downloaded_plugin = prev_map.get(info.plugin_id); + if (target_downloaded_plugin.is_downloaded) { // 既にダウンロード済み + const is_latest_version_available = !(target_downloaded_plugin.plugin_version === info.plugin_version); + + new_plugin_info = { + is_downloaded: true, + is_latest_version_already: (target_downloaded_plugin.downloaded_plugin_info?.plugin_version === info.plugin_version), + is_latest_version_available: is_latest_version_available, + latest_plugin_info: { ...info }, + ...target_downloaded_plugin, + }; + } else { // infoにもあり登録済みだがダウンロードされていない + new_plugin_info = { + is_downloaded: false, + is_latest_version_already: false, + is_latest_version_available: info.is_latest_version_available, + latest_plugin_info: { ...info }, + ...target_downloaded_plugin, + } + } + } else { // 未ダウンロード + new_plugin_info = { + plugin_id: info.plugin_id, + is_downloaded: false, + is_latest_version_already: false, + latest_plugin_info: { ...info }, }; } - return { - ...info, - latest_plugin_version: info.plugin_version, - }; - }); + new_data.push(new_plugin_info); + } // prev.data にのみ存在するアイテム = latest plugin infoには存在しない // を追加し、is_outdated: true を付与 prev.data.forEach(item => { if (!info_map.has(item.plugin_id)) { - merged.push({ ...item, is_outdated: true }); + new_data.push({ ...item, is_outdated: true }); } }); - let new_value = []; - for (const plugin of merged) { - if (plugin.downloaded_plugin_version !== plugin.latest_plugin_version && plugin.is_plugin_supported) { - plugin.is_latest_version_available = true; - } else { - plugin.is_latest_version_available = false; + new_data.forEach(plugin => { + if (!plugin.is_outdated) { + plugin.is_latest_version_available = (plugin.latest_plugin_info.is_plugin_supported); } - new_value.push(plugin); - } - - return new_value; + }); + return new_data; }); } catch (error) { console.error(error); @@ -68,6 +84,7 @@ export const PluginsController = ({ fetchPluginsHasRunRef }) => { if (!fetchPluginsHasRunRef.current) { loadPlugins(); + updateIsPluginsInitialized(true); } return () => fetchPluginsHasRunRef.current = true; }, []); @@ -76,13 +93,13 @@ export const PluginsController = ({ fetchPluginsHasRunRef }) => { useEffect(() => { updatePluginsData(prev => { // currentSavedPluginsStatus.data の各要素を Map 化して plugin_id で参照 - const savedMap = new Map(currentSavedPluginsStatus.data.map(saved => [saved.plugin_id, saved])); + const saved_map = new Map(currentSavedPluginsStatus.data.map(saved => [saved.plugin_id, saved])); const prev_map = new Map(prev.data.map(item => [item.plugin_id, item])); - // prev.data にある各アイテムについて、保存済みの状態情報があればマージ const merged = prev.data.map(item => { - if (savedMap.has(item.plugin_id)) { - return { ...item, is_enabled: savedMap.get(item.plugin_id).is_enabled }; + + if (saved_map.has(item.plugin_id)) { + return { ...item, is_enabled: saved_map.get(item.plugin_id).is_enabled }; } return item; }); @@ -93,7 +110,6 @@ export const PluginsController = ({ fetchPluginsHasRunRef }) => { merged.push({ plugin_id: saved.plugin_id, is_enabled: saved.is_enabled }); } }); - return merged; }); }, [currentSavedPluginsStatus]); diff --git a/src-ui/app/config_page/setting_section/setting_box/_components/plugins_control_component/PluginsControlComponent.jsx b/src-ui/app/config_page/setting_section/setting_box/_components/plugins_control_component/PluginsControlComponent.jsx index a8f70b73..0fd7c33a 100644 --- a/src-ui/app/config_page/setting_section/setting_box/_components/plugins_control_component/PluginsControlComponent.jsx +++ b/src-ui/app/config_page/setting_section/setting_box/_components/plugins_control_component/PluginsControlComponent.jsx @@ -1,31 +1,136 @@ +import React from "react"; import { SwitchBox } from "../index"; import { _DownloadButton } from "../_atoms/_download_button/_DownloadButton"; import styles from "./PluginsControlComponent.module.scss"; -export const PluginsControlComponent = ({ variable_state, plugin_status, toggleFunction, downloadStartFunction }) => { - const { plugin_id, is_pending, is_downloaded, is_enabled, is_latest_version_available, is_plugin_supported, is_outdated } = plugin_status; - +// メインのコントロールコンポーネント。ダウンロード済み / 未ダウンロードで分岐して表示する +export const PluginsControlComponent = ({ + variable_state, + plugin_status, + toggleFunction, + downloadStartFunction, +}) => { + // 共通オプション(各子コンポーネントに引き回す情報) const option = { - id: plugin_id, - is_pending: is_pending, - is_downloaded: is_downloaded, - data: is_enabled, - update_button: is_downloaded && is_latest_version_available, + id: plugin_status.plugin_id, + is_pending: plugin_status.is_pending, + is_downloaded: plugin_status.is_downloaded, + data: plugin_status.is_enabled, + update_button: plugin_status.is_downloaded && plugin_status.is_latest_version_available, state: variable_state, progress: null, }; - const togglePlugin = () => toggleFunction(plugin_id); - const is_turn_on_able = is_downloaded && (is_plugin_supported || is_outdated); + if (plugin_status.is_downloaded) { + return ( +{title}
+現在のバージョン: {current_version}
+最新版を使用中
+{title}
+現在のバージョン: {current_version}
+最新版を利用可能
<_DownloadButton option={option} downloadStartFunction={downloadStartFunction} /> - ) : ( -{title}
+現在のバージョン: {current_version}
+{desc}
+{title}
+現在のバージョン: {current_version}
+最新バージョン: {latest_version}
+ <_DownloadButton option={option} downloadStartFunction={downloadStartFunction} /> +{title}
+現在のバージョン: {current_version}
+最新バージョン: {latest_version}
+現在利用不可
+{plugin.title}
++ {plugin.is_downloaded + ? plugin.downloaded_plugin_info?.title || plugin.latest_plugin_info.title + : plugin.latest_plugin_info.title} +
{plugin.plugin_id}
{plugin.error ? (Error: {plugin.error}
) : (Downloaded Version: {plugin.downloaded_plugin_version}
-Latest Version: {plugin.latest_plugin_version}
+ {/* 状態に応じた情報表示(例:バージョン等) */}- Compatible: {plugin.min_supported_vrct_version} ~ {plugin.max_supported_vrct_version} + {plugin.is_downloaded + ? `現在のバージョン: ${plugin.downloaded_plugin_info?.plugin_version}` + : `最新バージョン: ${plugin.latest_plugin_info.plugin_version}`}
{t("update_modal.is_latest_version_already")}
; } return{t("update_modal.is_current_compute_device")}
; +}; + +const PluginUpdateNotification = () => { + const { enabledPluginsList } = usePlugins(); + + const incompatible_plugins_list = enabledPluginsList(); + + return ( +{plugin.title}
+ })} +An error occurred. Please restart VRCT or contact the developers.
+ {error ? ++ {formatted_stack} +
+Copy
+ {is_copied + ?{text}
+ + ); +}; \ No newline at end of file diff --git a/src-ui/app/error_boundary/contacts_container/ContactsContainer.module.scss b/src-ui/app/error_boundary/contacts_container/ContactsContainer.module.scss new file mode 100644 index 00000000..5e291d0f --- /dev/null +++ b/src-ui/app/error_boundary/contacts_container/ContactsContainer.module.scss @@ -0,0 +1,28 @@ +.container { + display: flex; + gap: 3.2rem; +} + +.github_issues, .google_forms { + display: flex; + flex-direction: column; + align-items: center; + width: 100%; + height: 100%; + padding: 1rem; + border-radius: 0.4rem; + gap: 1rem; + &:hover { + background-color: var(--dark_800_color); + } + &:active { + background-color: var(--dark_900_color) + } +} +.contact_button_icon { + width: 5.2rem; +} +.contact_button_label { + font-size: 1.4rem; + white-space: nowrap; +} \ No newline at end of file diff --git a/src-ui/assets/document.png b/src-ui/assets/document.png new file mode 100644 index 0000000000000000000000000000000000000000..cfe54e2d0491e01096a2f12c92b9242031399d1b GIT binary patch literal 1126 zcmeAS@N?(olHy`uVBq!ia0vp^A3&Ic4M^IBzMKT4I14-?iy0XBj({-ZRBb+K1_l-h zPZ!6Kid%2*TIVUdi#S}IcyLBz(AqP{title}
-現在のバージョン: {current_version}
+最新のバージョン: {latest_version}
最新版を使用中
{title}
-現在のバージョン: {current_version}
+最新のバージョン: {latest_version}
最新版を利用可能
<_DownloadButton option={option} downloadStartFunction={downloadStartFunction} />{title}
-現在のバージョン: {current_version}
-{desc}
+最新のバージョン: {latest_version}
{title}
-現在のバージョン: {current_version}
最新バージョン: {latest_version}
<_DownloadButton option={option} downloadStartFunction={downloadStartFunction} />{title}
-現在のバージョン: {current_version}
最新バージョン: {latest_version}
現在利用不可
{plugin.is_downloaded - ? plugin.downloaded_plugin_info?.title || plugin.latest_plugin_info.title - : plugin.latest_plugin_info.title} + ? plugin.downloaded_plugin_info?.title + : plugin.latest_plugin_info?.title}
{plugin.plugin_id}
- {plugin.error ? ( -Error: {plugin.error}
+ {plugin.is_error ? ( +Error: {plugin.error_message}
) : ({plugin.is_downloaded ? `現在のバージョン: ${plugin.downloaded_plugin_info?.plugin_version}` - : `最新バージョン: ${plugin.latest_plugin_info.plugin_version}`} + : null}
現在利用不可 使用中VRCTバージョンとの互換性なし
+最新のバージョン: {latest_version}
@@ -72,7 +79,7 @@ const DownloadedPluginControl = ({ } else { return (最新のバージョン: {latest_version}
+最新版は現在利用不可
最新のバージョン: {latest_version}
+VRCT最新版で利用可能
+最新のバージョン: {latest_version}
+最新版にアップデート後 利用可能
+ <_DownloadButton option={option} downloadStartFunction={downloadStartFunction} /> +現在利用不可 使用中VRCTバージョンとの互換性なし
最新情報が取得できません
+{plugin.title}
+ const target_data = plugin.downloaded_plugin_info; + return{target_data.title}
})}{t("update_modal.download_latest_and_restart")}
+{t("update_modal.download_latest_and_restart")}
+{t("update_modal.is_latest_version_already")}
; } return{t("update_modal.is_current_compute_device")}
; -}; - -const PluginUpdateNotification = () => { - const { enabledPluginsList } = usePlugins(); - - // ダウンロード済みのもの or プラグイン最新版が、VRCT最新版(VRCTアプデ後)に非対応のもの - const incompatible_plugins_list = enabledPluginsList().filter(plugin => { - if (!plugin.is_downloaded) return false; - if (!plugin.downloaded_plugin_info?.is_plugin_supported_latest_vrct || !plugin.latest_plugin_info.is_plugin_supported_latest_vrct) return true; - }); - - return ( -{target_data.title}
- })} -使用中プラグインの互換性チェック
+VRCT最新バージョンで互換性のないプラグインはアップデート後に無効化されます。引き続き使用したい場合は、各プラグインの更新を待ってください。
+{target_data.title}
+ {is_compatible + ?{target_data.title}
diff --git a/src-ui/logics/configs/plugins/usePlugins.js b/src-ui/logics/configs/plugins/usePlugins.js index 80e7e717..2e92ef74 100644 --- a/src-ui/logics/configs/plugins/usePlugins.js +++ b/src-ui/logics/configs/plugins/usePlugins.js @@ -1,5 +1,5 @@ import { invoke } from "@tauri-apps/api/tauri"; -import { IS_PLUGIN_DEV_MODE, getPluginsList } from "@ui_configs"; +import { IS_PLUGIN_PATH_DEV_MODE, getPluginsList } from "@ui_configs"; import { createAtomWithHook, useStore_SavedPluginsStatus, @@ -110,7 +110,7 @@ export const usePlugins = () => { }; const asyncLoadAllPlugins = async () => { - if (IS_PLUGIN_DEV_MODE) { + if (IS_PLUGIN_PATH_DEV_MODE) { imported_dev_plugins.forEach(({ index, downloaded_plugin_info }) => { if (!index || !downloaded_plugin_info) { console.error("Invalid development plugin detected", index, downloaded_plugin_info); diff --git a/src-ui/ui_configs.js b/src-ui/ui_configs.js index 6db3193f..6b8d0031 100644 --- a/src-ui/ui_configs.js +++ b/src-ui/ui_configs.js @@ -52,15 +52,20 @@ export const ui_configs = { ] }; -export const IS_PLUGIN_DEV_MODE = false; -if (IS_PLUGIN_DEV_MODE) console.warn("ui_configs IS_PLUGIN_DEV_MODE: true. Turn to 'false' when it's production environment."); +// true: src-ui\plugins false: src-tauri\target\debug\plugins +export const IS_PLUGIN_PATH_DEV_MODE = false; + +// true: dev_vrct_plugins_list.json false: vrct_plugins_list.json +export const IS_PLUGIN_LIST_URL_DEV_MODE = false; + export const getPluginsList = () => { const base_url = "https://raw.githubusercontent.com/ShiinaSakamoto/vrct_plugins_list/main/"; - const plugins_list_url = (IS_PLUGIN_DEV_MODE) - ? base_url + "dev_vrct_plugins_list.json" - : base_url + "vrct_plugins_list.json"; + const plugins_list_url = (IS_PLUGIN_LIST_URL_DEV_MODE) + ? base_url + "dev_vrct_plugins_list.json" + : base_url + "vrct_plugins_list.json"; return plugins_list_url; }; +if (IS_PLUGIN_PATH_DEV_MODE || IS_PLUGIN_LIST_URL_DEV_MODE) console.warn("ui_configs IS_PLUGIN_PATH_DEV_MODE or IS_PLUGIN_LIST_URL_DEV_MODE is true. Turn to 'false' when it's production environment."); export const translator_status = [ { id: "DeepL", label: "DeepL", is_available: false }, From fd59c0b28ff9aaace218010dc025ba9a1047cd9b Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Thu, 17 Apr 2025 19:44:14 +0900 Subject: [PATCH 32/47] [Update/Refactor] Automatically disable and save the status to config.json if the plugin is not supported. --- .../MergePluginsController.jsx | 2 ++ .../setting_box/plugins/Plugins.jsx | 31 ++----------------- src-ui/logics/configs/plugins/usePlugins.js | 29 +++++++++++++++++ 3 files changed, 33 insertions(+), 29 deletions(-) diff --git a/src-ui/app/_app_controllers/plugins_controllers/MergePluginsController.jsx b/src-ui/app/_app_controllers/plugins_controllers/MergePluginsController.jsx index c4545bc3..e0e258b7 100644 --- a/src-ui/app/_app_controllers/plugins_controllers/MergePluginsController.jsx +++ b/src-ui/app/_app_controllers/plugins_controllers/MergePluginsController.jsx @@ -10,6 +10,7 @@ export const MergePluginsController = () => { currentFetchedPluginsInfo, currentSavedPluginsStatus, downloadAndExtractPlugin, + toggleSavedPluginStatus, } = usePlugins(); const { checkVrctVerCompatibility } = useSoftwareVersion(); @@ -129,6 +130,7 @@ export const MergePluginsController = () => { !plugin.latest_plugin_info?.is_plugin_supported ) { plugin.is_enabled = false; + toggleSavedPluginStatus(plugin.plugin_id); } } }); 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 9f7f490e..e60927f4 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 @@ -22,9 +22,8 @@ const PluginDownloadContainer = () => { const { downloadAndExtractPlugin, currentPluginsData, - updatePluginsData, currentSavedPluginsStatus, - setSavedPluginsStatus, + toggleSavedPluginStatus, handlePendingPlugin, } = usePlugins(); @@ -42,33 +41,7 @@ const PluginDownloadContainer = () => { // プラグインのオンオフ切り替え処理 const toggleFunction = (target_plugin_id) => { - const is_exists = currentSavedPluginsStatus.data.some( - (d) => d.plugin_id === target_plugin_id - ); - let new_value = []; - if (is_exists) { - new_value = currentSavedPluginsStatus.data.map((d) => { - if (d.plugin_id === target_plugin_id) { - d.is_enabled = !d.is_enabled; - } - return d; - }); - } else { - new_value.push(...currentSavedPluginsStatus.data); - new_value.push({ - plugin_id: target_plugin_id, - is_enabled: true, - }); - } - - // 「currentPluginsData.data」でis_downloadedがtrueのものだけ残す - new_value = new_value.filter((item) => - currentPluginsData.data.some( - (plugin) => plugin.plugin_id === item.plugin_id && plugin.is_downloaded - ) - ); - - setSavedPluginsStatus(new_value); + toggleSavedPluginStatus(target_plugin_id); }; const variable_state = currentSavedPluginsStatus.state; diff --git a/src-ui/logics/configs/plugins/usePlugins.js b/src-ui/logics/configs/plugins/usePlugins.js index 2e92ef74..53db0c0b 100644 --- a/src-ui/logics/configs/plugins/usePlugins.js +++ b/src-ui/logics/configs/plugins/usePlugins.js @@ -298,7 +298,35 @@ export const usePlugins = () => { }); }; + const toggleSavedPluginStatus = (target_plugin_id) => { + const is_exists = currentSavedPluginsStatus.data.some( + (d) => d.plugin_id === target_plugin_id + ); + let new_value = []; + if (is_exists) { + new_value = currentSavedPluginsStatus.data.map((d) => { + if (d.plugin_id === target_plugin_id) { + d.is_enabled = !d.is_enabled; + } + return d; + }); + } else { + new_value.push(...currentSavedPluginsStatus.data); + new_value.push({ + plugin_id: target_plugin_id, + is_enabled: true, + }); + } + // 「currentPluginsData.data」でis_downloadedがtrueのものだけ残す + new_value = new_value.filter((item) => + currentPluginsData.data.some( + (plugin) => plugin.plugin_id === item.plugin_id && plugin.is_downloaded + ) + ); + + setSavedPluginsStatus(new_value); + }; const setSavedPluginsStatus = (plugins_status) => { pendingSavedPluginsStatus(); @@ -344,6 +372,7 @@ export const usePlugins = () => { currentLoadedPlugins, updateLoadedPlugins, + toggleSavedPluginStatus, setSavedPluginsStatus, handlePendingPlugin, From 9ef56db2dd70d000b256ab410e45edfb9ee176f4 Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Fri, 18 Apr 2025 00:10:09 +0900 Subject: [PATCH 33/47] [Update] Add safety that prevent to show the title Plugin compatibility list unnecessary. Remove the test code that is for showing the update modal. --- .../PluginCompatibilityList.jsx | 10 +++++++--- src-ui/logics/useReceiveRoutes.js | 8 +------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src-ui/app/modal_controller/update_modal/plugins_compatibility_list/PluginCompatibilityList.jsx b/src-ui/app/modal_controller/update_modal/plugins_compatibility_list/PluginCompatibilityList.jsx index 3591f962..d460b104 100644 --- a/src-ui/app/modal_controller/update_modal/plugins_compatibility_list/PluginCompatibilityList.jsx +++ b/src-ui/app/modal_controller/update_modal/plugins_compatibility_list/PluginCompatibilityList.jsx @@ -10,18 +10,22 @@ export const PluginCompatibilityList = () => { // ダウンロード済みのもの const downloaded_plugin = enabledPluginsList().filter(p => p.is_downloaded); - // プラグイン最新版が、VRCT最新版(VRCTアプデ後)に非対応のもの const compatible_plugins_list = []; const incompatible_plugins_list = []; for (const p of downloaded_plugin) { if (!p.downloaded_plugin_info?.is_plugin_supported_latest_vrct || !p.latest_plugin_info?.is_plugin_supported_latest_vrct) { + // プラグイン最新版でも、VRCT最新版(VRCTアプデ後)に非対応のもの incompatible_plugins_list.push(p); } else { + // 現プラグイン or 最新版が、VRCT最新版(VRCTアプデ後)に対応しているもの compatible_plugins_list.push(p); } } - const is_any_compatible_plugin = incompatible_plugins_list.length > 0; + const is_any_incompatible_plugin = incompatible_plugins_list.length > 0; + const is_any_compatible_plugin = compatible_plugins_list.length > 0; + + if (!is_any_incompatible_plugin && !is_any_compatible_plugin) return null; // This is just for safety. return (VRCT最新バージョンで互換性のないプラグインはアップデート後に無効化されます。引き続き使用したい場合は、各プラグインの更新を待ってください。
diff --git a/src-ui/logics/useReceiveRoutes.js b/src-ui/logics/useReceiveRoutes.js index fb826f8c..b73fe62e 100644 --- a/src-ui/logics/useReceiveRoutes.js +++ b/src-ui/logics/useReceiveRoutes.js @@ -206,13 +206,7 @@ export const useReceiveRoutes = () => { "/set/data/main_window_geometry": () => {}, "/run/open_filepath_logs": () => console.log("Opened Directory, Message Logs"), "/run/open_filepath_config_file": () => console.log("Opened Directory, Config File"), - "/run/software_update_info": () => { - updateLatestSoftwareVersionInfo({ - is_update_available: true, - new_version: "3.0.3", - }) - }, - // "/run/software_update_info": updateLatestSoftwareVersionInfo, + "/run/software_update_info": updateLatestSoftwareVersionInfo, "/run/connected_network": handleNetworkConnection, // Main Page From 01b7d6c94581d647b2b6c6827907957c8700222b Mon Sep 17 00:00:00 2001 From: Sakamoto Shiina <68018796+ShiinaSakamoto@users.noreply.github.com> Date: Fri, 18 Apr 2025 00:38:31 +0900 Subject: [PATCH 34/47] [Update] Plugins: Sort plugins list and remain the order of it. --- .../setting_section/setting_box/plugins/Plugins.jsx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) 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 e60927f4..2a02a4b0 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 @@ -17,7 +17,6 @@ export const Plugins = () => { ); }; - const PluginDownloadContainer = () => { const { downloadAndExtractPlugin, @@ -46,9 +45,14 @@ const PluginDownloadContainer = () => { const variable_state = currentSavedPluginsStatus.state; + // plugin_id で ABC 順にソート + const sorted_plugins_data = [...currentPluginsData.data].sort((a, b) => + a.plugin_id.localeCompare(b.plugin_id) + ); + return ({plugin.is_downloaded @@ -79,4 +83,4 @@ const PluginDownloadContainer = () => { ))}
Failed to fetch plugins data
} + {is_fetching &&Fetching plugins data...
} {sorted_plugins_data.map((plugin) => (diff --git a/src-ui/app/modal_controller/update_modal/plugins_compatibility_list/PluginCompatibilityList.jsx b/src-ui/app/modal_controller/update_modal/plugins_compatibility_list/PluginCompatibilityList.jsx index dd0133b1..e23c320c 100644 --- a/src-ui/app/modal_controller/update_modal/plugins_compatibility_list/PluginCompatibilityList.jsx +++ b/src-ui/app/modal_controller/update_modal/plugins_compatibility_list/PluginCompatibilityList.jsx @@ -9,6 +9,7 @@ export const PluginCompatibilityList = () => { const { enabledPluginsList, asyncFetchPluginsInfo, + currentFetchedPluginsInfo, } = usePlugins(); useEffect(() => { @@ -35,9 +36,15 @@ export const PluginCompatibilityList = () => { if (!is_any_incompatible_plugin && !is_any_compatible_plugin) return null; // This is just for safety. + // Duplicate + const is_failed_to_fetch = currentFetchedPluginsInfo.state === "error"; + const is_fetching = currentFetchedPluginsInfo.state === "pending"; + return (
使用中プラグインの互換性チェック
+ {is_failed_to_fetch &&Failed to fetch plugins data
} + {is_fetching &&Fetching plugins data...
}Failed to fetch plugins data
} {is_fetching &&Fetching plugins data...
} - {sorted_plugins_data.map((plugin) => ( -- {plugin.is_downloaded - ? plugin.downloaded_plugin_info?.title - : plugin.latest_plugin_info?.title} -
-{plugin.plugin_id}
- {plugin.is_error ? ( -Error: {plugin.error_message}
- ) : ( -- {plugin.is_downloaded - ? `現在のバージョン: ${plugin.downloaded_plugin_info?.plugin_version}` - : null} -
+ {sorted_plugins_data.map((plugin) => { + const target_info = plugin.is_downloaded + ? plugin.downloaded_plugin_info + : plugin.latest_plugin_info; + + const target_locale = target_info.locales && target_info.locales[i18n.language] + ? target_info.locales[i18n.language] + : { + title: target_info.title, + desc: target_info.desc || null, + }; + + return ( ++ {target_locale.title} +
+{plugin.plugin_id}
++ {target_locale.desc} +
+ {plugin.is_error ? ( +Error: {plugin.error_message}
+ ) : ( ++ {plugin.is_downloaded + ? `現在のバージョン: ${plugin.downloaded_plugin_info?.plugin_version}` + : null} +
+最新のバージョン: {latest_version}
-最新版にアップデート後 利用可能
+{downloaded_version_label}
+{latest_version_label}
+{t("config_page.plugins.available_after_updating")}
<_DownloadButton option={option} downloadStartFunction={downloadStartFunction} />現在利用不可 使用中VRCTバージョンとの互換性なし
+{t("config_page.plugins.unavailable_downloaded")}
最新情報が取得できません
+{t("config_page.plugins.no_latest_info")}
最新のバージョン: {latest_version}
-最新版を使用中
+{latest_version_label}
+{t("config_page.plugins.using_latest_version")}
最新のバージョン: {latest_version}
-最新版を利用可能
+{latest_version_label}
+{t("config_page.plugins.available_latest_version")}
<_DownloadButton option={option} downloadStartFunction={downloadStartFunction} />最新版は現在利用不可
+{t("config_page.plugins.available_latest_version")}
最新バージョン: {latest_version}
+{latest_version_label}
<_DownloadButton option={option} downloadStartFunction={downloadStartFunction} />最新のバージョン: {latest_version}
-VRCT最新版で利用可能
+{latest_version_label}
+{t("config_page.plugins.available_in_latest_vrct_version")}
最新バージョン: {latest_version}
-現在利用不可
+{latest_version_label}
+{t("config_page.plugins.unavailable_not_downloaded")}
- {target_locale.title} -
-{plugin.plugin_id}
-- {target_locale.desc} -
- {plugin.is_error ? ( -Error: {plugin.error_message}
- ) : ( -- {plugin.is_downloaded - ? `現在のバージョン: ${plugin.downloaded_plugin_info?.plugin_version}` - : null} -
-+ {target_locale.title} +
++ {target_locale.desc} +
+ {/*{plugin.plugin_id}
*/} +Error: {plugin.error_message}
+ ) : (