Drive page and picker
The media-drive plugin ships two surfaces for working with media: a Drive custom page that browses the catalog, and a picker form field that selects an existing record or uploads a new one. Both route through Spatie Media Library on the s3 disk.
The Drive page
DrivePage is a Filament Page registered by MediaDrivePlugin at slug drive. It renders the filament-media-drive::pages.drive-browser Blade view, which lists MediaDriveCatalog::visibleTo($user) — every Media row on the s3 disk the user is allowed to view, newest first.
Two header actions switch the layout:
grid(default) — responsive card grid (Squares2x2).list— single-column rows (Bars3).
setLayout() flips the public viewMode property between grid and list; the browser re-renders via Livewire. A third action, attach, commits the picker state on the page. The page itself carries a MediaPicker field so an editor can pin a media id from the same view.
// DrivePage.php
protected static ?string $slug = 'drive';
protected static bool $shouldRegisterNavigation = false;
public static function canAccess(): bool
{
return Gate::forUser(auth()->user())->allows('viewAny', Media::class);
}
shouldRegisterNavigation = false keeps Drive out of the panel sidebar in the published template — Media Library is the nav entry. The route /drive still resolves, so the picker modal and direct links work. A clone re-enables the sidebar item by overriding shouldRegisterNavigation = true on a subclass (or via PageConfiguration), without touching the package.
The picker field
MediaPicker is a Filament Field rendering forms.components.media-picker. It lists getVisibleMedia() (same catalog, same gate) as clickable buttons that $entangle the selected Media id into form state. A validation rule rejects ids the user cannot view via MediaDriveCatalog::canAttach().
MediaPicker::make('thumbnail')
->label('Thumbnail')
For uploads — including collection-bound thumbnails — use MediaLibraryFileUpload, the package's subclass of SpatieMediaLibraryFileUpload. It forces the s3 disk and stores through EditorImageStore, returning the new Media uuid as the field state.
MediaLibraryFileUpload::make('thumbnail')
->collection('thumbnail')
->disk('s3')
How a selection attaches
A picked id is stored as the model attribute (e.g. thumbnail column or a Spatie collection reference). A fresh upload goes through EditorImageStore::store(): the Livewire TemporaryUploadedFile is copied to a real local temp file, then $model->addMedia($source)->toMediaCollection($collection, 's3') runs. The target model is the record when it implements HasMedia and exists, otherwise the authenticated user (who must implement HasMedia). Collections resolve to body when registered, else uploads.
Authorization
Shield emits the Spatie permission rows that back the Media policy. viewAny gates the Drive page (canAccess); view gates both the picker list and per-item attach. No permission, no entry and no option.
flowchart LR
Form[Form: MediaPicker / MediaLibraryFileUpload] --> Modal[Picker modal]
Modal --> Drive[Drive page: grid/list catalog]
Drive -->|select existing| StoreID[Store media id on model]
Modal -->|upload new| Spatie[EditorImageStore: addMedia]
Spatie --> S3[(s3 disk)]
S3 --> NewMedia[New Media row]
NewMedia --> StoreID