Add drag & drop script variants and enhanced debugging tools

- Introduced multiple JavaScript scripts for handling drag & drop functionality:
  - `bridge_script.js`: Original implementation with popup prevention.
  - `bridge_script_debug.js`: Debug version with extensive logging for troubleshooting.
  - `bridge_script_v2.js`: Enhanced version extending DataTransfer for better integration.
  - `bridge_script_hybrid.js`: Hybrid approach allowing parallel native file drag.
  - `bridge_script_drop_intercept.js`: Intercepts drop events for custom handling.
  - `bridge_script_intercept.js`: Prevents browser drag for ALT+drag, using Qt for file drag.

- Added detailed documentation in `SCRIPT_VARIANTS.md` outlining usage, status, and recommended workflows for each script.
- Implemented logging features to capture drag events, DataTransfer modifications, and network requests for better debugging.
- Enhanced DataTransfer handling to support Windows-specific file formats and improve user experience during drag & drop operations.
This commit is contained in:
claudi 2026-02-17 19:19:14 +01:00
parent 88dc358894
commit dee02ad600
12 changed files with 2244 additions and 65 deletions

View file

@ -0,0 +1,165 @@
// 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;');
})();