- Full VPM Uploader feature set (auth, users, folders, AMPP monitor) - HTTP upload via presigned S3 URLs with XHR progress tracking - UDP upload mode with relay server (WebRTC DataChannel + HTTP fallback) - S3 Admin settings with live Test Connection (upload+delete verify) - UDP Relay Admin settings with health check - Standalone UDP relay server (Node.js + Docker) with multipart S3 assembly - Chrome Extension (Manifest v3): popup, background, content script - Dynamic S3 client — reconfigures on save without restart - Dark/light theme, full AMPP job monitor - docker-compose.yml with dragon-wind + udp-relay services Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
73 lines
2.7 KiB
JavaScript
73 lines
2.7 KiB
JavaScript
"use strict";
|
|
/**
|
|
* Dragon Wind — Content Script
|
|
* Injects drag-and-drop overlay on any page, sends files to background for upload.
|
|
*/
|
|
|
|
(function() {
|
|
if (window.__dragonWindLoaded) return;
|
|
window.__dragonWindLoaded = true;
|
|
|
|
let overlay = null;
|
|
|
|
document.addEventListener('dragover', (e) => {
|
|
if (e.dataTransfer?.types?.includes('Files')) {
|
|
e.preventDefault();
|
|
showOverlay();
|
|
}
|
|
});
|
|
|
|
document.addEventListener('dragleave', (e) => {
|
|
if (!e.relatedTarget || e.relatedTarget === document.body) hideOverlay();
|
|
});
|
|
|
|
document.addEventListener('drop', (e) => {
|
|
hideOverlay();
|
|
// Only intercept if dropping on the overlay itself
|
|
if (e.target !== overlay) return;
|
|
e.preventDefault();
|
|
const files = Array.from(e.dataTransfer.files);
|
|
if (!files.length) return;
|
|
chrome.runtime.sendMessage({ type: 'PAGE_DROP', files: files.map(f => ({ name: f.name, size: f.size })) });
|
|
showToast(`Dragon Wind: ${files.length} file${files.length>1?'s':''} ready — open extension to upload`);
|
|
});
|
|
|
|
function showOverlay() {
|
|
if (overlay) return;
|
|
overlay = document.createElement('div');
|
|
overlay.style.cssText = `
|
|
position:fixed;inset:0;z-index:2147483647;
|
|
background:rgba(6,8,14,.85);
|
|
display:flex;align-items:center;justify-content:center;
|
|
backdrop-filter:blur(4px);
|
|
pointer-events:none;
|
|
`;
|
|
overlay.innerHTML = `
|
|
<div style="text-align:center;color:#e4e8f1;font-family:system-ui,sans-serif">
|
|
<div style="font-size:3rem;margin-bottom:1rem">🌪️</div>
|
|
<div style="font-size:1.5rem;font-weight:700;background:linear-gradient(135deg,#e05c1a,#ff7d3b);-webkit-background-clip:text;-webkit-text-fill-color:transparent">Dragon Wind</div>
|
|
<div style="font-size:1rem;color:#7a85a0;margin-top:.5rem">Drop files to queue for upload</div>
|
|
</div>
|
|
`;
|
|
document.body.appendChild(overlay);
|
|
}
|
|
|
|
function hideOverlay() {
|
|
if (overlay) { overlay.remove(); overlay = null; }
|
|
}
|
|
|
|
function showToast(msg) {
|
|
const t = document.createElement('div');
|
|
t.style.cssText = `
|
|
position:fixed;bottom:24px;right:24px;z-index:2147483647;
|
|
background:#10141f;border:1px solid #e05c1a;border-radius:10px;
|
|
color:#e4e8f1;padding:12px 18px;font-family:system-ui,sans-serif;font-size:14px;
|
|
font-weight:600;box-shadow:0 4px 20px rgba(0,0,0,.4);
|
|
opacity:0;transform:translateY(8px);transition:all .25s;
|
|
`;
|
|
t.textContent = msg;
|
|
document.body.appendChild(t);
|
|
requestAnimationFrame(() => { t.style.opacity = '1'; t.style.transform = 'translateY(0)'; });
|
|
setTimeout(() => { t.style.opacity = '0'; setTimeout(() => t.remove(), 300); }, 4000);
|
|
}
|
|
})();
|