mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
feat: list with recent playlists
This commit is contained in:
1 parent
fff2aaa541
commit
1735026c20
8 files changed
+122
-34
No files matched your search
@@ -13,13 +13,15 @@ import { NgxUploaderModule } from 'ngx-uploader';
|
||||
import { PlaylistUploaderComponent } from './components/playlist-uploader/playlist-uploader.component';
|
||||
import { VideoPlayerComponent } from './components/video-player/video-player.component';
|
||||
import { MaterialModule } from './material.module';
|
||||
import { RecentPlaylistsComponent } from './components/recent-playlists/recent-playlists.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AppComponent,
|
||||
ChannelListContainerComponent,
|
||||
PlaylistUploaderComponent,
|
||||
VideoPlayerComponent
|
||||
VideoPlayerComponent,
|
||||
RecentPlaylistsComponent,
|
||||
],
|
||||
imports: [
|
||||
AppRoutingModule,
|
||||
@@ -30,10 +32,10 @@ import { MaterialModule } from './material.module';
|
||||
MaterialModule,
|
||||
NgxUploaderModule,
|
||||
ServiceWorkerModule.register('ngsw-worker.js', {
|
||||
enabled: environment.production
|
||||
})
|
||||
enabled: environment.production,
|
||||
}),
|
||||
],
|
||||
providers: [],
|
||||
bootstrap: [AppComponent]
|
||||
bootstrap: [AppComponent],
|
||||
})
|
||||
export class AppModule {}
|
||||
@@ -0,0 +1,16 @@
|
||||
.drop-container {
|
||||
/*width: 400px;*/
|
||||
height: 100px;
|
||||
border: 1px dashed #ccc;
|
||||
border-radius: 10px;
|
||||
margin: 0 auto;
|
||||
padding: 10px;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
input {
|
||||
border-radius: 4px;
|
||||
border: 1px solid #ccc;
|
||||
padding: 5px;
|
||||
}
|
||||
@@ -1,26 +1,25 @@
|
||||
<div
|
||||
class="drop-container"
|
||||
ngFileDrop
|
||||
[options]="options"
|
||||
(uploadOutput)="onUploadOutput($event)"
|
||||
[uploadInput]="uploadInput">
|
||||
<p>
|
||||
Drag files here or
|
||||
<label class="upload-button">
|
||||
<input
|
||||
type="file"
|
||||
ngFileSelect
|
||||
[options]="options"
|
||||
(uploadOutput)="onUploadOutput($event)"
|
||||
[uploadInput]="uploadInput"
|
||||
multiple>
|
||||
browse
|
||||
</label>
|
||||
to upload.
|
||||
</p>
|
||||
|
||||
<!-- <h3>Recent playlists:</h3>
|
||||
TODO
|
||||
<h3>Insert playlist by URL:</h3>
|
||||
TODO -->
|
||||
</div>
|
||||
<mat-card>
|
||||
<mat-card-subtitle>Add playlist</mat-card-subtitle>
|
||||
<div class="drop-container" ngFileDrop [options]="options" (uploadOutput)="onUploadOutput($event)"
|
||||
[uploadInput]="uploadInput">
|
||||
<p>
|
||||
Drag files here or
|
||||
<label class="upload-button">
|
||||
<input type="file" ngFileSelect [options]="options" (uploadOutput)="onUploadOutput($event)"
|
||||
[uploadInput]="uploadInput" multiple>
|
||||
browse
|
||||
</label>
|
||||
to upload.
|
||||
</p>
|
||||
</div>
|
||||
</mat-card>
|
||||
<br>
|
||||
<ng-container *ngIf="(playlists | keyvalue)?.length > 0">
|
||||
<mat-card>
|
||||
<mat-card-subtitle>Recent playlists</mat-card-subtitle>
|
||||
<mat-card-content>
|
||||
<app-recent-playlists [playlists]="playlists" (playlistClicked)="setPlaylist($event)">
|
||||
</app-recent-playlists>
|
||||
</mat-card-content>
|
||||
</mat-card>
|
||||
</ng-container>
|
||||
@@ -22,6 +22,7 @@ export class PlaylistUploaderComponent {
|
||||
humanizeBytes: Function;
|
||||
dragOver: boolean;
|
||||
options: UploaderOptions;
|
||||
playlists: any;
|
||||
|
||||
/**
|
||||
* Creates an instanceof PlaylistUploaderComponent
|
||||
@@ -34,6 +35,8 @@ export class PlaylistUploaderComponent {
|
||||
private m3uService: M3uService,
|
||||
private router: Router
|
||||
) {
|
||||
this.getPlaylists();
|
||||
|
||||
this.options = {
|
||||
concurrency: 1,
|
||||
maxUploads: 1,
|
||||
@@ -59,11 +62,12 @@ export class PlaylistUploaderComponent {
|
||||
const playlist = this.m3uService.convertArrayToPlaylist(
|
||||
array
|
||||
);
|
||||
this.savePlaylist(
|
||||
this.files[0].name,
|
||||
JSON.stringify(playlist)
|
||||
);
|
||||
|
||||
playlist.segments.forEach(element => {
|
||||
this.channelStore.add(createChannel(element));
|
||||
this.navigateToPlayer();
|
||||
});
|
||||
this.setPlaylist(playlist);
|
||||
};
|
||||
fileReader.readAsText(this.files[0].nativeFile);
|
||||
}
|
||||
@@ -106,4 +110,38 @@ export class PlaylistUploaderComponent {
|
||||
navigateToPlayer(): void {
|
||||
this.router.navigateByUrl('/iptv', { skipLocationChange: true });
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves playlist to the localStorage
|
||||
* @param name name of the playlist
|
||||
* @param playlist playlist to save
|
||||
*/
|
||||
savePlaylist(name: string, playlist: any): void {
|
||||
localStorage.setItem(name, playlist);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads all saved playlists from the localStorage
|
||||
*/
|
||||
getPlaylists(): void {
|
||||
this.playlists = { ...localStorage };
|
||||
|
||||
this.playlists = Object.keys(this.playlists)
|
||||
.filter(key => key.includes('.m3u'))
|
||||
.reduce((obj, key) => {
|
||||
obj[key] = JSON.parse(this.playlists[key]);
|
||||
return obj;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given playlist as active for the current session
|
||||
* @param playlist m3u playlist
|
||||
*/
|
||||
setPlaylist(playlist: any): void {
|
||||
playlist.segments.forEach(element => {
|
||||
this.channelStore.add(createChannel(element));
|
||||
this.navigateToPlayer();
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<button *ngFor="let playlist of playlists | keyvalue" mat-stroked-button (click)="playlistClicked.emit(playlist.value)">
|
||||
{{playlist.key}}
|
||||
</button>
|
||||
@@ -0,0 +1,3 @@
|
||||
button {
|
||||
margin: 5px;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-recent-playlists',
|
||||
templateUrl: './recent-playlists.component.html',
|
||||
styleUrls: ['./recent-playlists.component.scss'],
|
||||
})
|
||||
export class RecentPlaylistsComponent {
|
||||
/**
|
||||
* Playlist object
|
||||
*/
|
||||
@Input() playlists: any;
|
||||
|
||||
/**
|
||||
* Emits on playlist click
|
||||
*/
|
||||
@Output() playlistClicked: EventEmitter<any> = new EventEmitter();
|
||||
}
|
||||
@@ -18,4 +18,13 @@ export class M3uService {
|
||||
this.m3u8FileParser.read(m3uArray.join('\n'));
|
||||
return this.m3u8FileParser.getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts string to playlist structure
|
||||
* @param m3uString playlist as string
|
||||
*/
|
||||
convertStringToPlaylist(m3uString: string): any {
|
||||
this.m3u8FileParser.read(m3uString);
|
||||
return this.m3u8FileParser.getResult();
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user