Some checks are pending
Tests & Quality Checks / Test on Python 3.11 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.12 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.11-1 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.12-1 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.10 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.11-2 (push) Waiting to run
Tests & Quality Checks / Test on Python 3.12-2 (push) Waiting to run
Tests & Quality Checks / Build Artifacts (push) Blocked by required conditions
Tests & Quality Checks / Build Artifacts-1 (push) Blocked by required conditions
308 lines
9.3 KiB
Markdown
308 lines
9.3 KiB
Markdown
# Drag & Drop Problem Analysis - File Drop + Web App Popup
|
|
|
|
**Status**: Phase 1 (File Drop) ✅ Implemented | Phase 2 (Popup Trigger) ⏸️ Planned
|
|
**Last Updated**: March 3, 2026
|
|
|
|
## Overview
|
|
|
|
### Current Implementation Status
|
|
|
|
✅ **Phase 1 - File Drop (IMPLEMENTED)**
|
|
- JavaScript in `bridge_script_intercept.js` intercepts drag events
|
|
- Calls `window.bridge.start_file_drag(url)` via QWebChannel to Qt
|
|
- Validates path against whitelist via `PathValidator`
|
|
- Converts Azure Storage URLs to local paths via `URLConverter`
|
|
- Creates and executes native Qt file drag operation
|
|
- Target application (InDesign, Word, etc.) successfully receives file
|
|
|
|
⏸️ **Phase 2 - Programmatic Popup Trigger (PLANNED)**
|
|
- Would require reverse-engineering the web app's popup trigger mechanism
|
|
- Could be implemented by calling JavaScript function after successful drop
|
|
- Currently: Applications handle popups manually or separately from file drops
|
|
|
|
---
|
|
|
|
## Das Kernproblem
|
|
1. ✅ File gedroppt werden (Z:\ Laufwerk) → Native File-Drop
|
|
2. ✅ Web-App Popup erscheinen (Auschecken-Dialog) → Web-App Drop-Event
|
|
|
|
**Problem**: Diese beiden schließen sich gegenseitig aus:
|
|
- Native File-Drag (von Qt) → Web-App bekommt kein Drop-Event → Kein Popup
|
|
- Browser Text-Drag (von Web-App) → Kein File-Drop → Kein File
|
|
|
|
## Browser-Sicherheitsbeschränkungen
|
|
|
|
1. **DataTransfer.files ist read-only**
|
|
Wir können keine Files zu einem DataTransfer hinzufügen
|
|
|
|
2. **Nur EIN Drag zur Zeit möglich**
|
|
Wir können keinen parallelen Drag starten
|
|
|
|
3. **DataTransfer kann nicht erstellt werden**
|
|
Wir können kein synthetisches Drop-Event mit Files erzeugen
|
|
|
|
4. **Cross-Domain Sicherheit**
|
|
File-Zugriff ist stark eingeschränkt
|
|
|
|
## Getestete Ansätze
|
|
|
|
### ❌ Ansatz 1: DataTransfer erweitern
|
|
**Idee**: Web-App setzt URL, wir fügen Files hinzu
|
|
**Problem**: DataTransfer.files ist read-only
|
|
|
|
### ❌ Ansatz 2: Parallele Drags
|
|
**Idee**: Browser-Drag + Qt-Drag gleichzeitig
|
|
**Problem**: Nur ein Drag zur Zeit möglich
|
|
|
|
### ❌ Ansatz 3: Synthetisches Drop-Event
|
|
**Idee**: Original Drop abfangen, neues Event mit Files erzeugen
|
|
**Problem**: DataTransfer.files kann nicht gesetzt werden
|
|
|
|
### ⚠️ Ansatz 4: Native Drag + Event-Simulation
|
|
**Idee**: Qt Native Drag, dann Web-App Event manuell auslösen
|
|
**Problem**: Erfordert Kenntnis der exakten Web-App Event-Struktur (Angular CDK)
|
|
|
|
## 🎯 Praktikable Lösungen
|
|
|
|
### Lösung A: **Zwei-Phasen Ansatz** (EMPFOHLEN für Testing)
|
|
|
|
**Phase 1: File-Drop**
|
|
1. ALT-Drag startet
|
|
2. JavaScript erkennt convertible URL
|
|
3. Ruft Qt's `start_file_drag(url)` auf
|
|
4. `preventDefault()` verhindert Browser-Drag
|
|
5. Qt Native Drag läuft
|
|
6. File wird gedroppt ✅
|
|
|
|
**Phase 2: Popup manuell triggern**
|
|
7. Nach erfolgreichem Drop (via Qt Signal)
|
|
8. JavaScript simuliert den Event/API-Call der das Popup auslöst
|
|
9. Popup erscheint ✅
|
|
|
|
**Vorteile:**
|
|
- ✅ Funktioniert garantiert für File-Drop
|
|
- ✅ Kontrolle über beide Phasen
|
|
- ✅ Kann debugged werden
|
|
|
|
**Nachteile:**
|
|
- ⚠️ Erfordert Reverse-Engineering des Popup-Triggers
|
|
- ⚠️ Könnte bei Web-App Updates brechen
|
|
|
|
**Implementierung:**
|
|
```javascript
|
|
// Phase 1: Standard - File Drag
|
|
document.addEventListener('dragstart', function(e) {
|
|
if (!e.altKey) return;
|
|
|
|
// Extract URL from DataTransfer
|
|
var url = e.dataTransfer.getData('text/plain');
|
|
if (isConvertible(url)) {
|
|
e.preventDefault();
|
|
window.bridge.start_file_drag(url);
|
|
}
|
|
}, true);
|
|
|
|
// Phase 2: Popup Trigger (nach Drop-Erfolg)
|
|
// Qt ruft auf: window.trigger_checkout_popup(assetId)
|
|
window.trigger_checkout_popup = function(assetId) {
|
|
// Option 1: Klick auf Checkout-Button simulieren
|
|
// Option 2: API-Call direkt aufrufen
|
|
// Option 3: Angular-Event dispatchen
|
|
|
|
// Beispiel: Suche nach Angular-Component und rufe Methode auf
|
|
var angularComponent = findAngularComponent('ay-asset-card');
|
|
if (angularComponent) {
|
|
angularComponent.onCheckout(assetId);
|
|
}
|
|
};
|
|
```
|
|
|
|
**TODO für diese Lösung:**
|
|
1. ✅ File-Drag funktioniert bereits
|
|
2. ⏸️ Herausfinden wie Popup ausgelöst wird:
|
|
- Browser DevTools öffnen
|
|
- Network-Tab beobachten (API-Call?)
|
|
- Elements-Tab nutzen (Angular Component?)
|
|
- Event-Listeners ansehen
|
|
|
|
### Lösung B: **Gar nichts ändern beim Drag** (FALLBACK)
|
|
|
|
**Ansatz:**
|
|
1. ALT-Drag läuft normal durch (URL-Text wird gedroppt)
|
|
2. Popup erscheint ✅
|
|
3. Nach Popup-Bestätigung (Auschecken)
|
|
4. **DANN** konvertieren wir die URL und kopieren das File
|
|
|
|
**Vorteile:**
|
|
- ✅ Web-App funktioniert normal
|
|
- ✅ Kein Popup-Problem
|
|
- ✅ Einfach zu implementieren
|
|
|
|
**Nachteile:**
|
|
- ⚠️ Kein echter Drag & Drop (nur Copy)
|
|
- ⚠️ User muss zweimal handeln
|
|
|
|
### Lösung C: **File-Drop via Qt Window Overlay** (EXPERIMENTELL)
|
|
|
|
**Ansatz:**
|
|
1. Beim ALT-Drag: Start Normal Web-App Drag
|
|
2. Qt erstellt ein transparentes Overlay-Window über dem Browser
|
|
3. Overlay fängt das Drop-Event ab
|
|
4. Qt macht File-Drop
|
|
5. Qt leitet Drop-Koordinaten an Browser weiter
|
|
6. Browser bekommt synthetisches Event (ohne Files, nur Koordinaten)
|
|
7. Popup erscheint
|
|
|
|
**Vorteile:**
|
|
- ✅ Beide Funktionen potentiell möglich
|
|
- ✅ Keine DataTransfer-Manipulation nötig
|
|
|
|
**Nachteile:**
|
|
- ⚠️ Sehr komplex
|
|
- ⚠️ Plattform-spezifisch (Windows)
|
|
- ⚠️ Performance-Overhead
|
|
|
|
## 🔬 Nächste Schritte - Reverse Engineering
|
|
|
|
Um Lösung A zu implementieren, müssen wir herausfinden:
|
|
|
|
### 1. Wie wird das Popup ausgelöst?
|
|
|
|
**Debug-Schritte:**
|
|
```javascript
|
|
// In Browser Console ausführen während ALT-Drag+Drop
|
|
|
|
// Methode 1: Event-Listener finden
|
|
getEventListeners(document)
|
|
|
|
// Methode 2: Angular Component finden
|
|
var cards = document.querySelectorAll('ay-asset-card');
|
|
var component = ng.getComponent(cards[0]); // Angular DevTools
|
|
console.log(component);
|
|
|
|
// Methode 3: Network-Tab
|
|
// Schauen ob API-Call gemacht wird nach Drop
|
|
```
|
|
|
|
**Erwartete Möglichkeiten:**
|
|
- API-Call zu `/api/assets/{id}/checkout`
|
|
- Angular Event: `cdkDropListDropped`
|
|
- Component-Methode: `onAssetDropped()` oder ähnlich
|
|
- Modal-Service: `ModalService.show('checkout-dialog')`
|
|
|
|
### 2. Asset-ID extrahieren
|
|
|
|
Die Asset-ID wird benötigt für den Popup-Trigger:
|
|
|
|
```javascript
|
|
// Asset-ID ist wahrscheinlich in:
|
|
// - Element-ID: "anPGZszKzgKaSz1SIx2HFgduy"
|
|
// - Image-URL: "./GlobalDAM JRI_files/anPGZszKzgKaSz1SIx2HFgduy"
|
|
// - Data-Attribut: data-asset-id
|
|
|
|
function extractAssetId(element) {
|
|
// Aus Element-ID
|
|
if (element.id && element.id.match(/^a[A-Za-z0-9_-]+$/)) {
|
|
return element.id;
|
|
}
|
|
|
|
// Aus Bild-URL
|
|
var img = element.querySelector('img');
|
|
if (img && img.src) {
|
|
var match = img.src.match(/([A-Za-z0-9_-]{20,})/);
|
|
if (match) return match[1];
|
|
}
|
|
|
|
return null;
|
|
}
|
|
```
|
|
|
|
### 3. Popup programmatisch öffnen
|
|
|
|
Sobald wir wissen wie, implementieren wir:
|
|
|
|
```python
|
|
# Python (Qt)
|
|
class DragBridge(QObject):
|
|
@Slot(str)
|
|
def on_file_dropped_success(self, local_path: str):
|
|
"""Called after successful file drop."""
|
|
# Extrahiere Asset-ID aus Pfad oder URL-Mapping
|
|
asset_id = self.extract_asset_id(local_path)
|
|
|
|
# Trigger Popup via JavaScript
|
|
js_code = f"window.trigger_checkout_popup('{asset_id}')"
|
|
self.web_view.page().runJavaScript(js_code)
|
|
```
|
|
|
|
## ⚡ Quick Win: Debugging aktivieren
|
|
|
|
Fügen Sie zu **allen** JavaScript-Varianten umfangreiches Logging hinzu:
|
|
|
|
```javascript
|
|
// In bridge_script.js
|
|
|
|
// Log ALLE Events
|
|
['dragstart', 'drag', 'dragenter', 'dragover', 'drop', 'dragend'].forEach(function(eventName) {
|
|
document.addEventListener(eventName, function(e) {
|
|
console.log('[DEBUG]', eventName, {
|
|
target: e.target.tagName,
|
|
dataTransfer: {
|
|
types: e.dataTransfer.types,
|
|
effectAllowed: e.dataTransfer.effectAllowed,
|
|
dropEffect: e.dataTransfer.dropEffect
|
|
},
|
|
altKey: e.altKey,
|
|
coordinates: {x: e.clientX, y: e.clientY}
|
|
});
|
|
}, true);
|
|
});
|
|
|
|
// Log DataTransfer Zugriffe
|
|
Object.defineProperty(DataTransfer.prototype, 'types', {
|
|
get: function() {
|
|
var types = this._types || [];
|
|
console.log('[DEBUG] DataTransfer.types accessed:', types);
|
|
return types;
|
|
}
|
|
});
|
|
```
|
|
|
|
## 📝 Empfehlung
|
|
|
|
### Current Status (as of March 2026)
|
|
|
|
✅ **Phase 1 Complete:**
|
|
- File-drop via native Qt drag operations is fully functional
|
|
- JavaScript bridge (`bridge_script_intercept.js`) successfully intercepts and converts drags
|
|
- Path validation and Azure URL mapping working
|
|
- Tested with real applications (InDesign, Word, etc.)
|
|
|
|
### For Future Enhancement (Phase 2 - Popup Trigger)
|
|
|
|
**If popup trigger integration is needed:**
|
|
|
|
1. 🔍 **Reverse-Engineering the Target Web App:**
|
|
- Identify how popups are triggered (API call, component method, event, etc.)
|
|
- Use browser DevTools:
|
|
- Network tab → Monitor API calls
|
|
- Console → Check for JavaScript errors/logs
|
|
- Elements → Inspect component structure
|
|
- Angular/Vue DevTools if applicable
|
|
|
|
2. 🛠️ **Implement Popup Trigger:**
|
|
- Create JavaScript hook function (e.g., `window.trigger_popup(assetId)`)
|
|
- Connect to drop success signal from Qt
|
|
- Call popup trigger after successful file drop
|
|
|
|
3. 🧪 **Test Integration:**
|
|
- Verify file drops successfully
|
|
- Verify popup appears after drop
|
|
- Test with real assets/files
|
|
|
|
**Alternative Approaches:**
|
|
|
|
- **Lösung B (Manual)**: Keep file drop and popup as separate user actions
|
|
- **Lösung C (Complex)**: Use overlay window approach (more involved)
|
|
|
|
Current implementation uses **Phase 1 of Lösung A** and is production-ready.
|