mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 17:06:15 -08:00
feat: enhance playlist backup export functionality and UI feedback
Entire-Checkpoint: c6e522b4276c
This commit is contained in:
1 parent
1c1a53743a
commit
c8c93798f9
26 files changed
+2254
-375
No files matched your search
+45
-16
@@ -17,6 +17,7 @@ import { DialogService } from 'components';
|
||||
import {
|
||||
DatabaseService,
|
||||
DataService,
|
||||
PlaybackPositionService,
|
||||
SortBy,
|
||||
SortOrder,
|
||||
SortService,
|
||||
@@ -72,6 +73,9 @@ describe('RecentPlaylistsComponent busy state', () => {
|
||||
let dataService: {
|
||||
sendIpcEvent: jest.Mock;
|
||||
};
|
||||
let playbackPositionService: {
|
||||
getAllPlaybackPositions: jest.Mock;
|
||||
};
|
||||
let router: {
|
||||
navigate: jest.Mock;
|
||||
};
|
||||
@@ -94,6 +98,9 @@ describe('RecentPlaylistsComponent busy state', () => {
|
||||
dataService = {
|
||||
sendIpcEvent: jest.fn(),
|
||||
};
|
||||
playbackPositionService = {
|
||||
getAllPlaybackPositions: jest.fn().mockResolvedValue([]),
|
||||
};
|
||||
router = {
|
||||
navigate: jest.fn(),
|
||||
};
|
||||
@@ -128,6 +135,10 @@ describe('RecentPlaylistsComponent busy state', () => {
|
||||
provide: DataService,
|
||||
useValue: dataService,
|
||||
},
|
||||
{
|
||||
provide: PlaybackPositionService,
|
||||
useValue: playbackPositionService,
|
||||
},
|
||||
{
|
||||
provide: PlaylistContextFacade,
|
||||
useValue: {
|
||||
@@ -157,7 +168,9 @@ describe('RecentPlaylistsComponent busy state', () => {
|
||||
order: SortOrder.DESC,
|
||||
})
|
||||
),
|
||||
sortPlaylists: jest.fn((playlists: PlaylistMeta[]) => playlists),
|
||||
sortPlaylists: jest.fn(
|
||||
(playlists: PlaylistMeta[]) => playlists
|
||||
),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -238,9 +251,16 @@ describe('RecentPlaylistsComponent busy state', () => {
|
||||
const item = createPlaylistMeta({ _id: 'playlist-refresh-1' });
|
||||
const refresh = createDeferred<{
|
||||
success: boolean;
|
||||
favoritedXtreamIds: number[];
|
||||
recentlyViewedXtreamIds: { xtreamId: number; viewedAt: string }[];
|
||||
hiddenCategories: { xtreamId: number; type: string }[];
|
||||
favorites: Array<{ xtreamId: number; contentType: string }>;
|
||||
recentlyViewed: Array<{
|
||||
xtreamId: number;
|
||||
contentType: string;
|
||||
viewedAt: string;
|
||||
}>;
|
||||
hiddenCategories: Array<{
|
||||
xtreamId: number;
|
||||
categoryType: string;
|
||||
}>;
|
||||
}>();
|
||||
let confirmPromise: Promise<void> | undefined;
|
||||
|
||||
@@ -323,25 +343,29 @@ describe('RecentPlaylistsComponent busy state', () => {
|
||||
});
|
||||
databaseService.deleteXtreamPlaylistContent.mockResolvedValue({
|
||||
success: true,
|
||||
favoritedXtreamIds: [101, 202],
|
||||
recentlyViewedXtreamIds: [
|
||||
favorites: [
|
||||
{ xtreamId: 101, contentType: 'live' },
|
||||
{ xtreamId: 202, contentType: 'movie' },
|
||||
],
|
||||
recentlyViewed: [
|
||||
{
|
||||
xtreamId: 303,
|
||||
contentType: 'series',
|
||||
viewedAt: '2026-04-03T11:15:00.000Z',
|
||||
},
|
||||
],
|
||||
hiddenCategories: [{ xtreamId: 404, type: 'live' }],
|
||||
hiddenCategories: [{ xtreamId: 404, categoryType: 'live' }],
|
||||
});
|
||||
|
||||
component.refreshXtreamPlaylist(item);
|
||||
await confirmPromise;
|
||||
|
||||
expect(databaseService.updateXtreamPlaylistDetails).toHaveBeenCalledWith(
|
||||
{
|
||||
id: item._id,
|
||||
updateDate: 1712145600000,
|
||||
}
|
||||
);
|
||||
expect(
|
||||
databaseService.updateXtreamPlaylistDetails
|
||||
).toHaveBeenCalledWith({
|
||||
id: item._id,
|
||||
updateDate: 1712145600000,
|
||||
});
|
||||
expect(store.dispatch).toHaveBeenCalledWith(
|
||||
PlaylistActions.updatePlaylistMeta({
|
||||
playlist: { ...item, updateDate: 1712145600000 },
|
||||
@@ -350,14 +374,19 @@ describe('RecentPlaylistsComponent busy state', () => {
|
||||
expect(setItemSpy).toHaveBeenCalledWith(
|
||||
`xtream-restore-${item._id}`,
|
||||
JSON.stringify({
|
||||
favoritedXtreamIds: [101, 202],
|
||||
recentlyViewedXtreamIds: [
|
||||
hiddenCategories: [{ xtreamId: 404, categoryType: 'live' }],
|
||||
favorites: [
|
||||
{ xtreamId: 101, contentType: 'live' },
|
||||
{ xtreamId: 202, contentType: 'movie' },
|
||||
],
|
||||
recentlyViewed: [
|
||||
{
|
||||
xtreamId: 303,
|
||||
contentType: 'series',
|
||||
viewedAt: '2026-04-03T11:15:00.000Z',
|
||||
},
|
||||
],
|
||||
hiddenCategories: [{ xtreamId: 404, type: 'live' }],
|
||||
playbackPositions: [],
|
||||
})
|
||||
);
|
||||
expect(router.navigate).toHaveBeenCalledWith([
|
||||
|
||||
@@ -3,7 +3,14 @@ import {
|
||||
DragDropModule,
|
||||
moveItemInArray,
|
||||
} from '@angular/cdk/drag-drop';
|
||||
import { Component, effect, inject, input, output, signal } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
effect,
|
||||
inject,
|
||||
input,
|
||||
output,
|
||||
signal,
|
||||
} from '@angular/core';
|
||||
import { toSignal } from '@angular/core/rxjs-interop';
|
||||
import { MatDialog } from '@angular/material/dialog';
|
||||
import { MatInputModule } from '@angular/material/input';
|
||||
@@ -25,9 +32,11 @@ import {
|
||||
DataService,
|
||||
DbOperationEvent,
|
||||
isDbAbortError,
|
||||
PlaybackPositionService,
|
||||
PlaylistRefreshService,
|
||||
SortBy,
|
||||
SortService,
|
||||
XtreamPendingRestoreService,
|
||||
} from 'services';
|
||||
import {
|
||||
PLAYLIST_UPDATE,
|
||||
@@ -64,6 +73,7 @@ export class RecentPlaylistsComponent {
|
||||
private readonly dialog = inject(MatDialog);
|
||||
private readonly dialogService = inject(DialogService);
|
||||
private readonly dataService = inject(DataService);
|
||||
private readonly playbackPositionService = inject(PlaybackPositionService);
|
||||
private readonly playlistRefreshService = inject(PlaylistRefreshService);
|
||||
private readonly router = inject(Router);
|
||||
private readonly snackBar = inject(MatSnackBar);
|
||||
@@ -71,6 +81,9 @@ export class RecentPlaylistsComponent {
|
||||
private readonly store = inject(Store);
|
||||
private readonly translate = inject(TranslateService);
|
||||
private readonly playlistContext = inject(PlaylistContextFacade);
|
||||
private readonly pendingRestoreService = inject(
|
||||
XtreamPendingRestoreService
|
||||
);
|
||||
|
||||
readonly sidebarMode = input(false);
|
||||
readonly searchQueryInput = input<string>('');
|
||||
@@ -205,10 +218,7 @@ export class RecentPlaylistsComponent {
|
||||
* @param playlistId playlist id to remove
|
||||
*/
|
||||
removeClicked(item: PlaylistMeta): void {
|
||||
if (
|
||||
this.isDeletePending(item._id) ||
|
||||
this.isRefreshPending(item._id)
|
||||
) {
|
||||
if (this.isDeletePending(item._id) || this.isRefreshPending(item._id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -228,10 +238,7 @@ export class RecentPlaylistsComponent {
|
||||
* @param playlistId playlist id to remove
|
||||
*/
|
||||
async removePlaylist(item: PlaylistMeta) {
|
||||
if (
|
||||
this.isDeletePending(item._id) ||
|
||||
this.isRefreshPending(item._id)
|
||||
) {
|
||||
if (this.isDeletePending(item._id) || this.isRefreshPending(item._id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -276,10 +283,7 @@ export class RecentPlaylistsComponent {
|
||||
* @param item playlist to update
|
||||
*/
|
||||
refreshPlaylist(item: PlaylistMeta) {
|
||||
if (
|
||||
this.isDeletePending(item._id) ||
|
||||
this.isRefreshPending(item._id)
|
||||
) {
|
||||
if (this.isDeletePending(item._id) || this.isRefreshPending(item._id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -303,10 +307,7 @@ export class RecentPlaylistsComponent {
|
||||
* @param item Xtream playlist to refresh
|
||||
*/
|
||||
async refreshXtreamPlaylist(item: PlaylistMeta) {
|
||||
if (
|
||||
this.isDeletePending(item._id) ||
|
||||
this.isRefreshPending(item._id)
|
||||
) {
|
||||
if (this.isDeletePending(item._id) || this.isRefreshPending(item._id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -326,9 +327,8 @@ export class RecentPlaylistsComponent {
|
||||
}
|
||||
|
||||
this.setPendingRefresh(item._id, true);
|
||||
const operationId = this.databaseService.createOperationId(
|
||||
'xtream-refresh'
|
||||
);
|
||||
const operationId =
|
||||
this.databaseService.createOperationId('xtream-refresh');
|
||||
|
||||
try {
|
||||
// Show immediate feedback — deletion can take several seconds
|
||||
@@ -344,41 +344,34 @@ export class RecentPlaylistsComponent {
|
||||
// Delete content/categories and update the timestamp in
|
||||
// parallel — both operations are fully independent.
|
||||
const updateDate = Date.now();
|
||||
const [
|
||||
{
|
||||
favoritedXtreamIds,
|
||||
recentlyViewedXtreamIds,
|
||||
hiddenCategories,
|
||||
},
|
||||
] = await Promise.all([
|
||||
this.databaseService.deleteXtreamPlaylistContent(
|
||||
item._id,
|
||||
{
|
||||
operationId,
|
||||
onEvent: (workerEvent) =>
|
||||
this.updateBusyOperation(
|
||||
item._id,
|
||||
workerEvent
|
||||
),
|
||||
}
|
||||
),
|
||||
this.databaseService.updateXtreamPlaylistDetails({
|
||||
id: item._id,
|
||||
updateDate,
|
||||
}),
|
||||
]);
|
||||
|
||||
const restoreKey = `xtream-restore-${item._id}`;
|
||||
const restorePayload = {
|
||||
favoritedXtreamIds,
|
||||
recentlyViewedXtreamIds,
|
||||
hiddenCategories,
|
||||
};
|
||||
localStorage.setItem(
|
||||
restoreKey,
|
||||
JSON.stringify(restorePayload)
|
||||
const [restoreState, playbackPositions] = await Promise.all(
|
||||
[
|
||||
this.databaseService.deleteXtreamPlaylistContent(
|
||||
item._id,
|
||||
{
|
||||
operationId,
|
||||
onEvent: (workerEvent) =>
|
||||
this.updateBusyOperation(
|
||||
item._id,
|
||||
workerEvent
|
||||
),
|
||||
}
|
||||
),
|
||||
this.playbackPositionService.getAllPlaybackPositions(
|
||||
item._id
|
||||
),
|
||||
this.databaseService.updateXtreamPlaylistDetails({
|
||||
id: item._id,
|
||||
updateDate,
|
||||
}),
|
||||
]
|
||||
);
|
||||
|
||||
this.pendingRestoreService.set(item._id, {
|
||||
...restoreState,
|
||||
playbackPositions,
|
||||
});
|
||||
|
||||
// Update the timestamp in NgRx / IndexedDB
|
||||
this.store.dispatch(
|
||||
PlaylistActions.updatePlaylistMeta({
|
||||
@@ -390,7 +383,10 @@ export class RecentPlaylistsComponent {
|
||||
this.router.navigate(['/workspace', 'xtreams', item._id]);
|
||||
} catch (error) {
|
||||
if (!isDbAbortError(error)) {
|
||||
console.error('Error refreshing Xtream playlist:', error);
|
||||
console.error(
|
||||
'Error refreshing Xtream playlist:',
|
||||
error
|
||||
);
|
||||
this.snackBar.open(
|
||||
this.translate.instant(
|
||||
'HOME.PLAYLISTS.REFRESH_XTREAM_DIALOG.ERROR'
|
||||
@@ -408,35 +404,32 @@ export class RecentPlaylistsComponent {
|
||||
}
|
||||
|
||||
private async refreshM3uPlaylist(item: PlaylistMeta): Promise<void> {
|
||||
if (
|
||||
this.isDeletePending(item._id) ||
|
||||
this.isRefreshPending(item._id)
|
||||
) {
|
||||
if (this.isDeletePending(item._id) || this.isRefreshPending(item._id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.setPendingRefresh(item._id, true);
|
||||
const operationId = this.databaseService.createOperationId(
|
||||
'playlist-refresh'
|
||||
);
|
||||
const operationId =
|
||||
this.databaseService.createOperationId('playlist-refresh');
|
||||
|
||||
try {
|
||||
const refreshedPlaylist = await this.playlistRefreshService.refreshPlaylist(
|
||||
{
|
||||
operationId,
|
||||
playlistId: item._id,
|
||||
title: item.title,
|
||||
url: item.url,
|
||||
filePath: item.filePath,
|
||||
},
|
||||
{
|
||||
onEvent: (event) =>
|
||||
this.updateBusyOperation(
|
||||
item._id,
|
||||
this.toPlaylistRefreshBusyEvent(event)
|
||||
),
|
||||
}
|
||||
);
|
||||
const refreshedPlaylist =
|
||||
await this.playlistRefreshService.refreshPlaylist(
|
||||
{
|
||||
operationId,
|
||||
playlistId: item._id,
|
||||
title: item.title,
|
||||
url: item.url,
|
||||
filePath: item.filePath,
|
||||
},
|
||||
{
|
||||
onEvent: (event) =>
|
||||
this.updateBusyOperation(
|
||||
item._id,
|
||||
this.toPlaylistRefreshBusyEvent(event)
|
||||
),
|
||||
}
|
||||
);
|
||||
|
||||
this.updateBusyOperation(item._id, {
|
||||
operationId,
|
||||
@@ -458,7 +451,9 @@ export class RecentPlaylistsComponent {
|
||||
|
||||
this.clearBusyOperation(item._id);
|
||||
this.snackBar.open(
|
||||
this.translate.instant('HOME.PLAYLISTS.PLAYLIST_UPDATE_SUCCESS'),
|
||||
this.translate.instant(
|
||||
'HOME.PLAYLISTS.PLAYLIST_UPDATE_SUCCESS'
|
||||
),
|
||||
null,
|
||||
{ duration: 2000 }
|
||||
);
|
||||
@@ -540,7 +535,9 @@ export class RecentPlaylistsComponent {
|
||||
}
|
||||
|
||||
if (operation.operation === 'playlist-refresh') {
|
||||
await this.playlistRefreshService.cancelRefresh(operation.operationId);
|
||||
await this.playlistRefreshService.cancelRefresh(
|
||||
operation.operationId
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -710,7 +707,9 @@ export class RecentPlaylistsComponent {
|
||||
item: PlaylistMeta
|
||||
): string {
|
||||
if (item.filePath) {
|
||||
const message = String((error as { message?: string })?.message ?? error);
|
||||
const message = String(
|
||||
(error as { message?: string })?.message ?? error
|
||||
);
|
||||
|
||||
if (/(ENOENT|no such file or directory|not found)/i.test(message)) {
|
||||
return this.translateWithFallback(
|
||||
|
||||
@@ -5,7 +5,11 @@ import { Router } from '@angular/router';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DialogService } from 'components';
|
||||
import { DatabaseService, PlaylistRefreshService } from 'services';
|
||||
import {
|
||||
DatabaseService,
|
||||
PlaybackPositionService,
|
||||
PlaylistRefreshService,
|
||||
} from 'services';
|
||||
import { ChannelActions, PlaylistActions } from 'm3u-state';
|
||||
import { Playlist, PlaylistMeta } from 'shared-interfaces';
|
||||
import { PlaylistContextFacade } from './playlist-context.facade';
|
||||
@@ -46,7 +50,12 @@ describe('PlaylistRefreshActionService', () => {
|
||||
let playlistRefreshService: {
|
||||
refreshPlaylist: jest.Mock;
|
||||
};
|
||||
let routeProvider: ReturnType<typeof signal<'playlists' | 'xtreams' | null>>;
|
||||
let playbackPositionService: {
|
||||
getAllPlaybackPositions: jest.Mock;
|
||||
};
|
||||
let routeProvider: ReturnType<
|
||||
typeof signal<'playlists' | 'xtreams' | null>
|
||||
>;
|
||||
let resolvedPlaylistId: ReturnType<typeof signal<string | null>>;
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -56,14 +65,24 @@ describe('PlaylistRefreshActionService', () => {
|
||||
createOperationId: jest.fn((prefix: string) => `${prefix}-op`),
|
||||
deleteXtreamPlaylistContent: jest.fn().mockResolvedValue({
|
||||
success: true,
|
||||
favoritedXtreamIds: [101, 202],
|
||||
recentlyViewedXtreamIds: [
|
||||
favorites: [
|
||||
{
|
||||
xtreamId: 101,
|
||||
contentType: 'live',
|
||||
},
|
||||
{
|
||||
xtreamId: 202,
|
||||
contentType: 'movie',
|
||||
},
|
||||
],
|
||||
recentlyViewed: [
|
||||
{
|
||||
xtreamId: 303,
|
||||
contentType: 'series',
|
||||
viewedAt: '2026-04-04T08:00:00.000Z',
|
||||
},
|
||||
],
|
||||
hiddenCategories: [{ xtreamId: 404, type: 'live' }],
|
||||
hiddenCategories: [{ xtreamId: 404, categoryType: 'live' }],
|
||||
}),
|
||||
updateXtreamPlaylistDetails: jest.fn().mockResolvedValue(true),
|
||||
};
|
||||
@@ -82,6 +101,9 @@ describe('PlaylistRefreshActionService', () => {
|
||||
playlistRefreshService = {
|
||||
refreshPlaylist: jest.fn(),
|
||||
};
|
||||
playbackPositionService = {
|
||||
getAllPlaybackPositions: jest.fn().mockResolvedValue([]),
|
||||
};
|
||||
routeProvider = signal<'playlists' | 'xtreams' | null>('xtreams');
|
||||
resolvedPlaylistId = signal<string | null>(null);
|
||||
|
||||
@@ -118,6 +140,10 @@ describe('PlaylistRefreshActionService', () => {
|
||||
provide: PlaylistRefreshService,
|
||||
useValue: playlistRefreshService,
|
||||
},
|
||||
{
|
||||
provide: PlaybackPositionService,
|
||||
useValue: playbackPositionService,
|
||||
},
|
||||
{
|
||||
provide: PlaylistContextFacade,
|
||||
useValue: {
|
||||
@@ -171,14 +197,25 @@ describe('PlaylistRefreshActionService', () => {
|
||||
expect(setItemSpy).toHaveBeenCalledWith(
|
||||
`xtream-restore-${item._id}`,
|
||||
JSON.stringify({
|
||||
favoritedXtreamIds: [101, 202],
|
||||
recentlyViewedXtreamIds: [
|
||||
hiddenCategories: [{ xtreamId: 404, categoryType: 'live' }],
|
||||
favorites: [
|
||||
{
|
||||
xtreamId: 101,
|
||||
contentType: 'live',
|
||||
},
|
||||
{
|
||||
xtreamId: 202,
|
||||
contentType: 'movie',
|
||||
},
|
||||
],
|
||||
recentlyViewed: [
|
||||
{
|
||||
xtreamId: 303,
|
||||
contentType: 'series',
|
||||
viewedAt: '2026-04-04T08:00:00.000Z',
|
||||
},
|
||||
],
|
||||
hiddenCategories: [{ xtreamId: 404, type: 'live' }],
|
||||
playbackPositions: [],
|
||||
})
|
||||
);
|
||||
expect(store.dispatch).toHaveBeenCalledWith(
|
||||
@@ -212,7 +249,9 @@ describe('PlaylistRefreshActionService', () => {
|
||||
} as Playlist;
|
||||
routeProvider.set('playlists');
|
||||
resolvedPlaylistId.set(item._id);
|
||||
playlistRefreshService.refreshPlaylist.mockResolvedValue(refreshedPlaylist);
|
||||
playlistRefreshService.refreshPlaylist.mockResolvedValue(
|
||||
refreshedPlaylist
|
||||
);
|
||||
|
||||
service.refresh(item);
|
||||
await Promise.resolve();
|
||||
|
||||
@@ -7,7 +7,9 @@ import { DialogService } from 'components';
|
||||
import {
|
||||
DatabaseService,
|
||||
isDbAbortError,
|
||||
PlaybackPositionService,
|
||||
PlaylistRefreshService,
|
||||
XtreamPendingRestoreService,
|
||||
} from 'services';
|
||||
import { ChannelActions, PlaylistActions } from 'm3u-state';
|
||||
import { PlaylistMeta } from 'shared-interfaces';
|
||||
@@ -21,8 +23,12 @@ export class PlaylistRefreshActionService {
|
||||
private readonly snackBar = inject(MatSnackBar);
|
||||
private readonly dialogService = inject(DialogService);
|
||||
private readonly databaseService = inject(DatabaseService);
|
||||
private readonly playbackPositionService = inject(PlaybackPositionService);
|
||||
private readonly playlistRefreshService = inject(PlaylistRefreshService);
|
||||
private readonly playlistContext = inject(PlaylistContextFacade);
|
||||
private readonly pendingRestoreService = inject(
|
||||
XtreamPendingRestoreService
|
||||
);
|
||||
|
||||
readonly isRefreshing = signal(false);
|
||||
|
||||
@@ -31,9 +37,7 @@ export class PlaylistRefreshActionService {
|
||||
return false;
|
||||
}
|
||||
|
||||
return Boolean(
|
||||
playlist.serverUrl || playlist.url || playlist.filePath
|
||||
);
|
||||
return Boolean(playlist.serverUrl || playlist.url || playlist.filePath);
|
||||
}
|
||||
|
||||
refresh(playlist: PlaylistMeta): void {
|
||||
@@ -75,34 +79,27 @@ export class PlaylistRefreshActionService {
|
||||
);
|
||||
|
||||
const updateDate = Date.now();
|
||||
const [
|
||||
{
|
||||
favoritedXtreamIds,
|
||||
recentlyViewedXtreamIds,
|
||||
hiddenCategories,
|
||||
},
|
||||
] = await Promise.all([
|
||||
this.databaseService.deleteXtreamPlaylistContent(
|
||||
item._id,
|
||||
{ operationId }
|
||||
),
|
||||
this.databaseService.updateXtreamPlaylistDetails({
|
||||
id: item._id,
|
||||
updateDate,
|
||||
}),
|
||||
]);
|
||||
|
||||
const restoreKey = `xtream-restore-${item._id}`;
|
||||
const restorePayload = {
|
||||
favoritedXtreamIds,
|
||||
recentlyViewedXtreamIds,
|
||||
hiddenCategories,
|
||||
};
|
||||
localStorage.setItem(
|
||||
restoreKey,
|
||||
JSON.stringify(restorePayload)
|
||||
const [restoreState, playbackPositions] = await Promise.all(
|
||||
[
|
||||
this.databaseService.deleteXtreamPlaylistContent(
|
||||
item._id,
|
||||
{ operationId }
|
||||
),
|
||||
this.playbackPositionService.getAllPlaybackPositions(
|
||||
item._id
|
||||
),
|
||||
this.databaseService.updateXtreamPlaylistDetails({
|
||||
id: item._id,
|
||||
updateDate,
|
||||
}),
|
||||
]
|
||||
);
|
||||
|
||||
this.pendingRestoreService.set(item._id, {
|
||||
...restoreState,
|
||||
playbackPositions,
|
||||
});
|
||||
|
||||
this.store.dispatch(
|
||||
PlaylistActions.updatePlaylistMeta({
|
||||
playlist: { ...item, updateDate },
|
||||
@@ -197,10 +194,7 @@ export class PlaylistRefreshActionService {
|
||||
}
|
||||
}
|
||||
|
||||
private getRefreshErrorMessage(
|
||||
error: unknown,
|
||||
item: PlaylistMeta
|
||||
): string {
|
||||
private getRefreshErrorMessage(error: unknown, item: PlaylistMeta): string {
|
||||
if (
|
||||
error instanceof Error &&
|
||||
error.message?.includes('ENOENT') &&
|
||||
@@ -211,8 +205,6 @@ export class PlaylistRefreshActionService {
|
||||
);
|
||||
}
|
||||
|
||||
return this.translate.instant(
|
||||
'HOME.PLAYLISTS.PLAYLIST_UPDATE_ERROR'
|
||||
);
|
||||
return this.translate.instant('HOME.PLAYLISTS.PLAYLIST_UPDATE_ERROR');
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user