Skip to content

Commit 1f3bd3a

Browse files
committed
Fix multi-file upload cancellation in media picker modal
1 parent b0d3be4 commit 1f3bd3a

1 file changed

Lines changed: 43 additions & 10 deletions

File tree

packages/media/src/Http/Livewire/MediaPickerModal.php

Lines changed: 43 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use Illuminate\Support\Facades\Auth;
1616
use Illuminate\Support\Facades\DB;
1717
use Livewire\Component;
18+
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
1819
use Livewire\WithPagination;
1920
use Moox\Core\Support\Scopes\ScopeValue;
2021
use Moox\Localization\Models\Localization;
@@ -275,10 +276,12 @@ public function form(Schema $schema): Schema
275276
->disabled(fn (): bool => $this->shouldLockCollectionSelection())
276277
->live();
277278

279+
// Same approach as ListMedia: do not use live() + $set('files', null).
280+
// Clearing the FileUpload mid-batch cancels sibling uploads when multiple
281+
// files are selected at once. Skip already handled files via hash.
278282
$upload = FileUpload::make('files')
279283
->label(__('media::fields.upload'))
280-
->live()
281-
->afterStateUpdated(function ($state, $get, $set) {
284+
->afterStateUpdated(function ($state, $get) {
282285
if (! $state) {
283286
return;
284287
}
@@ -290,17 +293,19 @@ public function form(Schema $schema): Schema
290293
$files = is_array($state) ? $state : [$state];
291294

292295
foreach ($files as $tempFile) {
293-
if (! $tempFile || ! file_exists($tempFile->getRealPath())) {
296+
$realPath = $this->temporaryUploadPath($tempFile);
297+
298+
if ($realPath === null) {
294299
continue;
295300
}
296301

297-
$fileHash = hash_file('sha256', $tempFile->getRealPath());
302+
$fileHash = hash_file('sha256', $realPath);
298303

299-
if (in_array($fileHash, $this->processedHashes)) {
304+
if (in_array($fileHash, $this->processedHashes, true)) {
300305
continue;
301306
}
302307

303-
$fileName = $tempFile->getClientOriginalName();
308+
$fileName = $this->temporaryUploadOriginalName($tempFile);
304309

305310
$existingMedia = $this->applyMediaScope(Media::query())
306311
->where(function ($query) use ($fileName, $fileHash) {
@@ -313,6 +318,8 @@ public function form(Schema $schema): Schema
313318
->first();
314319

315320
if ($existingMedia) {
321+
$this->processedHashes[] = $fileHash;
322+
316323
Notification::make()
317324
->warning()
318325
->title(__('media::fields.duplicate_file'))
@@ -411,11 +418,9 @@ public function form(Schema $schema): Schema
411418
}
412419
}
413420

414-
// Formular zurücksetzen und Media-Liste aktualisieren
415-
$set('files', null);
416-
$this->refreshMedia();
417-
418421
if ($uploadedCount > 0) {
422+
$this->refreshMedia();
423+
419424
Notification::make()
420425
->success()
421426
->title(__('media::fields.file_uploaded_success'))
@@ -788,4 +793,32 @@ public function render()
788793
'mimeTypeLabels' => MediaIconHelper::getIconMapWithLabels(),
789794
]);
790795
}
796+
797+
protected function temporaryUploadPath(mixed $tempFile): ?string
798+
{
799+
if ($tempFile instanceof TemporaryUploadedFile) {
800+
$path = $tempFile->getRealPath();
801+
802+
return is_string($path) && $path !== '' && file_exists($path) ? $path : null;
803+
}
804+
805+
if (is_string($tempFile) && $tempFile !== '' && file_exists($tempFile)) {
806+
return $tempFile;
807+
}
808+
809+
return null;
810+
}
811+
812+
protected function temporaryUploadOriginalName(mixed $tempFile): string
813+
{
814+
if ($tempFile instanceof TemporaryUploadedFile) {
815+
return $tempFile->getClientOriginalName();
816+
}
817+
818+
if (is_string($tempFile)) {
819+
return basename($tempFile);
820+
}
821+
822+
return 'upload';
823+
}
791824
}

0 commit comments

Comments
 (0)