github tomatophp/filament-media-manager v4.0.3

14 hours ago

๐ŸŽฏ New Features

Collection Names Support

  • Multi-Picker Support - Added collection name support for multiple pickers on the same page

    • New collection_name column in media_has_models pivot table
    • Use ->collection('name') method to specify collection for each picker
    • Each picker maintains its own separate media attachments
    • Collection filtering in all trait methods
    • Backward compatible (null collection name supported)
  • Migration: 2024_10_21_000000_add_collection_name_to_media_has_models_table.php

    • Added collection_name (nullable string) column
    • Added responsive_images (boolean, default false) column
    • Supports rollback with proper column cleanup
  • Updated Methods with Collection Support:

    // Define separate collections for different pickers
    Forms\Components\MediaManagerPicker::make('featured_image')
        ->collection('featured')
        ->single();
    
    Forms\Components\MediaManagerPicker::make('gallery_images')
        ->collection('gallery')
        ->multiple();
    
    // Retrieve media by collection
    $product->getMediaManagerMedia('featured');
    $product->getMediaManagerMedia('gallery');
    $product->getMediaManagerUrl('featured');
    $product->getMediaManagerUrls('gallery');

Responsive Images Support

  • Spatie Media Library Integration - Added responsive images support using Spatie's built-in functionality

    • New ->responsiveImages() method on MediaManagerPicker
    • Automatic responsive image generation when enabled
    • Responsive images flag stored in pivot table
    • Multiple methods to retrieve responsive image URLs and srcset
  • New Trait Methods for Responsive Images:

    • getMediaManagerResponsiveImages(?string $collectionName = null) - Get media with responsive image data
    • getMediaManagerSrcset(?string $collectionName = null) - Get srcset attribute for first media
    • getMediaManagerSrcsets(?string $collectionName = null) - Get all srcset attributes
    • getMediaManagerResponsiveUrls(?string $collectionName = null) - Get responsive URLs for first media
    • getAllMediaManagerResponsiveUrls(?string $collectionName = null) - Get all responsive URLs
  • Usage Example:

    // Enable responsive images
    Forms\Components\MediaManagerPicker::make('hero_image')
        ->collection('hero')
        ->single()
        ->responsiveImages();
    
    // In Blade templates
    <img src="{{ $model->getMediaManagerUrl('hero') }}"
         srcset="{{ $model->getMediaManagerSrcset('hero') }}"
         alt="Hero Image">
    
    // Get detailed responsive data
    $responsiveImages = $model->getMediaManagerResponsiveImages('gallery');
    // Returns: ['media' => $media, 'url' => $url, 'responsive_urls' => [...], 'srcset' => '...']

Media Ordering & Reordering

  • Drag & Drop Reordering - Added drag and drop functionality to reorder media items in MediaManagerPicker

    • Visual drag handle (three bars icon) appears when multiple items are selected
    • Smooth animation during drag (150ms)
    • Ghost effect while dragging (40% opacity)
    • Cursor changes to "grab" on hover over drag handle
    • Only displays for multiple selection mode with 2+ items
    • Proper cleanup and reinitialization of Sortable instances
  • Order Column Support - Added order_column to media_has_models pivot table

    • New migration: 2024_10_20_000000_add_order_column_to_media_has_models_table.php
    • Unsigned integer column with index for performance
    • Nullable to support backward compatibility
    • Automatically managed during attach/sync operations
  • Order Persistence

    • Media items maintain their order across save/load operations
    • Order preserved when using attachMediaManagerMedia()
    • Order preserved when using syncMediaManagerMedia()
    • Order reflected in all getMediaManagerMedia() calls
    • Order properly hydrated when editing existing records

๐Ÿ”ง Bug Fixes

MediaManagerPicker Selection Issues

  • Fixed: Media selection not being set to form - Resolved inconsistent event detail structure

    • Changed from direct data to wrapped structure: { media: ... }
    • Ensures reliable state updates across all scenarios
    • Handles both single and multiple selection modes
    • Fixed race conditions with isProcessing flag
  • Fixed: Reordering persistence - Completely rewrote view logic for reliable drag & drop

    • Server-side ordering now respects state array order
    • Alpine.js state properly synced with Livewire
    • Added wire:key for proper Livewire DOM tracking
    • State watcher reinitializes Sortable after re-renders
    • Prevents order from reverting after drag operations

InteractsWithMediaManager Trait Updates

  • Collection Name Parameter - Changed getMediaManagerUrl() and getMediaManagerUrls() methods

    • Previously: Accepted $conversion parameter for image transformations
    • Now: Accepts $collectionName parameter to filter by media collection
    • More useful for retrieving specific media groups (e.g., 'gallery', 'thumbnails', 'documents')
    • Breaking change from previous implementation
  • Updated Methods with Ordering:

    // Now returns media in order
    $product->getMediaManagerMedia('gallery');
    $product->getMediaManagerUrl('thumbnails'); // Get first from thumbnails collection
    $product->getMediaManagerUrls('documents'); // Get all URLs from documents collection
    
    // Order is preserved when syncing
    $product->syncMediaManagerMedia(['uuid-3', 'uuid-1', 'uuid-2']);

๐Ÿ“ Technical Changes

Migration Changes

  • media_has_models table:
    • Added order_column (unsigned integer, nullable, indexed)
    • Supports rollback with proper index cleanup

View Refactoring

  • resources/views/forms/media-manager-picker.blade.php
    • Complete rewrite with cleaner Alpine.js logic
    • Removed complex nested x-data scopes
    • Server-side rendering with proper ordering
    • Simplified Sortable.js initialization
    • Added proper instance cleanup on destroy
    • Uses wire:key for DOM tracking
    • State watcher for automatic Sortable reinitialization

Backend Updates

  • src/Form/MediaManagerPicker.php

    • Added $collectionName property and collection() method
    • Added $generateResponsiveImages property and responsiveImages() method
    • Added shouldGenerateResponsiveImages() getter method
    • afterStateHydrated(): Now loads and sorts media by order_column and filters by collection_name
    • saveRelationshipsUsing(): Saves media with sequential order values, collection name, and responsive images flag
    • Generates responsive images when flag is enabled
  • src/Traits/InteractsWithMediaManager.php

    • Collection Name Support: All methods updated to accept optional $collectionName parameter
    • getMediaManagerMedia(?string $collectionName): Filters by collection name and returns sorted by order
    • attachMediaManagerMedia(array $uuids, ?string $collectionName): Supports collection-specific attachments
    • detachMediaManagerMedia(?array $uuids, ?string $collectionName): Supports collection-specific detachment
    • syncMediaManagerMedia(array $uuids, ?string $collectionName): Collection-aware sync operation
    • hasMediaManagerMedia(string $uuid, ?string $collectionName): Collection-aware existence check
    • getFirstMediaManagerMedia(?string $collectionName): Returns first from specific collection
    • getMediaManagerUrl(?string $collectionName): Gets URL from specific collection
    • getMediaManagerUrls(?string $collectionName): Gets all URLs from specific collection
    • New Responsive Images Methods:
      • getMediaManagerResponsiveImages(?string $collectionName): Get media with responsive data
      • getMediaManagerSrcset(?string $collectionName): Get srcset for first media
      • getMediaManagerSrcsets(?string $collectionName): Get all srcsets
      • getMediaManagerResponsiveUrls(?string $collectionName): Get responsive URLs for first media
      • getAllMediaManagerResponsiveUrls(?string $collectionName): Get all responsive URLs
  • src/Livewire/MediaPicker.php

    • selectMedia(): Fixed event detail structure with consistent wrapping

๐Ÿงช Testing

  • โœ… All 97 existing tests passing
  • โœ… Order persistence tested across all trait methods
  • โœ… Drag and drop functionality verified
  • โœ… State synchronization tested
  • โœ… Collection filtering tested
  • โœ… Backward compatibility maintained

โš ๏ธ Breaking Changes

  • InteractsWithMediaManager Trait:
    • getMediaManagerUrl(?string $collectionName = null) - Parameter changed from $conversion to $collectionName
    • getMediaManagerUrls(?string $collectionName = null) - Parameter changed from $conversion to $collectionName
    • If you were using these methods with conversion parameters, you'll need to update your code
    • Image conversions should now be handled separately using Spatie Media Library's conversion methods

๐Ÿ“‹ Migration Guide

If upgrading from v4.0.0 or v4.0.2:

  1. Run the new migrations:

    php artisan migrate

    This will add:

    • order_column (if upgrading from v4.0.0)
    • collection_name column
    • responsive_images column
  2. Update trait method calls if using conversions:

    // Old (v4.0.0)
    $product->getMediaManagerUrl('thumb'); // Got thumbnail conversion
    
    // New (v4.0.3)
    $product->getMediaManagerUrl('gallery'); // Gets first from 'gallery' collection
    
    // For conversions, use Spatie directly:
    $media = $product->getFirstMediaManagerMedia('gallery');
    $thumbnailUrl = $media?->getUrl('thumb');
  3. Using multiple pickers on the same page:

    // Now you can use collection names to separate pickers
    Forms\Components\MediaManagerPicker::make('featured_image')
        ->collection('featured')
        ->single();
    
    Forms\Components\MediaManagerPicker::make('gallery_images')
        ->collection('gallery')
        ->multiple();
    
    // Each will maintain separate media attachments
  4. Using responsive images:

    // Enable responsive images
    Forms\Components\MediaManagerPicker::make('hero_image')
        ->collection('hero')
        ->responsiveImages();
    
    // Retrieve responsive images
    $srcset = $model->getMediaManagerSrcset('hero');
  5. Backward Compatibility:

    • Existing media without order_column values will still work (nullable column). Order will be applied on next save.
    • Existing media without collection_name will work as before (defaults to null)
    • Responsive images are opt-in via ->responsiveImages() method

Full Changelog: v4.0.2...v4.0.3

Don't miss a new filament-media-manager release

NewReleases is sending notifications on new releases.