feat(book-uploader): Improved UX of drag&drop when adding books. (#2410)

The current experience was not great when you have several libraries, instead of swallowing the drop it was disabling the drag/drop zone leading to the browser taking over and opening the file.
This changes keeps the drag & drop enabled but just swallows the files and displays an error if no library is selected.
It also improves the UI by making it more clear when a drag event is happening.
This commit is contained in:
Giroux Arthur
2026-01-23 09:39:35 -07:00
committed by GitHub
parent d1c4836917
commit 5d1a295d49
3 changed files with 39 additions and 5 deletions

View File

@@ -90,8 +90,7 @@
[multiple]="true"
accept=".pdf,.epub,.cbz,.cbr,.cb7,.fb2,.mobi,.azw,.azw3"
(onSelect)="onFilesSelect($event)"
(uploadHandler)="uploadFiles($event)"
[disabled]="value === 'library' ? (!selectedLibrary || !selectedPath) : false">
(uploadHandler)="uploadFiles($event)">
<ng-template #header let-files let-chooseCallback="chooseCallback" let-clearCallback="clearCallback" let-uploadCallback="uploadCallback">
<div class="upload-actions">
<div class="action-buttons">

View File

@@ -98,9 +98,10 @@
.file-upload-section {
::ng-deep .p-fileupload {
border: 1px solid var(--border-color);
border: 2px dashed var(--border-color);
border-radius: 8px;
background: var(--ground-background);
transition: border-color 0.3s ease, background-color 0.3s ease;
.p-fileupload-buttonbar {
display: flex;
@@ -115,6 +116,25 @@
padding: 1rem;
background: transparent;
border: none;
transition: background-color 0.3s ease;
&.p-fileupload-highlight {
background: color-mix(in srgb, var(--primary-color) 5%, transparent);
.empty-icon-wrapper {
border-color: var(--primary-color);
.empty-icon {
color: var(--primary-color);
opacity: 1;
transform: scale(1.1);
}
}
}
}
&:has(.p-fileupload-highlight) {
border-color: var(--primary-color);
}
}
@@ -299,12 +319,13 @@
border-radius: 50%;
margin-bottom: 1rem;
border: 3px dashed var(--border-color);
transition: border-color 0.3s ease;
.empty-icon {
font-size: 2.5rem;
color: var(--text-secondary-color);
opacity: 0.6;
transition: color 0.3s ease;
transition: color 0.3s ease, opacity 0.3s ease, transform 0.3s ease;
&.active {
color: #22c55e;

View File

@@ -1,4 +1,4 @@
import {Component, inject, OnInit} from '@angular/core';
import {Component, inject, OnInit, ViewChild} from '@angular/core';
import {FileSelectEvent, FileUpload, FileUploadHandlerEvent} from 'primeng/fileupload';
import {Button} from 'primeng/button';
import {AsyncPipe} from '@angular/common';
@@ -43,6 +43,8 @@ interface UploadingFile {
styleUrl: './book-uploader.component.scss'
})
export class BookUploaderComponent implements OnInit {
@ViewChild(FileUpload) fileUpload!: FileUpload;
files: UploadingFile[] = [];
isUploading: boolean = false;
uploadCompleted: boolean = false;
@@ -116,6 +118,18 @@ export class BookUploaderComponent implements OnInit {
}
onFilesSelect(event: FileSelectEvent): void {
if (this.value === 'library' && (!this.selectedLibrary || !this.selectedPath)) {
this.messageService.add({
severity: 'error',
summary: 'No Destination Selected',
detail: 'Please select a library and subpath before adding files.',
life: 5000
});
// We need to clear the files input explicitely, otherwise the files remain selected in the file upload component
this.fileUpload.clear();
return;
}
const newFiles = event.currentFiles;
for (const file of newFiles) {
const exists = this.files.some(f => f.file.name === file.name && f.file.size === file.size);