import { Notifier } from "./Notifier.js"; import { ProgressBar } from "./ProgressBar.js"; import { VideoCompressor } from "./VideoCompressor.js"; import { FileSelector } from "./FileSelector.js"; const notifier = new Notifier(); const progressBar = new ProgressBar(); const videoCompressor = new VideoCompressor(progressBar); const fileSelector = new FileSelector("video/"); fileSelector.addInput(document.getElementById("file-input")); fileSelector.addDropZone(document.getElementById("file-drop-area")); fileSelector.onFileSelected = file => { document.getElementById("uploaded-video").src = URL.createObjectURL(file); document.getElementById("uploaded-video").load(); hideElements("#file-drop-area", "#file-input-spacing"); showElements("#uploaded-video", "#change-file"); }; async function compress(filesize, filesizeUnit) { document.getElementById("uploaded-video").pause(); const sectionChangePromise = showSection("loading"); if (!fileSelector.selectedFile) { await sectionChangePromise; // Avoid changing sections at the same time alert("Please select a file"); return; } const videoLength = document.getElementById("uploaded-video").duration; let targetFilesize; switch (filesizeUnit) { case "kb": targetFilesize = filesize * 1000; break; case "mb": targetFilesize = filesize * 1000000; break; } let result; try { result = await videoCompressor.compress(fileSelector.selectedFile, targetFilesize, videoLength); } catch (e) { await sectionChangePromise; // Avoid changing sections at the same time alert(e.message); showSection("file-picker"); return; } if (!result) return; notifier.notifyFinished(); const url = URL.createObjectURL(result); document.getElementById("compressed-video").src = url; document.getElementById("compressed-video").load(); document.getElementById("result-size").innerText = bytesToSizeString(result.size); document.getElementById("download").onclick = () => { const a = document.createElement("a"); a.href = url; a.download = result.name; a.click(); }; const shareData = { text: "Compressed using " + window.origin, files: [result], }; if (navigator.share && (!navigator.canShare || navigator.canShare(shareData))) { document.getElementById("share").style.display = "inline-block"; document.getElementById("share").onclick = () => navigator.share(shareData); } else { document.getElementById("share").style.display = "none"; } showSection("result"); } document.getElementById("compress").onclick = async () => { const filesize = document.getElementById("filesize").value; const filesizeUnit = document.getElementById("filesize-unit").value; await compress(filesize, filesizeUnit); } document.getElementById("cancel").onclick = () => { videoCompressor.stop(); showSection("file-picker"); }; document.getElementById("change-file").onclick = () => document.getElementById("file-input").click(); document.getElementById("back").onclick = () => showSection("file-picker"); window.onbeforeunload = event => { if (videoCompressor.inProgress) event.preventDefault(); }; function bytesToSizeString(bytes) { if (bytes >= 1000000000) return (bytes / 1000000000).toFixed(1) + " GB"; if (bytes >= 1000000) return (bytes / 1000000).toFixed(1) + " MB"; if (bytes >= 1000) return (bytes / 1000).toFixed(1) + " KB"; return bytes + " B"; } for (const tabbable of document.querySelectorAll("[tabindex='0']")) { tabbable.onkeydown = event => { if (['Enter', 'Space'].includes(event.code)) tabbable.click(); } } for (const preset of document.getElementsByClassName("preset")) { preset.onclick = () => compress(parseInt(preset.dataset.size), preset.dataset.unit); }