[Update] Plugins: Add update function.

This commit is contained in:
Sakamoto Shiina
2025-04-02 22:52:20 +09:00
parent c02d7c49e9
commit 67f32ad7b9
7 changed files with 83 additions and 52 deletions

View File

@@ -23,25 +23,43 @@ export const PluginsController = ({ fetchPluginsHasRunRef }) => {
const info_array = await asyncFetchPluginsInfo(); const info_array = await asyncFetchPluginsInfo();
updatePluginsData(prev => { updatePluginsData(prev => {
// Map を利用してそれぞれの配列を plugin_id で参照できるようにする // Map を利用してそれぞれの配列を plugin_id で参照できるようにする
const infoMap = new Map(info_array.map(info => [info.plugin_id, info])); const info_map = new Map(info_array.map(info => [info.plugin_id, info]));
const prevMap = new Map(prev.data.map(item => [item.plugin_id, item])); const prev_map = new Map(prev.data.map(item => [item.plugin_id, item]));
// info_array にある各アイテムについて、prev.data に同じ plugin_id があればマージ // info_array にある各アイテムについて、prev.data に同じ plugin_id があればマージ
const merged = info_array.map(info => { const merged = info_array.map(info => {
if (prevMap.has(info.plugin_id)) { if (prev_map.has(info.plugin_id)) {
return { ...info, ...prevMap.get(info.plugin_id) }; return {
...info,
latest_plugin_version: info.plugin_version,
...prev_map.get(info.plugin_id),
};
} }
return info; return {
...info,
latest_plugin_version: info.plugin_version,
};
}); });
// prev.data にのみ存在するアイテムを追加し、is_outdated: true を付与 // prev.data にのみ存在するアイテム = latest plugin infoには存在しない
// を追加し、is_outdated: true を付与
prev.data.forEach(item => { prev.data.forEach(item => {
if (!infoMap.has(item.plugin_id)) { if (!info_map.has(item.plugin_id)) {
merged.push({ ...item, is_outdated: true }); merged.push({ ...item, is_outdated: true });
} }
}); });
return merged; 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_value.push(plugin);
}
return new_value;
}); });
} catch (error) { } catch (error) {
console.error(error); console.error(error);
@@ -59,7 +77,7 @@ export const PluginsController = ({ fetchPluginsHasRunRef }) => {
updatePluginsData(prev => { updatePluginsData(prev => {
// currentSavedPluginsStatus.data の各要素を Map 化して plugin_id で参照 // currentSavedPluginsStatus.data の各要素を Map 化して plugin_id で参照
const savedMap = new Map(currentSavedPluginsStatus.data.map(saved => [saved.plugin_id, saved])); const savedMap = new Map(currentSavedPluginsStatus.data.map(saved => [saved.plugin_id, saved]));
const prevMap = new Map(prev.data.map(item => [item.plugin_id, item])); const prev_map = new Map(prev.data.map(item => [item.plugin_id, item]));
// prev.data にある各アイテムについて、保存済みの状態情報があればマージ // prev.data にある各アイテムについて、保存済みの状態情報があればマージ
const merged = prev.data.map(item => { const merged = prev.data.map(item => {
@@ -71,7 +89,7 @@ export const PluginsController = ({ fetchPluginsHasRunRef }) => {
// currentSavedPluginsStatus.data にのみ存在する項目があれば追加 // currentSavedPluginsStatus.data にのみ存在する項目があれば追加
currentSavedPluginsStatus.data.forEach(saved => { currentSavedPluginsStatus.data.forEach(saved => {
if (!prevMap.has(saved.plugin_id)) { if (!prev_map.has(saved.plugin_id)) {
merged.push({ plugin_id: saved.plugin_id, is_enabled: saved.is_enabled }); merged.push({ plugin_id: saved.plugin_id, is_enabled: saved.is_enabled });
} }
}); });

View File

@@ -32,6 +32,15 @@ export const _DownloadButton = ({option, ...props}) => {
<p className={styles.download_button_label}>{t("config_page.model_download_button_label")}</p> <p className={styles.download_button_label}>{t("config_page.model_download_button_label")}</p>
</button> </button>
); );
case option.update_button:
return (
<button
className={styles.update_button}
onClick={() => props.downloadStartFunction(option.id)}
>
<p className={styles.download_button_label}>Update</p>
</button>
);
default: default:
return null; return null;
} }

View File

@@ -29,3 +29,17 @@
position: absolute; position: absolute;
font-size: 1rem; font-size: 1rem;
} }
.update_button {
pointer-events: auto;
background-color: var(--primary_400_color);
padding: 0.8rem;
flex-shrink: 0;
border-radius: 0.2rem;
&:hover {
background-color: var(--primary_450_color);
}
&:active {
background-color: var(--primary_500_color);
}
}

View File

@@ -1,48 +1,31 @@
import { import { SwitchBox } from "../index";
SwitchBox,
} from "../index";
import { _DownloadButton } from "../_atoms/_download_button/_DownloadButton"; import { _DownloadButton } from "../_atoms/_download_button/_DownloadButton";
import styles from "./PluginsControlComponent.module.scss"; import styles from "./PluginsControlComponent.module.scss";
export const PluginsControlComponent = ({ variable_state, plugin_status, toggleFunction, ...props }) => { 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;
const option = { const option = {
id: plugin_status.plugin_id, id: plugin_id,
is_pending: plugin_status.is_pending, is_pending: is_pending,
is_downloaded: plugin_status.is_downloaded, is_downloaded: is_downloaded,
data: plugin_status.is_enabled, data: is_enabled,
update_button: is_downloaded && is_latest_version_available,
state: variable_state, state: variable_state,
progress: null, progress: null,
}; };
const adjustedToggleFunction = () => { const togglePlugin = () => toggleFunction(plugin_id);
toggleFunction(plugin_status.plugin_id); const is_turn_on_able = is_downloaded && (is_plugin_supported || is_outdated);
};
let is_turn_on_able = false;
if (plugin_status.is_downloaded && plugin_status.is_plugin_supported) {
is_turn_on_able = true;
}
if (plugin_status.is_outdated) {
is_turn_on_able = true;
}
return ( return (
<div className={styles.container}> <div className={styles.container}>
{is_turn_on_able && {is_plugin_supported ? (
<SwitchBox <_DownloadButton option={option} downloadStartFunction={downloadStartFunction} />
variable={option} ) : (
toggleFunction={adjustedToggleFunction} <div className={styles.unavailable_text}>Downloaded but outdated.</div>
/>} )}
{plugin_status.is_plugin_supported ? {is_turn_on_able && <SwitchBox variable={option} toggleFunction={togglePlugin} />}
<_DownloadButton
option={option}
downloadStartFunction={props.downloadStartFunction}
/>
:
<div className={styles.unavailable_text}>
Downloaded but outdated.
</div>
}
</div> </div>
); );
}; };

View File

@@ -1,4 +1,8 @@
.container { .container {
display: flex;
justify-content: center;
align-items: center;
gap: 2rem;
} }
.unavailable_text { .unavailable_text {

View File

@@ -88,7 +88,8 @@ const PluginDownloadContainer = () => {
) : ( ) : (
<div className={styles.plugin_info_wrapper}> <div className={styles.plugin_info_wrapper}>
<div className={styles.plugin_info}> <div className={styles.plugin_info}>
<p>Version: {plugin.plugin_version}</p> <p>Downloaded Version: {plugin.downloaded_plugin_version}</p>
<p>Latest Version: {plugin.latest_plugin_version}</p>
<p> <p>
Compatible: {plugin.min_supported_vrct_version} ~ {plugin.max_supported_vrct_version} Compatible: {plugin.min_supported_vrct_version} ~ {plugin.max_supported_vrct_version}
</p> </p>

View File

@@ -47,17 +47,19 @@ export const usePlugins = () => {
return console.error("An invalid plugin was detected.", plugin_info.plugin_id, plugin_info.location, component); return console.error("An invalid plugin was detected.", plugin_info.plugin_id, plugin_info.location, component);
} }
updatePluginsData(prev => { 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 => const new_value = prev.data.map(old_value =>
old_value.plugin_id === plugin_info.plugin_id 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 return new_value;
? new_value
: [...new_value, { plugin_id: plugin_info.plugin_id, location: plugin_info.location, component, is_downloaded: true }];
}); });
}, },
createAtomWithHook: (...args) => createAtomWithHook(...args), createAtomWithHook: (...args) => createAtomWithHook(...args),