|
|
@ -2,24 +2,35 @@ import { CommonModule } from '@angular/common';
|
|
|
|
import {
|
|
|
|
import {
|
|
|
|
Component,
|
|
|
|
Component,
|
|
|
|
EventEmitter,
|
|
|
|
EventEmitter,
|
|
|
|
|
|
|
|
HostListener,
|
|
|
|
Input,
|
|
|
|
Input,
|
|
|
|
OnChanges,
|
|
|
|
OnChanges,
|
|
|
|
|
|
|
|
OnDestroy,
|
|
|
|
Output,
|
|
|
|
Output,
|
|
|
|
SimpleChanges,
|
|
|
|
SimpleChanges,
|
|
|
|
} from '@angular/core';
|
|
|
|
} from '@angular/core';
|
|
|
|
|
|
|
|
import { ImageService } from '../../services/image/image.service';
|
|
|
|
|
|
|
|
|
|
|
|
@Component({
|
|
|
|
@Component({
|
|
|
|
selector: 'app-drag-drop',
|
|
|
|
selector: 'app-drag-drop',
|
|
|
|
imports: [CommonModule],
|
|
|
|
imports: [CommonModule],
|
|
|
|
templateUrl: './drag-drop.component.html',
|
|
|
|
templateUrl: './drag-drop.component.html',
|
|
|
|
})
|
|
|
|
})
|
|
|
|
export class DragDropComponent implements OnChanges {
|
|
|
|
export class DragDropComponent implements OnChanges, OnDestroy {
|
|
|
|
@Input() initialFiles: string[] = [];
|
|
|
|
@Input() initialFiles: { name: string; id?: string }[] = [];
|
|
|
|
@Input() errorMessage: string = '';
|
|
|
|
@Input() errorMessage: string = '';
|
|
|
|
fileNames: string[] = [];
|
|
|
|
fileNames: { name: string; id?: string }[] = [];
|
|
|
|
@Output() filesSelected = new EventEmitter<FileList>();
|
|
|
|
@Output() filesSelected = new EventEmitter<FileList>();
|
|
|
|
@Output() fileRemoved = new EventEmitter<string>();
|
|
|
|
@Output() fileRemoved = new EventEmitter<string>();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
hoveredFileName: string | null = null;
|
|
|
|
|
|
|
|
previewUrl: string | null = null;
|
|
|
|
|
|
|
|
private objectUrl: string | null = null;
|
|
|
|
|
|
|
|
private imageUrlCache: { [id: string]: string } = {};
|
|
|
|
|
|
|
|
private lastHoveredId: string | null = null;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
constructor(private imageService: ImageService) {}
|
|
|
|
|
|
|
|
|
|
|
|
ngOnChanges(changes: SimpleChanges) {
|
|
|
|
ngOnChanges(changes: SimpleChanges) {
|
|
|
|
if (changes['initialFiles']) {
|
|
|
|
if (changes['initialFiles']) {
|
|
|
|
this.fileNames = [...this.initialFiles];
|
|
|
|
this.fileNames = [...this.initialFiles];
|
|
|
@ -58,20 +69,67 @@ export class DragDropComponent implements OnChanges {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
updateFileNamesFromFileList(files: FileList): void {
|
|
|
|
updateFileNamesFromFileList(files: FileList): void {
|
|
|
|
this.fileNames = Array.from(files).map((file) => file.name);
|
|
|
|
this.fileNames = Array.from(files).map((file) => ({ name: file.name }));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private updateFileNames(files: FileList): void {
|
|
|
|
private updateFileNames(files: FileList): void {
|
|
|
|
const newFileNames = Array.from(files).map(file => file.name);
|
|
|
|
const newFileNames = Array.from(files).map((file) => ({ name: file.name }));
|
|
|
|
this.fileNames = [...this.fileNames, ...newFileNames];
|
|
|
|
this.fileNames = [...this.fileNames, ...newFileNames];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
removeFile(fileName: string, event: Event): void {
|
|
|
|
removeFile(fileName: string, event: Event): void {
|
|
|
|
event.stopPropagation(); // Empêcher la propagation du clic
|
|
|
|
event.stopPropagation(); // Empêcher la propagation du clic
|
|
|
|
const index = this.fileNames.indexOf(fileName);
|
|
|
|
const index = this.fileNames.findIndex((f) => f.name === fileName);
|
|
|
|
if (index > -1) {
|
|
|
|
if (index > -1) {
|
|
|
|
this.fileNames.splice(index, 1);
|
|
|
|
this.fileNames.splice(index, 1);
|
|
|
|
this.fileRemoved.emit(fileName);
|
|
|
|
this.fileRemoved.emit(fileName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async onFileNameMouseEnter(fileName: string): Promise<void> {
|
|
|
|
|
|
|
|
const fileObj = this.getFileByName(fileName);
|
|
|
|
|
|
|
|
if (!fileObj) {
|
|
|
|
|
|
|
|
this.hoveredFileName = null;
|
|
|
|
|
|
|
|
this.previewUrl = null;
|
|
|
|
|
|
|
|
this.lastHoveredId = null;
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ne rien faire si on survole le même fichier
|
|
|
|
|
|
|
|
if (fileObj.id && this.lastHoveredId === fileObj.id) {
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
this.hoveredFileName = fileName;
|
|
|
|
|
|
|
|
this.lastHoveredId = fileObj.id || null;
|
|
|
|
|
|
|
|
if (fileObj.id) {
|
|
|
|
|
|
|
|
if (this.imageUrlCache[fileObj.id]) {
|
|
|
|
|
|
|
|
this.previewUrl = this.imageUrlCache[fileObj.id];
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
this.imageService.getImage(fileObj.id).subscribe((blob) => {
|
|
|
|
|
|
|
|
const objectUrl = URL.createObjectURL(blob);
|
|
|
|
|
|
|
|
this.imageUrlCache[fileObj.id!] = objectUrl;
|
|
|
|
|
|
|
|
this.previewUrl = objectUrl;
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
this.previewUrl = null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@HostListener('mouseleave') onFileNameMouseLeave(): void {
|
|
|
|
|
|
|
|
this.hoveredFileName = null;
|
|
|
|
|
|
|
|
this.previewUrl = null;
|
|
|
|
|
|
|
|
this.lastHoveredId = null;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
getFileByName(fileName: string): { name: string; id?: string } | undefined {
|
|
|
|
|
|
|
|
return this.fileNames.find((f) => f.name === fileName);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ngOnDestroy(): void {
|
|
|
|
|
|
|
|
// Révoquer tous les objectURLs du cache
|
|
|
|
|
|
|
|
Object.values(this.imageUrlCache).forEach((url) =>
|
|
|
|
|
|
|
|
URL.revokeObjectURL(url)
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
this.imageUrlCache = {};
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|