File size: 6,140 Bytes
0ce04f3 06fbe5b 0ce04f3 6e095c8 0ce04f3 6e095c8 0ce04f3 06fbe5b 0ce04f3 6e095c8 0ce04f3 06fbe5b 0ce04f3 06fbe5b 0ce04f3 06fbe5b 0ce04f3 06fbe5b 0ce04f3 06fbe5b 6e095c8 06fbe5b 6e095c8 06fbe5b 0ce04f3 6e095c8 0ce04f3 06fbe5b 0ce04f3 06fbe5b 6e095c8 06fbe5b 0ce04f3 6e095c8 0ce04f3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
// app/static/script.js
document.addEventListener('DOMContentLoaded', () => {
// --- State ---
let currentFile = null;
let currentXHR = null;
// --- DOM Elements ---
const states = {
initial: document.getElementById('state-initial'),
uploading: document.getElementById('state-uploading'),
complete: document.getElementById('state-complete'),
error: document.getElementById('state-error'),
};
const dropZone = document.getElementById('drop-zone');
const browseBtn = document.getElementById('browse-btn');
const fileInput = document.getElementById('file-input');
const fileNameEl = document.getElementById('file-name');
const fileSizeEl = document.getElementById('file-size');
const progressBar = document.getElementById('progress-bar');
const statusText = document.getElementById('status-text');
const downloadLink = document.getElementById('download-link');
const uploadAnotherBtn = document.getElementById('upload-another-btn');
const errorMessage = document.getElementById('error-message');
const retryBtn = document.getElementById('retry-btn');
// New elements for copy functionality
const downloadUrlInput = document.getElementById('download-url-input');
const copyLinkBtn = document.getElementById('copy-link-btn');
// --- UI State Management ---
function switchState(state) {
Object.values(states).forEach(el => el.classList.remove('active'));
if (states[state]) {
states[state].classList.add('active');
}
}
// --- Event Listeners ---
browseBtn.addEventListener('click', () => fileInput.click());
fileInput.addEventListener('change', handleFileSelect);
dropZone.addEventListener('dragover', (e) => {
e.preventDefault();
dropZone.classList.add('drag-over');
});
dropZone.addEventListener('dragleave', () => dropZone.classList.remove('drag-over'));
dropZone.addEventListener('drop', (e) => {
e.preventDefault();
dropZone.classList.remove('drag-over');
if (e.dataTransfer.files.length > 0) {
handleFileSelect({ target: { files: e.dataTransfer.files } });
}
});
uploadAnotherBtn.addEventListener('click', resetUploader);
retryBtn.addEventListener('click', resetUploader);
copyLinkBtn.addEventListener('click', handleCopyLink);
// --- Core Functions ---
function handleFileSelect(event) {
const file = event.target.files[0];
if (!file) return;
currentFile = file;
fileNameEl.textContent = file.name;
fileSizeEl.textContent = formatBytes(file.size);
startUpload(file);
}
function startUpload(file) {
switchState('uploading');
statusText.textContent = 'Uploading...';
progressBar.style.width = '0%';
const formData = new FormData();
formData.append('file', file);
const xhr = new XMLHttpRequest();
currentXHR = xhr;
xhr.upload.addEventListener('progress', (event) => {
if (event.lengthComputable) {
const percentage = (event.loaded / event.total) * 100;
progressBar.style.width = `${percentage}%`;
statusText.textContent = `${formatBytes(event.loaded)} / ${formatBytes(event.total)}`;
}
});
xhr.addEventListener('load', () => {
if (xhr.status >= 200 && xhr.status < 300) {
const response = JSON.parse(xhr.responseText);
// Construct the full, absolute URL for sharing
const fullUrl = `${window.location.origin}${response.download_url}`;
downloadLink.href = response.download_url;
downloadLink.download = response.filename;
downloadUrlInput.value = fullUrl;
switchState('complete');
} else {
handleUploadError(xhr);
}
});
xhr.addEventListener('error', () => handleUploadError(xhr));
xhr.addEventListener('abort', () => console.log('Upload aborted.'));
xhr.open('POST', '/upload', true);
xhr.send(formData);
}
// NEW: Function to handle copying the link
function handleCopyLink() {
// Use the modern Navigator Clipboard API
navigator.clipboard.writeText(downloadUrlInput.value).then(() => {
// Provide visual feedback
copyLinkBtn.textContent = 'Copied!';
copyLinkBtn.classList.add('copied');
// Revert back after a couple of seconds
setTimeout(() => {
copyLinkBtn.textContent = 'Copy';
copyLinkBtn.classList.remove('copied');
}, 2000);
}).catch(err => {
console.error('Failed to copy text: ', err);
// You could add an error state to the button here if needed
});
}
function handleUploadError(xhr) {
let message = 'An unknown network error occurred.';
try {
const errorData = JSON.parse(xhr.responseText);
message = errorData.detail || 'Upload failed.';
} catch (e) {
if (xhr.statusText) {
message = xhr.statusText;
}
}
errorMessage.textContent = message;
switchState('error');
}
function resetUploader() {
if (currentXHR) {
currentXHR.abort();
currentXHR = null;
}
currentFile = null;
fileInput.value = '';
downloadUrlInput.value = ''; // Clear the URL input
switchState('initial');
}
function formatBytes(bytes, decimals = 2) {
if (bytes === 0) return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
}
switchState('initial');
}); |