# Media Manager V2 Design & Architecture ## Overview The **Media Manager V2** transforms the product image management experience from a simple upload utility to a full-featured "WYSIWYG" editor. It introduces a persistent "Draft" state, drag-and-drop reordering, and a robust generic synchronization engine that reconciles state between Google Drive (Source of Truth) and Shopify. ## UI UX Design ### Launch Logic To work around Google Apps Script limitations (triggers cannot open modals): 1. **Watcher Sidebar**: A lightweight sidebar remains open, polling for selection changes. 2. **Context Action**: When a user selects a cell in **Column A** (Product Image), the sidebar presents a large **"Edit Media"** button. 3. **Modal**: Clicking the button launches the full Media Manager Modal. ### Interface Features - **Grid Layout**: Drag-and-drop sortable grid. - **Badges**: - ☁️ **Drive Only**: New uploads or files not yet synced. - 🛍️ **Shopify Only**: Media found on Shopify but missing from Drive (will be backfilled). - ✅ **Synced**: Verifiable link between Drive and Shopify. - **Video Support**: - Grid: Videos play silently loop (`muted autoplay`). - Preview: Full modal with controls. - **Details Mode**: A togglable text view listing pending operations (e.g., "Deleting 2 files, Reordering 3..."). ![Media Manager Mockup](./images/media_manager_mockup.png) ## Data Architecture ### 1. Naming Convention Files in Drive function as the source of truth for order. - **Pattern**: `[SKU]_[Index].[Extension]` - **Example**: `TSHIRT-001_0001.jpg`, `TSHIRT-001_0002.mp4` - **Padding**: 4 digits to support >10 items cleanly. ### 2. Session Recovery (Draft State) To prevent data loss during browser refreshes or crashes, the edit state is persisted immediately to `UserProperties`. - **Storage**: `PropertiesService.getUserProperties()` - **Key**: `MEDIA_SESSION_[SKU]` - **Schema**: ```json { "schemaVersion": 1, "timestamp": 1234567890, "sku": "SKU-123", "items": [ { "id": "drive_file_id_or_shopify_id", "source": "drive|shopify|new", "filename": "original_name.jpg", "status": "active|deleted|staged", "thumbnail": "data:image..." } ] } ``` ### 3. Synchronization Logic (Two-Way Reconcile) #### Phase A: Load & Match (Read-Only) Executed when opening the manager. 1. **Fetch**: Get all Drive Files in SKU folder and all Shopify Media via GraphQL. 2. **Match**: - **Strong Verification**: `Drive.appProperties.shopify_media_id === Shopify.media.id` - **Legacy Fallback**: `Drive.name === Shopify.filename` (Only if no ID match) 3. **Conflict Resolution**: If duplicates found, prefer high-res/latest. #### Phase B: Save (Transactional) Executed when user clicks "Save". 1. **Delete**: Process items marked `deleted` (Remove from Shopify & Trash in Drive). 2. **Backfill**: Download "Shopify Only" items to Drive -> Set `appProperties`. 3. **Upload**: Upload "Drive Only" items -> Create Media -> Set `appProperties`. 4. **Reorder**: Execute `productReorderMedia` GraphQL mutation with final ID list. 5. **Finalize**: - Rename all Drive files to `SKU_{index}` sequence. - Clear `MEDIA_SESSION_[SKU]` property. ## Technical Components ### Frontend - **HTML/CSS**: Glassmorphism aesthetic (Inter font, backdrop-filter). - **JS**: Vanilla JS with HTML5 Drag & Drop API. ### Backend Services - **`MediaService`**: Orchestrates the Phase A/B logic. - **`ShopifyMediaService`**: Handles GraphQL mutations (`productCreateMedia`, `productReorderMedia`). - **`GASDriveService`**: Manages File renaming and `appProperties` metadata. ## Future Proofing - **Metadata**: We avoid relying on file hashes/sizes due to Shopify's aggressive image compression. We rely strictly on stored IDs (`appProperties`) where possible. - **Scale**: Pagination may be needed if SKUs usually exceed 50 images (current limit 250 in GraphQL). ## Development Roadmap - [ ] **Backend Implementation** - [ ] Update `getMediaForSku` to return combined state (Drive + Shopify + Session) - [ ] Implement `saveMediaChanges(sku, changes)` transaction logic - [ ] Renaming files (`SKU_####.ext`) - [ ] Deleting/Trashing files - [ ] Uploading/Backfilling - [ ] Implement Session Recovery (Read/Write `UserProperties`) - [ ] **Frontend Implementation** - [ ] **Watcher Sidebar**: Create `MediaSidebar.html` to poll for selection. - [ ] **Manager Modal**: Refactor `MediaManager.html`. - [ ] State Management (Staging) - [ ] Drag-and-Drop Grid - [ ] Preview Modal (Image + Video) - [ ] "Details..." View - [ ] **Verification** - [ ] Manual Test: Drag & Drop ordering - [ ] Manual Test: Save & Sync - [ ] Manual Test: Session Recovery (Reload browser mid-edit)