webdrop-bridge/docs/ANGULAR_CDK_ANALYSIS.md
claudi dee02ad600 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.
2026-02-17 19:19:14 +01:00

268 lines
7.8 KiB
Markdown

# Angular CDK Drag & Drop Analysis - GlobalDAM
## Framework Detection
**Web Application:** Agravity GlobalDAM
**Framework:** Angular 19.2.14
**Drag & Drop:** Angular CDK (Component Dev Kit)
**Styling:** TailwindCSS
## Technical Findings
### 1. Angular CDK Implementation
```html
<!-- Drag Group (oberste Ebene) -->
<div cdkdroplistgroup="" aydnd="" class="flex h-full flex-col">
<!-- Drop Zone (Collections) -->
<div cdkdroplist="" class="cdk-drop-list" id="collectioncsuaaDVNokl0...">
<!-- Draggable Element (Asset Card) -->
<li cdkdrag="" class="cdk-drag asset-list-item" draggable="false">
<img src="./GlobalDAM JRI_files/anPGZszKzgKaSz1SIx2HFgduy"
alt="weiss_ORIGINAL">
</li>
</div>
</div>
```
### 2. Key Observations
#### Native HTML5 Drag ist DEAKTIVIERT
```html
draggable="false"
```
**Bedeutung:**
- Kein Zugriff auf native `dragstart`, `drag`, `dragend` Events
- Kein `event.dataTransfer` API verfügbar
- Angular CDK simuliert Drag & Drop komplett in JavaScript
- Daten werden NICHT über natives Clipboard/DataTransfer übertragen
#### Angular CDK Direktiven
- `cdkdroplistgroup` - Gruppiert mehrere Drop-Zonen
- `cdkdroplist` - Markiert Drop-Bereiche (Collections, Clipboard)
- `cdkdrag` - Markiert draggbare Elemente (Assets)
- `cdkdroplistsortingdisabled` - Sortierung deaktiviert
#### Asset Identifikation
```html
<!-- Asset ID im Element-ID -->
<div id="anPGZszKzgKaSz1SIx2HFgduy">
<!-- Asset ID in der Bild-URL -->
<img src="./GlobalDAM JRI_files/anPGZszKzgKaSz1SIx2HFgduy">
<!-- Asset Name im alt-Attribut -->
<img alt="weiss_ORIGINAL">
```
## Impact on WebDrop Bridge
### ❌ Bisheriger Ansatz funktioniert NICHT
Unser aktueller Ansatz basiert auf:
1. Interception von nativen Drag-Events
2. Manipulation von `event.dataTransfer.effectAllowed` und `.dropEffect`
3. Setzen von URLs im DataTransfer
**Das funktioniert NICHT mit Angular CDK**, da:
- Angular CDK das native Drag & Drop komplett umgeht
- Keine nativen Events gefeuert werden
- DataTransfer API nicht verwendet wird
### ✅ Mögliche Lösungsansätze
#### Ansatz 1: JavaScript Injection zur Laufzeit
Injiziere JavaScript-Code, der Angular CDK Events abfängt:
```javascript
// Überwache Angular CDK Event-Handler
document.addEventListener('cdkDragStarted', (event) => {
const assetId = event.source.element.nativeElement.id;
const assetName = event.source.element.nativeElement.querySelector('img')?.alt;
// Sende an Qt WebChannel
bridge.handleDragStart(assetId, assetName);
});
document.addEventListener('cdkDragDropped', (event) => {
// Verhindere das Standard-Verhalten
event.preventDefault();
// Starte nativen Drag von Qt aus
bridge.initNativeDrag();
});
```
**Vorteile:**
- ✅ Direkter Zugriff auf Angular CDK Events
- ✅ Kann Asset-Informationen extrahieren
- ✅ Kann Drag-Operationen abfangen
**Nachteile:**
- ⚠️ Erfordert genaue Kenntnis der Angular CDK Internals
- ⚠️ Könnte bei Angular CDK Updates brechen
- ⚠️ Komplexer zu implementieren
#### Ansatz 2: DOM Mutation Observer
Überwache DOM-Änderungen während des Drags:
```javascript
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
// Suche nach CDK Drag-Elementen mit bestimmten Klassen
const dragElement = document.querySelector('.cdk-drag-preview');
if (dragElement) {
const assetId = dragElement.querySelector('[id^="a"]')?.id;
bridge.handleDrag(assetId);
}
});
});
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true,
attributeFilter: ['class']
});
```
**Vorteile:**
- ✅ Robuster gegenüber Framework-Updates
- ✅ Funktioniert mit beliebigen Frameworks
**Nachteile:**
- ⚠️ Performance-Overhead
- ⚠️ Kann falsche Positive erzeugen
#### Ansatz 3: Qt WebChannel Bridge mit Custom Events
Nutze Qt WebChannel, um mit der Angular-Anwendung zu kommunizieren:
```python
# Python-Seite (Qt)
class DragBridge(QObject):
@Slot(str, str)
def onAssetDragStart(self, asset_id: str, asset_name: str):
"""Called from JavaScript when Angular CDK drag starts."""
logger.info(f"Asset drag started: {asset_id} ({asset_name})")
self.convert_and_drag(asset_id, asset_name)
```
```javascript
// JavaScript-Seite (injiziert via QWebEngineScript)
new QWebChannel(qt.webChannelTransport, (channel) => {
const dragBridge = channel.objects.dragBridge;
// Monkey-patch Angular CDK's DragRef
const originalStartDraggingSequence = CdkDrag.prototype._startDraggingSequence;
CdkDrag.prototype._startDraggingSequence = function(event) {
const assetElement = this.element.nativeElement;
const assetId = assetElement.id;
const assetName = assetElement.querySelector('img')?.alt;
// Benachrichtige Qt
dragBridge.onAssetDragStart(assetId, assetName);
// Rufe original Angular CDK Methode auf
return originalStartDraggingSequence.call(this, event);
};
});
```
**Vorteile:**
- ✅ Saubere Kommunikation zwischen Qt und Web
- ✅ Kann Asset-Informationen zuverlässig extrahieren
- ✅ Typensicher (Qt Signals/Slots)
**Nachteile:**
- ⚠️ Erfordert Monkey-Patching von Angular CDK
- ⚠️ Kann bei CDK Updates brechen
#### Ansatz 4: Browser DevTools Protocol (Chrome DevTools)
Nutze Chrome DevTools Protocol für tiefere Integration:
```python
from PySide6.QtWebEngineCore import QWebEngineProfile
profile = QWebEngineProfile.defaultProfile()
profile.setRequestInterceptor(...)
# Intercepte Netzwerk-Requests und injiziere Header
# Überwache JavaScript-Execution via CDP
```
**Vorteile:**
- ✅ Sehr mächtig, kann JavaScript-Execution überwachen
- ✅ Kann Events auf niedrigerer Ebene abfangen
**Nachteile:**
- ⚠️ Sehr komplex
- ⚠️ Erfordert Chrome DevTools Protocol Kenntnisse
- ⚠️ Performance-Overhead
## Empfohlener Ansatz
### **Ansatz 3: Qt WebChannel Bridge** (BEVORZUGT)
**Begründung:**
1. ✅ Saubere Architektur mit klarer Trennung
2. ✅ Typsicher durch Qt Signals/Slots
3. ✅ Kann Asset-IDs und -Namen zuverlässig extrahieren
4. ✅ Funktioniert auch wenn Angular CDK interne Änderungen hat
5. ✅ Ermöglicht bidirektionale Kommunikation
**Implementierungsschritte:**
### Phase 1: Asset-Informationen extrahieren
1. JavaScript via QWebEngineScript injizieren
2. Qt WebChannel setuppen
3. Angular CDK Events überwachen (ohne Monkey-Patching als Test)
4. Asset-IDs und Namen an Qt senden
### Phase 2: Native Drag initiieren
1. Bei CDK Drag-Start: Extrahiere Asset-Informationen
2. Sende Asset-ID an Backend/API
3. Erhalte lokalen Dateipfad oder Azure Blob URL
4. Konvertiere zu lokalem Pfad (wie aktuell)
5. Initiiere nativen Drag mit QDrag
### Phase 3: Drag-Feedback
1. Zeige Drag-Preview in Qt (optional)
2. Update Cursor während Drag
3. Cleanup nach Drag-Ende
## Asset-ID zu Dateipfad Mapping
Die Anwendung verwendet Asset-IDs in mehreren Formaten:
```javascript
// Asset-ID: anPGZszKzgKaSz1SIx2HFgduy
// Mögliche URL-Konstruktion:
const assetUrl = `https://dev.agravity.io/api/assets/${assetId}`;
const downloadUrl = `https://dev.agravity.io/api/assets/${assetId}/download`;
const blobUrl = `https://static.agravity.io/${workspaceId}/${assetId}/${filename}`;
```
**Für WebDrop Bridge:**
- Asset-ID aus DOM extrahieren
- Asset-Metadaten via API abrufen (falls verfügbar)
- Blob-URL konstruieren
- URL Converter nutzen (bereits implementiert!)
## Next Steps
1. **Proof of Concept**: Qt WebChannel mit einfachem Event-Logger
2. **Asset-ID Extraction**: JavaScript Injection testen
3. **API Research**: GlobalDAM API untersuchen (Asset-Metadaten)
4. **Integration**: Mit bestehendem URLConverter verbinden
5. **Testing**: Mit echten Assets testen
## Hinweise
- Angular CDK Version kann sich unterscheiden - Code muss robust sein
- Asset-IDs scheinen eindeutig zu sein (Base64-ähnlich)
- Die Anwendung nutzt Azure Blob Storage (basierend auf bisherigen URLs)
- Custom Components (`ay-*`) deuten auf eine eigene Component Library hin