For data integration correctly, the plugins data (saved, downloaded, fetched) merge whenever update data each of it. Separate plugins controllers.
207 lines
9.3 KiB
JavaScript
207 lines
9.3 KiB
JavaScript
import { useEffect, useRef } from "react";
|
||
import { usePlugins } from "@logics_configs";
|
||
import { useSoftwareVersion } from "@logics_common";
|
||
|
||
export const MergePluginsController = () => {
|
||
const {
|
||
currentLoadedPlugins,
|
||
updatePluginsData,
|
||
currentPluginsData,
|
||
currentFetchedPluginsInfo,
|
||
currentSavedPluginsStatus,
|
||
downloadAndExtractPlugin,
|
||
} = usePlugins();
|
||
const { checkVrctVerCompatibility } = useSoftwareVersion();
|
||
|
||
// downloaded, fetched, saved の各情報をまとめてマージ
|
||
useEffect(() => {
|
||
const mergePluginData = () => {
|
||
updatePluginsData(prev => {
|
||
// downloaded, fetched, 保存済み状態のMapをそれぞれ作成(plugin_id をキー)
|
||
const downloaded_map = new Map(
|
||
currentLoadedPlugins.data.map(info => [info.plugin_id, info])
|
||
);
|
||
const fetched_map = new Map(
|
||
currentFetchedPluginsInfo.data.map(info => [info.plugin_id, info])
|
||
);
|
||
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])
|
||
);
|
||
|
||
// union_keys: Saved以外の情報に対して重複なくキーを取得する
|
||
const union_keys = new Set([
|
||
...downloaded_map.keys(),
|
||
...fetched_map.keys(),
|
||
...prev_map.keys(),
|
||
]);
|
||
|
||
const new_data = [];
|
||
for (const id of union_keys) {
|
||
const downloaded = downloaded_map.get(id);
|
||
const fetched = fetched_map.get(id);
|
||
const prev_plugin = prev_map.get(id);
|
||
let plugin = {};
|
||
|
||
if (downloaded) {
|
||
// ダウンロード済み情報に対してサポート確認
|
||
const { is_plugin_supported, is_plugin_supported_latest_vrct } =
|
||
checkVrctVerCompatibility(
|
||
downloaded.min_supported_vrct_version,
|
||
downloaded.max_supported_vrct_version
|
||
);
|
||
plugin = {
|
||
// prevの情報があれば引き継ぎつつ上書き
|
||
...(prev_plugin || {}),
|
||
plugin_id: downloaded.plugin_id,
|
||
component: downloaded.component,
|
||
is_downloaded: true,
|
||
downloaded_plugin_info: {
|
||
...downloaded,
|
||
is_plugin_supported,
|
||
is_plugin_supported_latest_vrct,
|
||
},
|
||
};
|
||
|
||
if (fetched) {
|
||
const is_latest_version_available =
|
||
(downloaded.plugin_version !== fetched.plugin_version && fetched.is_plugin_supported);
|
||
plugin = {
|
||
...plugin,
|
||
is_outdated: false,
|
||
latest_plugin_info: { ...fetched },
|
||
is_latest_version_available:
|
||
plugin.is_downloaded && is_latest_version_available,
|
||
is_latest_version_already:
|
||
downloaded.plugin_version === fetched.plugin_version,
|
||
};
|
||
} else {
|
||
// フェッチ情報がない場合の初期状態
|
||
plugin = {
|
||
...plugin,
|
||
is_latest_version_available: false,
|
||
is_latest_version_already: true,
|
||
};
|
||
}
|
||
} else if (fetched) {
|
||
// フェッチ情報のみの場合は、ダウンロードしていない初期状態
|
||
plugin = {
|
||
...(prev_plugin || {}),
|
||
plugin_id: fetched.plugin_id,
|
||
is_downloaded: false,
|
||
is_latest_version_available: fetched.is_plugin_supported,
|
||
is_latest_version_already: false,
|
||
is_outdated: false,
|
||
latest_plugin_info: { ...fetched },
|
||
};
|
||
} else if (prev_plugin) {
|
||
// 既存情報のみ存在する場合は outdated フラグを付与
|
||
plugin = { ...prev_plugin, is_outdated: true };
|
||
}
|
||
// いずれかの情報がある場合のみ new_data に追加
|
||
if (plugin.plugin_id) {
|
||
new_data.push(plugin);
|
||
}
|
||
}
|
||
|
||
// 保存済み状態(currentSavedPluginsStatus)のマージ
|
||
// ・new_dataに存在する各プラグインに対して、保存済みの is_enabled を上書き
|
||
new_data.forEach(plugin => {
|
||
if (saved_map.has(plugin.plugin_id)) {
|
||
plugin.is_enabled = saved_map.get(plugin.plugin_id).is_enabled;
|
||
}
|
||
});
|
||
// ・prev.data には存在せず、保存済み情報にのみある場合は追加
|
||
for (const [id, saved] of saved_map.entries()) {
|
||
if (!new_data.some(item => item.plugin_id === id)) {
|
||
new_data.push({ plugin_id: saved.plugin_id, is_enabled: saved.is_enabled });
|
||
}
|
||
}
|
||
|
||
|
||
// 追加処理: ダウンロード済みかつ有効なプラグインで、サポート対象でない場合は無効化
|
||
new_data.forEach(plugin => {
|
||
if (plugin.is_downloaded && plugin.is_enabled) {
|
||
if (
|
||
!plugin.downloaded_plugin_info?.is_plugin_supported &&
|
||
!plugin.latest_plugin_info?.is_plugin_supported
|
||
) {
|
||
plugin.is_enabled = false;
|
||
}
|
||
}
|
||
});
|
||
|
||
console.log("merged plugin data", new_data);
|
||
return new_data;
|
||
});
|
||
};
|
||
|
||
mergePluginData();
|
||
}, [currentFetchedPluginsInfo.data, currentLoadedPlugins.data, currentSavedPluginsStatus]);
|
||
|
||
|
||
|
||
// --- 自動アップデート(ダウンロード処理)のuseEffect ---
|
||
// ※downloadAndExtractPlugin の重複実行を防ぐため、実行中の plugin_id を useRef で管理
|
||
const downloadingRef = useRef(new Set());
|
||
|
||
useEffect(() => {
|
||
if (!currentPluginsData.data.length) return;
|
||
// マージ結果の currentPluginsData.data を元にダウンロード処理をチェック
|
||
currentPluginsData.data.forEach(plugin => {
|
||
if (plugin.is_downloaded &&
|
||
plugin.is_enabled &&
|
||
!plugin.is_latest_version_already &&
|
||
plugin.is_latest_version_available
|
||
) {
|
||
console.log(!downloadingRef.current.has(plugin.plugin_id));
|
||
|
||
if (!downloadingRef.current.has(plugin.plugin_id)) {
|
||
downloadingRef.current.add(plugin.plugin_id);
|
||
// ※ downloadAndExtractPlugin は外部通信を伴い currentLoadedPlugins.data 更新を引き起こすので注意
|
||
downloadAndExtractPlugin(plugin)
|
||
.then(() => {
|
||
console.log(`Plugin ${plugin.plugin_id} updated successfully`);
|
||
downloadingRef.current.delete(plugin.plugin_id);
|
||
})
|
||
.catch((error) => {
|
||
console.error(`Plugin ${plugin.plugin_id} update failed`, error);
|
||
downloadingRef.current.delete(plugin.plugin_id);
|
||
});
|
||
}
|
||
}
|
||
});
|
||
}, [currentPluginsData.data]);
|
||
|
||
|
||
|
||
|
||
return null;
|
||
};
|
||
|
||
|
||
|
||
|
||
|
||
// ダウンロード済みで最新版じゃない場合、自動的にアップデート
|
||
// // is_latest_version_supported: true のみ。
|
||
// // 失敗した場合、現在のバージョンが非対応の場合はdisabledにする。
|
||
// new_data.forEach(async plugin => {
|
||
// if (plugin.is_enabled) {
|
||
// console.log(plugin);
|
||
|
||
// if (!plugin.is_latest_version_already && plugin.is_latest_version_available) {
|
||
// await downloadAndExtractPlugin(plugin);
|
||
// }
|
||
// }
|
||
// });
|
||
|
||
// new_data.forEach(plugin => {
|
||
// if (plugin.is_downloaded && plugin.is_enabled) {
|
||
// if (!plugin.downloaded_plugin_info?.is_plugin_supported && !plugin.latest_plugin_info?.is_plugin_supported) {
|
||
// plugin.is_enabled = false
|
||
// }
|
||
// }
|
||
// });
|