mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
refactor(playlist-import): update file upload handling and emit imported event
Entire-Checkpoint: c6e522b4276c
This commit is contained in:
1 parent
db55c07030
commit
4616df5d16
3 files changed
+25
-45
No files matched your search
+1
-1
@@ -45,7 +45,7 @@
|
||||
@case ('file') {
|
||||
<app-file-upload
|
||||
(fileRejected)="rejectFile($event)"
|
||||
(fileSelected)="handlePlaylist($event)"
|
||||
(imported)="onFileImported()"
|
||||
(closeDialog)="closeDialog()"
|
||||
/>
|
||||
}
|
||||
|
||||
+4
-26
@@ -111,21 +111,11 @@ export class AddPlaylistDialogComponent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse and store uploaded playlist
|
||||
* @param payload
|
||||
* Closes the dialog after a successful file import. The actual parse and
|
||||
* dispatch happens inside `PlaylistFileImportService` (called from the
|
||||
* `FileUploadComponent`).
|
||||
*/
|
||||
handlePlaylist(payload: { uploadEvent: Event; file: File }): void {
|
||||
const playlist = (payload.uploadEvent.target as FileReader)
|
||||
.result as string;
|
||||
|
||||
this.store.dispatch(
|
||||
PlaylistActions.parsePlaylist({
|
||||
uploadType: 'FILE',
|
||||
playlist,
|
||||
title: this.normalizeImportedFileTitle(payload.file.name),
|
||||
path: (payload.file as File & { path?: string }).path,
|
||||
})
|
||||
);
|
||||
onFileImported(): void {
|
||||
this.closeDialog();
|
||||
}
|
||||
|
||||
@@ -181,16 +171,4 @@ export class AddPlaylistDialogComponent {
|
||||
const normalizedValue = value?.trim();
|
||||
return normalizedValue ? normalizedValue : undefined;
|
||||
}
|
||||
|
||||
private normalizeImportedFileTitle(filename: string): string {
|
||||
const normalizedFilename = filename.trim();
|
||||
if (!normalizedFilename) {
|
||||
return filename;
|
||||
}
|
||||
|
||||
return (
|
||||
normalizedFilename.replace(/\.(m3u8?|pls|txt)$/i, '') ||
|
||||
normalizedFilename
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
import { Component, EventEmitter, Output, signal } from '@angular/core';
|
||||
import { Component, EventEmitter, Output, inject, signal } from '@angular/core';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { PlaylistFileImportService } from '@iptvnator/playlist/shared/util';
|
||||
import { DragDropFileUploadDirective } from './drag-drop-file-upload.directive';
|
||||
|
||||
const M3U_EXTENSIONS = ['.m3u', '.m3u8'];
|
||||
const MB = 1024 * 1024;
|
||||
const KB = 1024;
|
||||
|
||||
@@ -14,15 +14,15 @@ const KB = 1024;
|
||||
styleUrls: ['./file-upload.component.scss'],
|
||||
})
|
||||
export class FileUploadComponent {
|
||||
@Output() fileSelected = new EventEmitter<{
|
||||
uploadEvent: Event;
|
||||
file: File;
|
||||
}>();
|
||||
private readonly importService = inject(PlaylistFileImportService);
|
||||
|
||||
@Output() imported = new EventEmitter<{ title: string }>();
|
||||
@Output() fileRejected = new EventEmitter<string>();
|
||||
@Output() closeDialog = new EventEmitter<void>();
|
||||
|
||||
readonly selectedFile = signal<File | null>(null);
|
||||
readonly isDragging = signal(false);
|
||||
readonly isImporting = signal(false);
|
||||
|
||||
openPicker(input: HTMLInputElement): void {
|
||||
input.value = '';
|
||||
@@ -60,14 +60,21 @@ export class FileUploadComponent {
|
||||
this.selectedFile.set(null);
|
||||
}
|
||||
|
||||
confirm(): void {
|
||||
async confirm(): Promise<void> {
|
||||
const file = this.selectedFile();
|
||||
if (!file) return;
|
||||
if (!file || this.isImporting()) return;
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = (uploadEvent) =>
|
||||
this.fileSelected.emit({ uploadEvent, file });
|
||||
reader.readAsText(file);
|
||||
this.isImporting.set(true);
|
||||
const result = await this.importService.importFile(file);
|
||||
this.isImporting.set(false);
|
||||
|
||||
if (result.ok === true) {
|
||||
this.imported.emit({ title: result.title });
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectedFile.set(null);
|
||||
this.fileRejected.emit(file.name);
|
||||
}
|
||||
|
||||
formatSize(bytes: number): string {
|
||||
@@ -78,15 +85,10 @@ export class FileUploadComponent {
|
||||
|
||||
private setFile(file: File | undefined): void {
|
||||
if (!file) return;
|
||||
if (!this.hasAllowedExtension(file.name)) {
|
||||
if (!this.importService.isSupportedFile(file)) {
|
||||
this.fileRejected.emit(file.name);
|
||||
return;
|
||||
}
|
||||
this.selectedFile.set(file);
|
||||
}
|
||||
|
||||
private hasAllowedExtension(name: string): boolean {
|
||||
const lower = name.toLowerCase();
|
||||
return M3U_EXTENSIONS.some((ext) => lower.endsWith(ext));
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user