// WebDrop Bridge - Intercept Version // Prevents browser drag for ALT+drag, hands off to Qt for file drag (function() { if (window.__webdrop_intercept_injected) return; window.__webdrop_intercept_injected = true; // Intercept mode enabled var INTERCEPT_ENABLED = true; console.log('%c[WebDrop Intercept] Script loaded - INTERCEPT_ENABLED=' + INTERCEPT_ENABLED, 'background: #2196F3; color: white; font-weight: bold; padding: 4px 8px;'); var currentDragUrl = null; var angularDragHandlers = []; var originalAddEventListener = EventTarget.prototype.addEventListener; var listenerPatchActive = true; // Capture Authorization token from XHR requests window.capturedAuthToken = null; var originalXHRSetRequestHeader = XMLHttpRequest.prototype.setRequestHeader; XMLHttpRequest.prototype.setRequestHeader = function(header, value) { if (header === 'Authorization' && value.startsWith('Bearer ')) { window.capturedAuthToken = value; console.log('[Intercept] Captured auth token'); } return originalXHRSetRequestHeader.apply(this, arguments); }; // ============================================================================ // PART 1: Intercept Angular's dragstart listener registration // ============================================================================ EventTarget.prototype.addEventListener = function(type, listener, options) { if (listenerPatchActive && type === 'dragstart' && listener) { // Store Angular's dragstart handler instead of registering it console.log('[Intercept] Storing Angular dragstart listener for', this.tagName || this.constructor.name); angularDragHandlers.push({ target: this, listener: listener, options: options }); return; // Don't actually register it yet } // All other events: use original return originalAddEventListener.call(this, type, listener, options); }; // ============================================================================ // PART 2: Intercept DataTransfer.setData to capture URL // ============================================================================ var originalSetData = DataTransfer.prototype.setData; DataTransfer.prototype.setData = function(format, data) { if (format === 'text/plain' || format === 'text/uri-list') { currentDragUrl = data; console.log('%c[Intercept] Captured URL:', 'color: #4CAF50; font-weight: bold;', data.substring(0, 80)); } return originalSetData.call(this, format, data); }; console.log('[Intercept] DataTransfer.setData patched ✓'); // ============================================================================ // PART 3: Install OUR dragstart handler in capture phase // ============================================================================ setTimeout(function() { console.log('[Intercept] Installing dragstart handler, have', angularDragHandlers.length, 'Angular handlers'); // Stop intercepting addEventListener listenerPatchActive = false; // Register OUR handler in capture phase originalAddEventListener.call(document, 'dragstart', function(e) { currentDragUrl = null; // Reset console.log('%c[Intercept] dragstart', 'background: #FF9800; color: white; padding: 2px 6px;', 'ALT:', e.altKey); // Call Angular's handlers first to let them set the data var handled = 0; for (var i = 0; i < angularDragHandlers.length; i++) { var h = angularDragHandlers[i]; if (h.target === document || h.target === e.target || (h.target.contains && h.target.contains(e.target))) {https://devagravitystg.file.core.windows.net/devagravitysync/anPGZszKzgKaSz1SIx2HFgduy/weiss_ORIGINAL.jpg try { h.listener.call(e.target, e); handled++; } catch(err) { console.error('[Intercept] Error calling Angular handler:', err); } } } console.log('[Intercept] Called', handled, 'Angular handlers, URL:', currentDragUrl ? currentDragUrl.substring(0, 60) : 'none'); // NOW check if we should intercept if (e.altKey && currentDragUrl) { var isAzure = /^https?:\/\/.+\.file\.core\.windows\.net\//i.test(currentDragUrl); var isZDrive = /^z:/i.test(currentDragUrl); if (isAzure || isZDrive) { console.log('%c[Intercept] PREVENTING browser drag, using Qt', 'background: #F44336; color: white; font-weight: bold; padding: 4px 8px;'); e.preventDefault(); e.stopPropagation(); ensureChannel(function() { if (window.bridge && typeof window.bridge.start_file_drag === 'function') { console.log('%c[Intercept] → Qt: start_file_drag', 'color: #9C27B0; font-weight: bold;'); window.bridge.start_file_drag(currentDragUrl); } else { console.error('[Intercept] bridge.start_file_drag not available!'); } }); currentDragUrl = null; return false; } } console.log('[Intercept] Normal drag, allowing browser'); }, true); // Capture phase console.log('[Intercept] dragstart handler installed ✓'); }, 1500); // Wait for Angular to register its listeners // ============================================================================ // PART 3: QWebChannel connection // ============================================================================ function ensureChannel(callback) { if (window.bridge) { callback(); return; } if (window.QWebChannel && window.qt && window.qt.webChannelTransport) { new QWebChannel(window.qt.webChannelTransport, function(channel) { window.bridge = channel.objects.bridge; console.log('[WebDrop Intercept] QWebChannel connected ✓'); callback(); }); } else { console.error('[WebDrop Intercept] QWebChannel not available!'); } } // Initialize channel on load if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function() { ensureChannel(function() { console.log('[WebDrop Intercept] Bridge ready ✓'); }); }); } else { ensureChannel(function() { console.log('[WebDrop Intercept] Bridge ready ✓'); }); } console.log('%c[WebDrop Intercept] Ready! ALT-drag will use Qt file drag.', 'background: #4CAF50; color: white; font-weight: bold; padding: 4px 8px;'); })();