MidiVizSF2 / patch.js
shethjenil's picture
Update patch.js
5aa3719 verified
function base64ToUrl(base64, mimeType = '') {
// Split the base64 string if it contains a data URL prefix
const [prefix, data] = base64.includes(',') ? base64.split(',') : ['', base64];
// Try to extract the MIME type from the prefix if not provided
const mime = mimeType || (prefix.match(/data:(.*?);base64/) || [])[1] || 'application/octet-stream';
// Decode base64 to raw binary data
const binary = atob(data);
const len = binary.length;
const bytes = new Uint8Array(len);
for (let i = 0; i < len; i++) {
bytes[i] = binary.charCodeAt(i);
}
// Create a blob and generate a URL
const blob = new Blob([bytes], { type: mime });
return URL.createObjectURL(blob);
}
function getElementByXpath(path, timeout = 5000) {
return new Promise((resolve, reject) => {
const intervalTime = 500;
let elapsedTime = 0;
const interval = setInterval(() => {
let node = document.evaluate(path, document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
if (node) {
clearInterval(interval);
resolve(node);
}
elapsedTime += intervalTime;
if (elapsedTime >= timeout) {
clearInterval(interval);
reject(new Error(`XPath "${path}" not found within ${timeout}ms`));
}
}, intervalTime);
});
}
async function uploadFileFromURL(url, filename, file_element) {
try {
if (!file_element) throw new Error("File input element not found.");
const response = await fetch(url);
if (!response.ok) throw new Error(`Failed to fetch file: ${response.statusText}`);
const blob = await response.blob();
const newFile = new File([blob], filename, { type: blob.type });
const dataTransfer = new DataTransfer();
if (file_element.multiple) {
for (const file of file_element.files) {
dataTransfer.items.add(file);
}
}
dataTransfer.items.add(newFile);
file_element.files = dataTransfer.files;
file_element.dispatchEvent(new Event("change", { bubbles: true }));
} catch (error) {
console.error("Error:", error);
}
}
function waitForElement(selector, timeout = 5000) {
return new Promise((resolve, reject) => {
const intervalTime = 500;
let elapsedTime = 0;
const interval = setInterval(() => {
const element = document.querySelector(selector);
if (element) {
clearInterval(interval);
resolve(element);
}
elapsedTime += intervalTime;
if (elapsedTime >= timeout) {
clearInterval(interval);
reject(new Error(`Element "${selector}" not found within ${timeout}ms`));
}
}, intervalTime);
});
}
document.addEventListener("DOMContentLoaded", function () {
getElementByXpath("//*[text()='Hide top bar']", 5000)
.then((node) => {
node.scrollIntoView();
node.click();
return waitForElement("#midi_file_input");
})
.then((file_upload) => {
if (!file_upload) throw new Error("File input element not found.");
// Wait for stability before proceeding
return new Promise(resolve => setTimeout(() => resolve(file_upload), 500));
})
.then((file_upload) => {
return waitForElement(".show_top_button").then((node) => {
node.remove();
selector = document.getElementById("renderer_mode_selector");
selector.selectedIndex = 2;
selector.dispatchEvent(new Event('change'));
// return uploadFileFromURL("/output.mid", "output.mid", file_upload);
});
})
.catch((error) => {
console.error("Error:", error);
});
});
window.addEventListener("message", async (event) => {
if (event.data?.type === "load-midi" && event.data.name) {
const url = event.data.url;
const file_name = event.data.name
const input = document.getElementById("midi_file_input");
if (url && input) {
await uploadFileFromURL(url, file_name, input);
}
}
});