feat: export playlist as m3u

This commit is contained in:
4gray committed 2023-03-11 18:27:16 +01:00
1 parent ba41c8dae5
commit 7e4d6b171f
8 files changed
+204 -179

No files matched your search

@@ -67,6 +67,10 @@
</ng-container>
</mat-dialog-content>
<mat-dialog-actions align="end">
<button mat-flat-button color="accent" (click)="exportPlaylist()">
{{ 'HOME.PLAYLISTS.INFO_DIALOG.EXPORT_PLAYLIST' | translate }}
</button>
<div style="flex: 1 1 auto"></div>
<button
mat-flat-button
mat-dialog-close
@@ -13,7 +13,8 @@ import { Actions } from '@ngrx/effects';
import { provideMockActions } from '@ngrx/effects/testing';
import { MockStore, provideMockStore } from '@ngrx/store/testing';
import { TranslateModule } from '@ngx-translate/core';
import { MockModule, MockPipe } from 'ng-mocks';
import { MockModule, MockPipe, MockProvider } from 'ng-mocks';
import { NgxIndexedDBModule } from 'ngx-indexed-db';
import { Observable } from 'rxjs';
import { DataService } from '../../../services/data.service';
import { ElectronServiceStub } from '../../../services/electron.service.stub';
@@ -23,7 +24,6 @@ import { PlaylistInfoComponent } from './playlist-info.component';
describe('PlaylistInfoComponent', () => {
let component: PlaylistInfoComponent;
let fixture: ComponentFixture<PlaylistInfoComponent>;
let electronService: DataService;
let mockStore: MockStore;
const actions$ = new Observable<Actions>();
@@ -45,6 +45,7 @@ describe('PlaylistInfoComponent', () => {
UntypedFormBuilder,
provideMockStore(),
provideMockActions(actions$),
MockProvider(NgxIndexedDBModule),
],
}).compileComponents();
})
@@ -6,16 +6,19 @@ import {
ReactiveFormsModule,
UntypedFormBuilder,
UntypedFormGroup,
Validators,
Validators
} from '@angular/forms';
import { MatButtonModule } from '@angular/material/button';
import { MatCheckboxModule } from '@angular/material/checkbox';
import { MatDialogModule, MAT_DIALOG_DATA } from '@angular/material/dialog';
import { MatIconModule } from '@angular/material/icon';
import { MatInputModule } from '@angular/material/input';
import { Store } from '@ngrx/store';
import { TranslateModule } from '@ngx-translate/core';
import { firstValueFrom } from 'rxjs';
import { Playlist } from '../../../../../shared/playlist.interface';
import { DataService } from '../../../services/data.service';
import { PlaylistsService } from '../../../services/playlists.service';
import { PlaylistMeta } from '../../../shared/playlist-meta.type';
import * as PlaylistActions from '../../../state/actions';
@@ -26,6 +29,7 @@ import * as PlaylistActions from '../../../state/actions';
imports: [
TranslateModule,
MatButtonModule,
MatIconModule,
MatInputModule,
MatCheckboxModule,
CommonModule,
@@ -49,6 +53,7 @@ export class PlaylistInfoComponent {
private formBuilder: UntypedFormBuilder,
private dataService: DataService,
@Inject(MAT_DIALOG_DATA) playlist: Playlist,
private playlistService: PlaylistsService,
private store: Store
) {
this.playlist = playlist;
@@ -89,4 +94,21 @@ export class PlaylistInfoComponent {
saveChanges(playlist: PlaylistMeta): void {
this.store.dispatch(PlaylistActions.updatePlaylistMeta({ playlist }));
}
async exportPlaylist() {
const playlistAsString = await firstValueFrom(
this.playlistService.getRawPlaylistById(this.playlist._id)
);
const element = document.createElement('a');
element.setAttribute(
'href',
'data:text/plain;charset=utf-8,' +
encodeURIComponent(playlistAsString)
);
element.setAttribute('download', this.playlist.title || 'exported.m3u');
element.style.display = 'none';
document.body.appendChild(element);
element.click();
document.body.removeChild(element);
}
}
+9 -2
View File
@@ -7,12 +7,12 @@ import { Channel } from '../../../shared/channel.interface';
import { GLOBAL_FAVORITES_PLAYLIST_ID } from '../../../shared/constants';
import {
Playlist,
PlaylistUpdateState,
PlaylistUpdateState
} from '../../../shared/playlist.interface';
import {
aggregateFavoriteChannels,
createFavoritesPlaylist,
createPlaylistObject,
createPlaylistObject
} from '../../../shared/playlist.utils';
import { DbStores } from '../indexed-db.config';
import { PlaylistMeta } from '../shared/playlist-meta.type';
@@ -191,4 +191,11 @@ export class PlaylistsService {
)
);
}
getRawPlaylistById(id: string) {
return this.dbService.getByID<Playlist>(DbStores.Playlists, id).pipe(map(playlist => {
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
return playlist.playlist.header.raw + '\n' + playlist.playlist.items.map(item => item.raw).join('\n');
}));
}
}
+2 -1
View File
@@ -65,7 +65,8 @@
"UPDATE_FAILED": "Update fehlgeschlagen",
"AUTO_UPDATE": "Auto-update",
"AUTO_UPDATE_DESCRIPTION": "Wenn die Auto-Refresh-Funktion aktiviert ist, wird die Wiedergabeliste bei jedem Start der Anwendung automatisch aktualisiert.",
"CUSTOM_USER_AGENT": "Einige IPTV-Anbieter benötigen einen bestimmten 'User-Agent', um ihre Playlist abspielen zu können."
"CUSTOM_USER_AGENT": "Einige IPTV-Anbieter benötigen einen bestimmten 'User-Agent', um ihre Playlist abspielen zu können.",
"EXPORT_PLAYLIST": "Als m3u exportieren"
},
"UPDATED": "Aktualisiert am",
"REFRESH": "Aktualisieren",
+2 -1
View File
@@ -32,7 +32,8 @@
"UPDATE_FAILED": "Last playlist update failed",
"AUTO_UPDATE": "Auto-update",
"AUTO_UPDATE_DESCRIPTION": "If the auto-refresh function is activated, the playlist will be updated automatically each time the app is started.",
"CUSTOM_USER_AGENT": "Some IPTV providers need a specific user-agent in order to play their playlist."
"CUSTOM_USER_AGENT": "Some IPTV providers need a specific user-agent in order to play their playlist.",
"EXPORT_PLAYLIST": "Export playlist as m3u"
},
"REMOVE_DIALOG": {
"TITLE": "Remove playlist",
+2 -1
View File
@@ -32,7 +32,8 @@
"UPDATE_FAILED": "Не удалось обновить плейлист",
"AUTO_UPDATE": "Автообновление",
"AUTO_UPDATE_DESCRIPTION": "Если активирована функция автообновления, список воспроизведения будет обновляться автоматически при каждом запуске приложения.",
"CUSTOM_USER_AGENT": "Некоторые IPTV провайдеры требуют указанние определенного пользовательского агента (User Agent) для воспроизведения своего плейлиста."
"CUSTOM_USER_AGENT": "Некоторые IPTV провайдеры требуют указанние определенного пользовательского агента (User Agent) для воспроизведения своего плейлиста.",
"EXPORT_PLAYLIST": "Экспортировать плейлист (m3u)"
},
"UPDATED": "Обновлен",
"REFRESH": "Обновить плейлист",