diff --git a/.github/workflows/phpstan.yml b/.github/workflows/phpstan.yml index ccfa9d9..e2aabdc 100644 --- a/.github/workflows/phpstan.yml +++ b/.github/workflows/phpstan.yml @@ -16,7 +16,7 @@ jobs: - name: Setup PHP uses: shivammathur/setup-php@v2 with: - php-version: '8.1' + php-version: '8.2' coverage: none - name: Install composer dependencies diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml index b74e2ef..93daafd 100644 --- a/.github/workflows/run-tests.yml +++ b/.github/workflows/run-tests.yml @@ -13,13 +13,19 @@ jobs: fail-fast: true matrix: os: [ubuntu-latest] - php: [8.2, 8.1] - laravel: [10.*] + php: [8.3,8.2, 8.1] + laravel: [10.*,11.*] stability: [prefer-stable] include: + - laravel: 11.* + testbench: 9.* + carbon: ^2.63 - laravel: 10.* testbench: 8.* carbon: ^2.63 + exclude: + - laravel: 11.* + php: 8.1 name: P${{ matrix.php }} - L${{ matrix.laravel }} - ${{ matrix.stability }} - ${{ matrix.os }} diff --git a/composer.json b/composer.json index 43d599e..1eaf63e 100644 --- a/composer.json +++ b/composer.json @@ -25,15 +25,15 @@ "require": { "php": "^8.1", "filament/filament": "^3.0", - "illuminate/contracts": "^10.0", - "spatie/image": "^2.2", + "illuminate/contracts": "^10.0|^11.0", + "spatie/image": "^2.2|^3.0", "spatie/laravel-package-tools": "^1.15.0" }, "require-dev": { "laravel/pint": "^1.0", - "nunomaduro/collision": "^7.9", + "nunomaduro/collision": "^7.9|^8.0", "larastan/larastan": "^2.0.1", - "orchestra/testbench": "^8.0", + "orchestra/testbench": "^8.0|^9.0", "pestphp/pest": "^2.0", "pestphp/pest-plugin-arch": "^2.0", "pestphp/pest-plugin-laravel": "^2.0", diff --git a/config/gallery-json-media.php b/config/gallery-json-media.php index 710b332..cfedb6b 100644 --- a/config/gallery-json-media.php +++ b/config/gallery-json-media.php @@ -3,7 +3,6 @@ declare(strict_types=1); // config for WebplusMultimedia\GalleryJsonMedia -use Spatie\Image\Manipulations; return [ 'disk' => 'public', @@ -13,7 +12,7 @@ 'signing_key' => 'app.key', 'driver' => 'imagick', // gd or imagick 'quality' => 80, - 'thumbnails-crop-method' => Manipulations::CROP_CENTER, + 'thumbnails-crop-method' => null, 'thumbnails-saved-format' => null, // Manipulations::FORMAT_PNG / following formats are supported: FORMAT_JPG, FORMAT_PJPG, FORMAT_PNG, FORMAT_GIF, FORMAT_WEBP and FORMAT_TIFF ], diff --git a/resources/dist/components/gallery-json-media.js b/resources/dist/components/gallery-json-media.js index ce59cb2..627efe5 100644 --- a/resources/dist/components/gallery-json-media.js +++ b/resources/dist/components/gallery-json-media.js @@ -1,4 +1,4 @@ -function u(i){return i?i>1e3*1e3?((i/(1e3*1e3)).toFixed(1)+" Mb").replace(".",","):i>1024?((i/1e3).toFixed(1)+" kb").replace(".",","):(i.toFixed(1)+" *kb").replace(".",","):"unknow size"}function f(i,s){return i instanceof File?{name:i.name,size:i.size,mime_type:i.type,is_new:!0,is_success:!1,error:!1,filekey:s,progress:0,url:URL.createObjectURL(i)}:!1}function w(i){return{_minSize:null,_maxSize:null,_acceptedFileTypes:null,minSize(s){return this._minSize=s,this},maxSize(s){return this._maxSize=s,this},fileType(s){return this._acceptedFileTypes=s,this},check(){return!U(i,this._acceptedFileTypes)||!z(i,this._maxSize)||!M(i,this._minSize)}}}function F(i,s,p){let o=i.length+p;return!(s&&o>s)}function M(i,s){return!(s&&i.size>s)}function z(i,s){return!(s&&i.size>s*1024)}function U(i,s){return s?s.filter(o=>o===i.type).length>0:!0}function m(){return("10000000-1000-4000-8000"+-1e11).replace(/[018]/g,i=>(i^crypto.getRandomValues(new Uint8Array(1))[0]&15>>i/4).toString(16))}function x(i){return{xls(){return` +function w(i){return i?i>1e3*1e3?((i/(1e3*1e3)).toFixed(1)+" Mb").replace(".",","):i>1024?((i/1e3).toFixed(1)+" kb").replace(".",","):(i.toFixed(1)+" *kb").replace(".",","):"unknow size"}function F(i,s){return i instanceof File?{name:i.name,size:i.size,mime_type:i.type,is_new:!0,is_success:!1,error:!1,filekey:s,progress:0,url:URL.createObjectURL(i)}:!1}function m(i){return{_minSize:null,_maxSize:null,_acceptedFileTypes:null,minSize(s){return this._minSize=s,this},maxSize(s){return this._maxSize=s,this},fileType(s){return this._acceptedFileTypes=s,this},check(){return!I(i,this._acceptedFileTypes)||!U(i,this._maxSize)||!z(i,this._minSize)}}}function x(i,s,c){let h=i.length+c;return!(s&&h>s)}function z(i,s){return!(s&&i.size>s)}function U(i,s){return!(s&&i.size>s*1024)}function I(i,s){return s?s.filter(h=>h===i.type).length>0:!0}function v(){return("10000000-1000-4000-8000"+-1e11).replace(/[018]/g,i=>(i^crypto.getRandomValues(new Uint8Array(1))[0]&15>>i/4).toString(16))}function y(i){return{xls(){return` @@ -19,4 +19,4 @@ function u(i){return i?i>1e3*1e3?((i/(1e3*1e3)).toFixed(1)+" Mb").replace(".",", - `},getFile(){try{if(i.mime_type.startsWith("image"))return`${i.name}`;if(i.name.toLowerCase().endsWith(".pdf"))return this.pdf();if(i.name.toLowerCase().endsWith(".xls")||i.name.toLowerCase().endsWith(".xlsx"))return this.xls();if(i.name.toLowerCase().endsWith(".doc")||i.name.toLowerCase().endsWith(".docx"))return this.word()}catch{}return this.unKnown()}}}function T({state:i,statePath:s,minSize:p,maxSize:o,maxFiles:g,isMultiple:I,isDeletable:v,isDisabled:O,isDownloadable:Z,uploadingMessage:y,isReorderable:H,acceptedFileTypes:B,hasCustomPropertiesAction:L,deleteUploadedFileUsing:b,getUploadedFilesUsing:V,removeUploadedFileUsing:D,customPropertyActionName:S,reorderUploadedFilesUsing:$}){return{state:i,statePath:s,customPropertyActionName:S,hasCustomPropertiesAction:L,isDeletable:v,isReorderable:H,lastState:null,uploadFiles:[],uploadedFileIndex:{},editingFile:{},startUpload:!1,fileKeyIndex:{},progress:0,_startSwipeX:0,stopDragging:!0,getHumanSize(e){return u(e)},uploadUsing:(e,t,r,n,h,d)=>{this.$wire.upload(`${s}.${e}`,t,c=>{r(d)},()=>{n(d)},c=>{h(d,c)})},getFileName:function(e){if(e.startsWith("blob:")||e.startsWith("livewire:"))return e;let t=e.lastIndexOf("/");return t!==-1?e.slice(t+1):e},getContentImage(e){return x(e).getFile()},saveFilesUsing(e){let t=this.$refs.galleryImages,r=function(l){l.uploadFiles.filter(k=>k.is_success===!1).length===0&&(l.dispatchFormEvent("form-processing-finished"),l.startUpload=!1)},n=l=>{this.uploadFiles[l].is_success=!0,this.uploadFiles[l].progress=0,r(this)},h=l=>{this.uploadFiles[l].progress=0,this.uploadFiles[l].error=!0,r(this)},d=(l,a)=>{this.uploadFiles[l].progress=a.detail.progress},c=e.length,C=0;if(c){if(!F(e,g,c)){new FilamentNotification().title("Max Files reach").danger().send();return}this.startUpload||this.dispatchFormEvent("form-processing-started",{message:y}),this.startUpload=!0;for(let l of Array.from(e)){if(w(l).fileType(B).maxSize(o).minSize(p).check()){new FilamentNotification().title(`File "${l.name}" invalid`).warning().send();continue}let a=f(l,m());a&&(this.uploadFiles.push({...a}),this.uploadUsing(a.filekey,l,n,h,d,this.uploadFiles.length-1),C++)}setTimeout(()=>{t.scrollTo({left:t.scrollWidth,behavior:"smooth"})},30),C===0&&(this.startUpload=!1,this.dispatchFormEvent("form-processing-finished"))}},laFileInput:{async"@change"(){let e=this.$event.target.files;await this.saveFilesUsing(e)}},onScrolling:{"@wheel.stop"(e){let t=Object.entries(this.uploadFiles).length,r=this.$refs.galleryImages,n=this.$refs.ulGalleryWrapper;if(t*320>r.clientWidth){let h=e.deltaY<0?-280:280;(e.deltaY>0&&r.scrollLeft>=0&&r.scrollLeft+r.clientWidth0)&&(e.preventDefault(),r.scrollTo({left:r.scrollLeft+h,behavior:"smooth"}))}}},pointerNone:{"@pointerenter"(e){let t=this.$refs.galleryImages;t.style.pointerEvents="none"},"@pointerleave"(e){let t=this.$refs.galleryImages;t.style.pointerEvents="auto"}},dropZone:{"@click.prevent.stop"(){this.$refs.laFileInput.click()},"@dragover.prevent.stop"(){this.$event.target.classList.contains("wm-json-media-dropzone")},async"@drop.prevent.stop"(){this.$event.target.classList.contains("wm-json-media-dropzone")&&(await this.saveFilesUsing(this.$event.dataTransfer.files),this.$refs.dropzone.classList.remove("wm-dropzone"))},"@dragenter.prevent.stop"(){this.$refs.dropzone.classList.add("wm-dropzone")},"@dragleave.prevent.stop"(){return this.$event.target===this.$refs.dropzone&&this.$refs.dropzone.classList.remove("wm-dropzone"),!1}},leftArrow:{"@click.stop"(){let e=Object.entries(this.uploadFiles).length,t=this.$refs.galleryImages;t.scrollLeft>0&&t.scroll({left:t.scrollLeft-300,behavior:"smooth"})}},rightArrow:{"@click.stop"(){let e=this.$refs.galleryImages;e.scrollLeft+e.clientWidthr?.url).reduce((t,[r,n])=>(t[n.url]=r,t),{})},async getFiles(){return await this.getUploadedFiles(),Object.entries(this.fileKeyIndex).reduce((e,[t,r])=>(r.error=!1,r.is_success=!0,r.is_new=!1,r.filekey=t,e.push({...r}),e),[])},getUpdateFileEntries:function(){return Object.entries(this.state).map((e,t)=>(delete e.deleted,{key:e}))},dispatchFormEvent:function(e,t={}){this.$el.closest("form")?.dispatchEvent(new CustomEvent(e,{composed:!0,cancelable:!0,detail:t}))},canUpload:function(){return g?Object.entries(this.uploadFiles).length{if(this.state!==void 0){if(this.state!==null&&Object.values(this.state).filter(e=>e.file.startsWith("livewire-file:")).length){this.lastState=null;return}JSON.stringify(this.getUpdateFileEntries())!==this.lastState&&(this.lastState=JSON.stringify(this.getUpdateFileEntries()),this.uploadFiles=await this.getFiles())}}),this.$watch("sortKeys",async()=>{await $(this.sortKeys)}),this.$nextTick(async()=>{this.uploadFiles=await this.getFiles()})},dropcheck:0,usedKeyboard:!1,originalIndexBeingDragged:null,indexBeingDragged:null,indexBeingDraggedOver:null,preDragOrder:null,sortKeys:null,dragstart(e){this.preDragOrder=[...this.uploadFiles],this.indexBeingDragged=e.target.getAttribute("x-ref"),this.originalIndexBeingDragged=e.target.getAttribute("x-ref"),e.dataTransfer.dropEffect="copy"},updateListOrder(e){if(this.indexBeingDragged){this.indexBeingDraggedOver=e.target.getAttribute("x-ref");let t=this.indexBeingDragged,r=this.indexBeingDraggedOver;if(this.indexBeingDragged===r||t===r)return;this.move(t,r),this.indexBeingDragged=r}},setParentDraggable(e){e.target.closest("li").setAttribute("draggable",!0)},setParentNotDraggable(e){e.target.closest("li").setAttribute("draggable",!1)},resetState(){this.dropcheck=0,this.indexBeingDragged=null,this.preDragOrder=[...this.uploadFiles],this.indexBeingDraggedOver=null,this.originalIndexBeingDragged=null},revertState(){this.uploadFiles=this.preDragOrder.length?this.preDragOrder:this.uploadFiles,this.resetState()},rePositionPlaceholder(){this.uploadFiles=[...this.preDragOrder],this.indexBeingDragged=this.originalIndexBeingDragged},move(e,t){let r=this.uploadFiles;if(t>=r.length){let n=t-r.length+1;for(;n--;)r.push(void 0)}r.splice(t,0,r.splice(e,1)[0]),this.uploadFiles=r},getSort(){if(this.indexBeingDragged===this.originalIndexBeingDragged)return null;this.sortKeys=this.uploadFiles.map(e=>e.filekey)}}}export{T as galleryFileUpload}; + `},getFile(){try{if(i.mime_type.startsWith("image"))return`${i.name}`;if(i.name.toLowerCase().endsWith(".pdf"))return this.pdf();if(i.name.toLowerCase().endsWith(".xls")||i.name.toLowerCase().endsWith(".xlsx"))return this.xls();if(i.name.toLowerCase().endsWith(".doc")||i.name.toLowerCase().endsWith(".docx"))return this.word()}catch{}return this.unKnown()}}}function A({state:i,statePath:s,minSize:c,maxSize:h,maxFiles:u,isMultiple:O,isDeletable:H,isDisabled:Z,isDownloadable:_,uploadingMessage:B,isReorderable:L,acceptedFileTypes:b,hasCustomPropertiesAction:V,deleteUploadedFileUsing:D,getUploadedFilesUsing:S,removeUploadedFileUsing:$,customPropertyActionName:k,reorderUploadedFilesUsing:M}){return{state:i,statePath:s,customPropertyActionName:k,hasCustomPropertiesAction:V,isDeletable:H,isReorderable:L,lastState:null,uploadFiles:[],uploadedFileIndex:{},editingFile:{},startUpload:!1,fileKeyIndex:{},progress:0,_startSwipeX:0,stopDragging:!0,getHumanSize(e){return w(e)},uploadUsing:(e,t,r,n,d,p)=>{this.$wire.upload(`${s}.${e}`,t,g=>{r(p)},()=>{n(p)},g=>{d(p,g)})},getFileName:function(e){if(e.startsWith("blob:")||e.startsWith("livewire:"))return e;let t=e.lastIndexOf("/");return t!==-1?e.slice(t+1):e},getContentImage(e){return y(e).getFile()},saveFilesUsing(e){let t=this.$refs.galleryImages,r=function(l){let o=l.uploadFiles.filter(a=>a.is_success===!1).length,f=l.uploadFiles.filter(a=>a.error===!0).length;o-f===0&&(l.dispatchFormEvent("form-processing-finished"),f&&(l.uploadFiles=l.uploadFiles.filter(a=>!a.error).map(a=>(a.error=!1,a))),l.startUpload=!1)},n=l=>{this.uploadFiles[l].is_success=!0,this.uploadFiles[l].progress=0,r(this)},d=l=>{this.uploadFiles[l].progress=0,this.uploadFiles[l].error=!0,r(this)},p=(l,o)=>{this.uploadFiles[l].progress=o.detail.progress},g=e.length,C=0;if(g){if(!x(e,u,g)){new FilamentNotification().title("Max Files reach").danger().send();return}this.startUpload||this.dispatchFormEvent("form-processing-started",{message:B}),this.startUpload=!0;for(let l of Array.from(e)){if(m(l).fileType(b).maxSize(h).minSize(c).check()){new FilamentNotification().title(`File "${l.name}" invalid`).warning().send();continue}let o=F(l,v());o&&(this.uploadFiles.push({...o}),this.uploadUsing(o.filekey,l,n,d,p,this.uploadFiles.length-1),C++)}setTimeout(()=>{t.scrollTo({left:t.scrollWidth,behavior:"smooth"})},30),C===0&&(this.startUpload=!1,this.dispatchFormEvent("form-processing-finished"))}},laFileInput:{async"@change"(){let e=this.$event.target.files;await this.saveFilesUsing(e)}},onScrolling:{"@wheel.stop"(e){let t=Object.entries(this.uploadFiles).length,r=this.$refs.galleryImages,n=this.$refs.ulGalleryWrapper;if(t*320>r.clientWidth){let d=e.deltaY<0?-280:280;(e.deltaY>0&&r.scrollLeft>=0&&r.scrollLeft+r.clientWidth0)&&(e.preventDefault(),r.scrollTo({left:r.scrollLeft+d,behavior:"smooth"}))}}},pointerNone:{"@pointerenter"(e){let t=this.$refs.galleryImages;t.style.pointerEvents="none"},"@pointerleave"(e){let t=this.$refs.galleryImages;t.style.pointerEvents="auto"}},dropZone:{"@click.prevent.stop"(){this.$refs.laFileInput.click()},"@dragover.prevent.stop"(){this.$event.target.classList.contains("wm-json-media-dropzone")},async"@drop.prevent.stop"(){this.$event.target.classList.contains("wm-json-media-dropzone")&&(await this.saveFilesUsing(this.$event.dataTransfer.files),this.$refs.dropzone.classList.remove("wm-dropzone"))},"@dragenter.prevent.stop"(){this.$refs.dropzone.classList.add("wm-dropzone")},"@dragleave.prevent.stop"(){return this.$event.target===this.$refs.dropzone&&this.$refs.dropzone.classList.remove("wm-dropzone"),!1}},leftArrow:{"@click.stop"(){let e=Object.entries(this.uploadFiles).length,t=this.$refs.galleryImages;t.scrollLeft>0&&t.scroll({left:t.scrollLeft-300,behavior:"smooth"})}},rightArrow:{"@click.stop"(){let e=this.$refs.galleryImages;e.scrollLeft+e.clientWidthr?.url).reduce((t,[r,n])=>(t[n.url]=r,t),{})},async getFiles(){return await this.getUploadedFiles(),Object.entries(this.fileKeyIndex).reduce((e,[t,r])=>(r.error=!1,r.is_success=!0,r.is_new=!1,r.filekey=t,e.push({...r}),e),[])},getUpdateFileEntries:function(){return Object.entries(this.state).map((e,t)=>(delete e.deleted,{key:e}))},dispatchFormEvent:function(e,t={}){this.$el.closest("form")?.dispatchEvent(new CustomEvent(e,{composed:!0,cancelable:!0,detail:t}))},canUpload:function(){return u?Object.entries(this.uploadFiles).length{if(this.state!==void 0){if(this.state!==null&&Object.values(this.state).filter(e=>e.file.startsWith("livewire-file:")).length){this.lastState=null;return}JSON.stringify(this.getUpdateFileEntries())!==this.lastState&&(this.lastState=JSON.stringify(this.getUpdateFileEntries()),this.uploadFiles=await this.getFiles())}}),this.$watch("sortKeys",async()=>{await M(this.sortKeys)}),this.$nextTick(async()=>{this.uploadFiles=await this.getFiles()})},dropcheck:0,usedKeyboard:!1,originalIndexBeingDragged:null,indexBeingDragged:null,indexBeingDraggedOver:null,preDragOrder:null,sortKeys:null,dragstart(e){this.preDragOrder=[...this.uploadFiles],this.indexBeingDragged=e.target.getAttribute("x-ref"),this.originalIndexBeingDragged=e.target.getAttribute("x-ref"),e.dataTransfer.dropEffect="copy"},updateListOrder(e){if(this.indexBeingDragged){this.indexBeingDraggedOver=e.target.getAttribute("x-ref");let t=this.indexBeingDragged,r=this.indexBeingDraggedOver;if(this.indexBeingDragged===r||t===r)return;this.move(t,r),this.indexBeingDragged=r}},setParentDraggable(e){e.target.closest("li").setAttribute("draggable",!0)},setParentNotDraggable(e){e.target.closest("li").setAttribute("draggable",!1)},resetState(){this.dropcheck=0,this.indexBeingDragged=null,this.preDragOrder=[...this.uploadFiles],this.indexBeingDraggedOver=null,this.originalIndexBeingDragged=null},revertState(){this.uploadFiles=this.preDragOrder.length?this.preDragOrder:this.uploadFiles,this.resetState()},rePositionPlaceholder(){this.uploadFiles=[...this.preDragOrder],this.indexBeingDragged=this.originalIndexBeingDragged},move(e,t){let r=this.uploadFiles;if(t>=r.length){let n=t-r.length+1;for(;n--;)r.push(void 0)}r.splice(t,0,r.splice(e,1)[0]),this.uploadFiles=r},getSort(){if(this.indexBeingDragged===this.originalIndexBeingDragged)return null;this.sortKeys=this.uploadFiles.map(e=>e.filekey)}}}export{A as galleryFileUpload}; diff --git a/resources/js/index.js b/resources/js/index.js index b839235..5566bbc 100644 --- a/resources/js/index.js +++ b/resources/js/index.js @@ -78,10 +78,17 @@ export function galleryFileUpload( /**@type {HTMLElement} */ const wrapper = this.$refs.galleryImages const stopUploading = function(component) { - let rest = component.uploadFiles.filter(f => f.is_success === false).length + let rest = component.uploadFiles.filter(f => f.is_success === false).length, + numberErrors = component.uploadFiles.filter(f => f.error === true).length - if (rest === 0) { + if ((rest - numberErrors) === 0) { component.dispatchFormEvent('form-processing-finished') + if(numberErrors) { + // Removed thumbnails with no upload + component.uploadFiles = component.uploadFiles + .filter(file => !file.error) + .map(file =>{ file.error = false; return file }) + } component.startUpload = false } } @@ -91,7 +98,6 @@ export function galleryFileUpload( stopUploading(this) } const error = (fileKey) => { - //delete this.uploadFiles[fileKey] this.uploadFiles[fileKey].progress = 0 this.uploadFiles[fileKey].error = true stopUploading(this) diff --git a/src/JsonMedia/ImageManipulation/Croppa.php b/src/JsonMedia/ImageManipulation/Croppa.php index 5835603..713a2ac 100644 --- a/src/JsonMedia/ImageManipulation/Croppa.php +++ b/src/JsonMedia/ImageManipulation/Croppa.php @@ -9,7 +9,6 @@ use Spatie\Image\Exceptions\InvalidImageDriver; use Spatie\Image\Exceptions\InvalidManipulation; use Spatie\Image\Image; -use Spatie\Image\Manipulations; final class Croppa { @@ -34,28 +33,18 @@ public function url(): string */ public function render(): void { - $image = Image::load($this->filesystem->path($this->filePath)) - ->useImageDriver(config('gallery-json-media.images.driver')); - - $manipulations = new Manipulations(); - $manipulations->quality(config('gallery-json-media.images.quality')); - - if ($this->width and $this->height) { - $manipulations->crop( - cropMethod: config('gallery-json-media.images.thumbnails-crop-method'), - width: $this->width, - height: $this->height - ); - } else { - if ($this->width) { - $manipulations->width($this->width); - } - if ($this->height) { - $manipulations->height($this->height); - } + $image = Image::useImageDriver(config('gallery-json-media.images.driver')) + ->load($this->filesystem->path($this->filePath)) + ->quality(config('gallery-json-media.images.quality')); + + if ($this->width) { + $image->width($this->width); + } + if ($this->height) { + $image->height($this->height); } - $image->manipulate($manipulations) - ->save($this->filesystem->path($this->getPathNameForThumbs())); + + $image->save($this->filesystem->path($this->getPathNameForThumbs())); } protected function getPathNameForThumbs(): string