penguinmod-editor / src /components /loader /tw-progress-monitor.js
soiz1's picture
Update src/components/loader/tw-progress-monitor.js
3ae777b verified
raw
history blame
3.65 kB
// 必要なモジュールをインポート
const corsAnywhere = require('cors-anywhere');
const XMLHttpRequest = require('xmlhttprequest').XMLHttpRequest;
// CORSプロキシサーバーの設定
const host = '127.0.0.1';
const port = 8080;
corsAnywhere.createServer({
originWhitelist: [], // すべてのオリジンを許可
requireHeaders: [],
}).listen(port, host, () => {
console.log(`CORS Anywhere server is running on ${host}:${port}`);
});
// グローバルな進行状況管理変数
let total = 0;
let complete = 0;
let state = 0;
let currentProgress = 0;
let progressHandler = (state, progress, complete, total) => {};
// 進行状況ハンドラを設定する関数
export const setProgressHandler = newHandler => {
progressHandler = newHandler;
progressHandler(state, currentProgress, complete, total);
};
// 進行状況更新をキューに入れる関数
const queueProgressHandlerUpdate = () => {
if (progressHandlerTimeout === null) {
progressHandlerTimeout = requestAnimationFrame(fireProgressHandler);
}
};
// 進行状況を更新する関数
const setProgress = progress => {
if (progress < 0) {
progress = 0;
}
if (progress > 1) {
progress = 1;
}
currentProgress = progress;
queueProgressHandlerUpdate();
};
// ステータスを設定する関数
const setState = newState => {
if (state === newState) {
return;
}
state = newState;
complete = 0;
total = 0;
setProgress(0);
};
// XMLHttpRequestで進行状況を監視してリソースを取得する関数
const fetchWithProgress = url => {
setState(1);
const proxyUrl = `http://127.0.0.1:8080/` + encodeURIComponent(url); // ローカルのCORSプロキシを使用
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = () => {
resolve(new Response(xhr.response, {
status: xhr.status,
statusText: xhr.statusText
}));
};
xhr.onloadend = () => setProgress(1);
xhr.onerror = () => reject(new Error('[tw-progress-monitor] xhr failed with status ' + xhr.status));
xhr.onprogress = e => {
if (e.lengthComputable) {
setProgress(e.loaded / e.total);
}
};
xhr.open('GET', proxyUrl);
xhr.send();
});
};
// fetchのオーバーライド
const originalFetch = window.fetch;
window.fetch = (url, opts) => {
const isGET = typeof opts === 'object' && opts && opts.method === 'GET';
const isProjectURL = typeof url === 'string' && /^https:\/\/projects\.scratch\.mit\.edu\/\d+$/.test(url);
if (isGET && isProjectURL) {
return fetchWithProgress(url);
}
return originalFetch(url, opts);
};
// Web Workerのメッセージ処理
const handleWorkerMessage = e => {
const data = e.data;
if (Array.isArray(data)) {
complete += data.length;
setProgress(complete / total);
}
};
if (window.Worker) {
let downloadWorker = null;
const originalPostMessage = window.Worker.prototype.postMessage;
window.Worker.prototype.postMessage = function (message) {
if (downloadWorker === null) {
if (message && message.url && message.id && message.options) {
downloadWorker = this;
downloadWorker.addEventListener('message', handleWorkerMessage);
}
}
if (downloadWorker === this) {
setState(2);
total++;
}
originalPostMessage.call(this, message);
};
}