mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
refactor: replace ngx-uploader with own component
This commit is contained in:
1 parent
1716cd0d8b
commit
a62073332c
6 files changed
+71
-182
No files matched your search
@@ -1,25 +1,26 @@
|
||||
<div
|
||||
class="drop-container"
|
||||
ngFileDrop
|
||||
[options]="options"
|
||||
(uploadOutput)="onUploadOutput($event)"
|
||||
[uploadInput]="uploadInput"
|
||||
class="file-upload"
|
||||
appDragDropFileUpload
|
||||
(click)="fileField.click()"
|
||||
(fileDropped)="upload($event)"
|
||||
>
|
||||
<mat-icon class="upload-icon">save_alt</mat-icon>
|
||||
<p class="upload-title">{{ 'HOME.FILE_UPLOAD.DRAG_DROP' | translate }}</p>
|
||||
<p>{{ 'HOME.FILE_UPLOAD.OR' | translate }}</p>
|
||||
<mat-icon class="upload-icon">upload_file</mat-icon>
|
||||
<span class="label"
|
||||
>{{
|
||||
('HOME.FILE_UPLOAD.DRAG_DROP' | translate) +
|
||||
' ' +
|
||||
('HOME.FILE_UPLOAD.OR' | translate)
|
||||
}}
|
||||
<br />
|
||||
{{ 'HOME.FILE_UPLOAD.CHOOSE_PLAYLIST' | translate }}</span
|
||||
>
|
||||
<input
|
||||
type="file"
|
||||
ngFileSelect
|
||||
[options]="options"
|
||||
(uploadOutput)="onUploadOutput($event)"
|
||||
class="input-file"
|
||||
name="file"
|
||||
id="file"
|
||||
[uploadInput]="uploadInput"
|
||||
name="playlist"
|
||||
#fileField
|
||||
(change)="upload($any($event).target.files)"
|
||||
accept=".m3u,.m3u8"
|
||||
hidden
|
||||
multiple
|
||||
/>
|
||||
<label for="file">{{
|
||||
'HOME.FILE_UPLOAD.CHOOSE_PLAYLIST' | translate
|
||||
}}</label>
|
||||
</div>
|
||||
@@ -1,48 +1,27 @@
|
||||
.drop-container {
|
||||
text-align: center;
|
||||
color: #666;
|
||||
}
|
||||
$electron-title-width: 28px;
|
||||
|
||||
#file input {
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ccc;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.upload-title {
|
||||
font-size: 1.25em;
|
||||
}
|
||||
|
||||
.input-file {
|
||||
width: 0.1px;
|
||||
height: 0.1px;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.input-file + label {
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
color: white;
|
||||
background-color: #3f51b5;
|
||||
display: inline-block;
|
||||
text-transform: uppercase;
|
||||
border-radius: 4px;
|
||||
.file-upload {
|
||||
height: calc(100vh - 230px);
|
||||
cursor: pointer;
|
||||
line-height: 35px;
|
||||
padding: 3px 10px;
|
||||
}
|
||||
border: 1px dashed #999;
|
||||
border-radius: 5px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin: 20px;
|
||||
gap: 20px;
|
||||
|
||||
.input-file:focus + label,
|
||||
.input-file + label:hover {
|
||||
background-color: #202b69;
|
||||
}
|
||||
.upload-icon {
|
||||
color: #999;
|
||||
font-size: 60px;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
}
|
||||
|
||||
.upload-icon {
|
||||
font-size: 80px;
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
padding-top: 20px;
|
||||
.label {
|
||||
display: block;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
import { TranslateService, TranslatePipe } from '@ngx-translate/core';
|
||||
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
|
||||
import { FileUploadComponent } from './file-upload.component';
|
||||
import { MatIconModule } from '@angular/material/icon';
|
||||
import { MockModule, MockPipe } from 'ng-mocks';
|
||||
import { NgxUploaderModule } from 'ngx-uploader';
|
||||
import { TranslateServiceStub } from '../../../testing/translate.stub';
|
||||
|
||||
describe('FileUploadComponent', () => {
|
||||
let component: FileUploadComponent;
|
||||
let fixture: ComponentFixture<FileUploadComponent>;
|
||||
|
||||
beforeEach(
|
||||
waitForAsync(() => {
|
||||
TestBed.configureTestingModule({
|
||||
declarations: [FileUploadComponent, MockPipe(TranslatePipe)],
|
||||
imports: [
|
||||
MockModule(MatIconModule),
|
||||
MockModule(NgxUploaderModule),
|
||||
],
|
||||
providers: [
|
||||
{
|
||||
provide: TranslateService,
|
||||
useClass: TranslateServiceStub,
|
||||
},
|
||||
],
|
||||
}).compileComponents();
|
||||
})
|
||||
);
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(FileUploadComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,10 +1,4 @@
|
||||
import { Component, EventEmitter, Output } from '@angular/core';
|
||||
import {
|
||||
UploaderOptions,
|
||||
UploadFile,
|
||||
UploadOutput,
|
||||
UploadInput,
|
||||
} from 'ngx-uploader';
|
||||
|
||||
@Component({
|
||||
selector: 'app-file-upload',
|
||||
@@ -12,79 +6,36 @@ import {
|
||||
styleUrls: ['./file-upload.component.scss'],
|
||||
})
|
||||
export class FileUploadComponent {
|
||||
/** Array with uploaded files */
|
||||
files: UploadFile[] = [];
|
||||
/** Upload emitter */
|
||||
uploadInput: EventEmitter<UploadInput> = new EventEmitter<UploadInput>();
|
||||
/** Drag over flag */
|
||||
dragOver: boolean;
|
||||
/** ngx-uploader lib options */
|
||||
options: UploaderOptions = {
|
||||
allowedContentTypes: [
|
||||
'application/x-mpegurl',
|
||||
'application/octet-stream',
|
||||
'application/mpegurl',
|
||||
'application/vnd.apple.mpegurl',
|
||||
'application/vnd.apple.mpegurl.audio',
|
||||
'audio/x-mpegurl',
|
||||
'audio/mpegurl',
|
||||
],
|
||||
concurrency: 1,
|
||||
maxUploads: 1,
|
||||
};
|
||||
/** Emits on reject event */
|
||||
@Output() fileRejected: EventEmitter<string> = new EventEmitter();
|
||||
/** Emits after successful file selection */
|
||||
@Output() fileSelected: EventEmitter<{
|
||||
uploadEvent: Event;
|
||||
file: UploadFile;
|
||||
file: File;
|
||||
}> = new EventEmitter();
|
||||
|
||||
/**
|
||||
* Handles file upload
|
||||
* @param output
|
||||
*/
|
||||
onUploadOutput(output: UploadOutput): void {
|
||||
if (output.type === 'allAddedToQueue') {
|
||||
if (this.files.length > 0) {
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onload = (uploadEvent) =>
|
||||
this.fileSelected.emit({
|
||||
uploadEvent,
|
||||
file: this.files[0],
|
||||
});
|
||||
fileReader.readAsText(this.files[0].nativeFile);
|
||||
}
|
||||
} else if (
|
||||
output.type === 'addedToQueue' &&
|
||||
typeof output.file !== 'undefined'
|
||||
) {
|
||||
this.files.push(output.file);
|
||||
} else if (
|
||||
output.type === 'uploading' &&
|
||||
typeof output.file !== 'undefined'
|
||||
) {
|
||||
const index = this.files.findIndex(
|
||||
(file) =>
|
||||
typeof output.file !== 'undefined' &&
|
||||
file.id === output.file.id
|
||||
);
|
||||
this.files[index] = output.file;
|
||||
} else if (output.type === 'cancelled' || output.type === 'removed') {
|
||||
this.files = this.files.filter(
|
||||
(file: UploadFile) => file !== output.file
|
||||
);
|
||||
} else if (output.type === 'dragOver') {
|
||||
this.dragOver = true;
|
||||
} else if (output.type === 'dragOut') {
|
||||
this.dragOver = false;
|
||||
} else if (output.type === 'drop') {
|
||||
this.dragOver = false;
|
||||
} else if (
|
||||
output.type === 'rejected' &&
|
||||
typeof output.file !== 'undefined'
|
||||
) {
|
||||
this.fileRejected.emit(output.file.name);
|
||||
/** Emits on reject event */
|
||||
@Output() fileRejected: EventEmitter<string> = new EventEmitter();
|
||||
|
||||
allowedContentTypes = [
|
||||
'application/mpegurl',
|
||||
'application/x-mpegurl',
|
||||
'application/octet-stream',
|
||||
'application/vnd.apple.mpegurl',
|
||||
'application/vnd.apple.mpegurl.audio',
|
||||
'audio/x-mpegurl',
|
||||
'audio/mpegurl',
|
||||
];
|
||||
|
||||
upload(fileList: FileList) {
|
||||
if (!this.allowedContentTypes.includes(fileList[0].type)) {
|
||||
this.fileRejected.emit(fileList[0].name);
|
||||
return;
|
||||
}
|
||||
const fileReader = new FileReader();
|
||||
fileReader.onload = (uploadEvent) =>
|
||||
this.fileSelected.emit({
|
||||
uploadEvent,
|
||||
file: fileList[0],
|
||||
});
|
||||
fileReader.readAsText(fileList[0]);
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,6 @@ import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { TranslatePipe, TranslateService } from '@ngx-translate/core';
|
||||
import { MockComponent, MockModule, MockPipe, MockProvider } from 'ng-mocks';
|
||||
import { NgxIndexedDBModule, NgxIndexedDBService } from 'ngx-indexed-db';
|
||||
import { UploadFile } from 'ngx-uploader';
|
||||
import { of } from 'rxjs';
|
||||
import { FileUploadComponent } from '../home/file-upload/file-upload.component';
|
||||
import { RecentPlaylistsComponent } from '../home/recent-playlists/recent-playlists.component';
|
||||
@@ -101,10 +100,10 @@ describe('HomeComponent', () => {
|
||||
const title = 'my-list.m3u';
|
||||
const path = '/home/user/iptv/' + title;
|
||||
const playlistContent = 'test';
|
||||
const file: UploadFile = {
|
||||
nativeFile: { path },
|
||||
const file: File = {
|
||||
path,
|
||||
name: title,
|
||||
} as unknown as UploadFile;
|
||||
} as unknown as File;
|
||||
const uploadEvent: Event = {
|
||||
target: { result: playlistContent },
|
||||
} as unknown as Event;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { Component, NgZone } from '@angular/core';
|
||||
import { MatSnackBar } from '@angular/material/snack-bar';
|
||||
import { Router } from '@angular/router';
|
||||
import { UploadFile } from 'ngx-uploader';
|
||||
import {
|
||||
PLAYLIST_PARSE,
|
||||
PLAYLIST_PARSE_BY_URL,
|
||||
@@ -92,14 +91,14 @@ export class HomeComponent {
|
||||
* Parse and store uploaded playlist
|
||||
* @param payload
|
||||
*/
|
||||
handlePlaylist(payload: { uploadEvent: Event; file: UploadFile }): void {
|
||||
handlePlaylist(payload: { uploadEvent: Event; file: File }): void {
|
||||
this.isLoading = true;
|
||||
const result = (payload.uploadEvent.target as FileReader).result;
|
||||
const array = (result as string).split('\n');
|
||||
this.electronService.sendIpcEvent(PLAYLIST_PARSE, {
|
||||
title: payload.file.name,
|
||||
playlist: array,
|
||||
path: (payload.file.nativeFile as any).path,
|
||||
path: payload.file.path,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user