diff --git a/demo/app/Sharp/Posts/PostForm.php b/demo/app/Sharp/Posts/PostForm.php index bd0c6538f..ee2c40812 100644 --- a/demo/app/Sharp/Posts/PostForm.php +++ b/demo/app/Sharp/Posts/PostForm.php @@ -67,7 +67,7 @@ public function buildFormFields(FieldsContainer $formFields): void SharpFormEditorUpload::make() ->setStorageDisk('local') ->setStorageBasePath('data/posts/{id}/embed') - ->setMaxFileSize(1) + ->setMaxFileSize(2) ->setHasLegend() ) ->setMaxLength(2000) @@ -126,8 +126,8 @@ public function buildFormFields(FieldsContainer $formFields): void ) ->addItemField( SharpFormUploadField::make('document') - ->setMaxFileSize(1) - ->setAllowedExtensions(['pdf', 'zip']) + ->setMaxFileSize(2) + ->setAllowedExtensions(['pdf', 'zip', 'mp4', 'mp3']) ->setStorageDisk('local') ->setStorageBasePath('data/posts/{id}') ->addConditionalDisplay('!is_link'), @@ -203,7 +203,7 @@ public function find($id): array return $this ->setCustomTransformer('author_id', fn ($value, Post $instance) => $instance->author) ->setCustomTransformer('cover', new SharpUploadModelFormAttributeTransformer()) - ->setCustomTransformer('attachments[document]', new SharpUploadModelFormAttributeTransformer()) + ->setCustomTransformer('attachments[document]', new SharpUploadModelFormAttributeTransformer(withPlayablePreview: true)) ->transform(Post::with('cover', 'attachments', 'categories')->findOrFail($id)); } diff --git a/demo/app/Sharp/Posts/PostShow.php b/demo/app/Sharp/Posts/PostShow.php index 25a4fa9fa..a2bcbc759 100644 --- a/demo/app/Sharp/Posts/PostShow.php +++ b/demo/app/Sharp/Posts/PostShow.php @@ -154,7 +154,7 @@ public function find(mixed $id): array ->setCustomTransformer('cover', new SharpUploadModelThumbnailUrlTransformer(500)) ->setCustomTransformer( 'attachments[document]', - new SharpUploadModelFormAttributeTransformer(withThumbnails: true) + new SharpUploadModelFormAttributeTransformer(withPlayablePreview: true) ) ->setCustomTransformer('attachments[link_url]', fn ($value, $instance) => $instance->is_link ? sprintf('%s', $value, str($value)->limit(30)) diff --git a/demo/config/filesystems.php b/demo/config/filesystems.php index cf5abce76..a63ac647c 100644 --- a/demo/config/filesystems.php +++ b/demo/config/filesystems.php @@ -33,6 +33,7 @@ 'local' => [ 'driver' => 'local', 'root' => storage_path('app'), + 'serve' => true, ], 'public' => [ diff --git a/docs/guide/sharp-uploads.md b/docs/guide/sharp-uploads.md index 942c62bc2..81d4b60b8 100644 --- a/docs/guide/sharp-uploads.md +++ b/docs/guide/sharp-uploads.md @@ -336,3 +336,26 @@ $this->addField( ``` In this code, the `legend` designates a custom attribute. + +## Preview audio or video upload + +If the field allows to upload an audio or video file, you can display a preview of it by specifying the `withPlayablePreview` option: + +```php +class MyForm extends SharpForm +{ + // ... + function find($id): array + { + return $this + ->setCustomTransformer( + 'video', + new SharpUploadModelFormAttributeTransformer(withPlayablePreview: true) + ) + ->transform(Book::with('video')->findOrFail($id)); + } +``` + +::: warning +This feature is using Laravel's file [Temporary URL](https://laravel.com/docs/12.x/filesystem#temporary-urls) feature which only supports S3 & local driver. +::: diff --git a/resources/js/form/components/fields/upload/Upload.vue b/resources/js/form/components/fields/upload/Upload.vue index 4840066ab..54be7fdc4 100644 --- a/resources/js/form/components/fields/upload/Upload.vue +++ b/resources/js/form/components/fields/upload/Upload.vue @@ -68,6 +68,7 @@ }>(); const form = useParentForm(); const transformedImg = ref(); + const playablePreviewUrl = ref(); const uppyFile = ref>(); const isEditable = computed(() => { return props.value && canTransform(props.value.name, props.value.mime_type) && !props.hasError @@ -135,6 +136,8 @@ const blob = await response.blob(); transformedImg.value = URL.createObjectURL(blob); } + } else if(file.type?.startsWith('video/') || file.type?.startsWith('audio/')) { + playablePreviewUrl.value = URL.createObjectURL(file.data); } }) .on('restriction-failed', (file, error) => { @@ -350,6 +353,7 @@ uppy.removeFile(uppyFile.value.id); uppyFile.value = null; transformedImg.value = null; + playablePreviewUrl.value = null; editModalImageUrl.value = null; } } @@ -382,6 +386,9 @@ if(!props.persistThumbnailUrl && transformedImg.value) { URL.revokeObjectURL(transformedImg.value); } + if(playablePreviewUrl.value) { + URL.revokeObjectURL(playablePreviewUrl.value); + } emit('uploading', false); }); @@ -392,69 +399,83 @@