mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-10 18:36:15 -08:00
feat(stalker): display all type items when no category is selected
This commit is contained in:
1 parent
53a23cd03a
commit
52a618fd0f
6 files changed
+223
-58
No files matched your search
@@ -48,7 +48,11 @@
|
||||
|
||||
{{ getContentLabel() }}
|
||||
|
||||
@if (!contentItems() && !isContentLoading()) {
|
||||
@if (
|
||||
!contentItems() &&
|
||||
!isContentLoading() &&
|
||||
!stalkerStore.selectedCategoryId()
|
||||
) {
|
||||
<h2>
|
||||
{{ 'PORTALS.SELECT_CATEGORY' | translate }}
|
||||
</h2>
|
||||
|
||||
@@ -87,11 +87,34 @@ export class StalkerMainContainerComponent {
|
||||
}
|
||||
|
||||
getContentLabel(): string {
|
||||
const categoryName = this.stalkerStore.getSelectedCategoryName();
|
||||
const selectedContentType = this.stalkerStore.selectedContentType();
|
||||
const selectedCategoryId = this.stalkerStore.selectedCategoryId();
|
||||
const typeLabelByContentType: Record<string, string> = {
|
||||
vod: this.translateService.instant('PORTALS.SIDEBAR.MOVIES'),
|
||||
series: this.translateService.instant('PORTALS.SIDEBAR.SERIES'),
|
||||
itv: this.translateService.instant('PORTALS.SIDEBAR.LIVE_TV'),
|
||||
};
|
||||
const selectedTypeLabel =
|
||||
typeLabelByContentType[selectedContentType] ?? '';
|
||||
|
||||
const selectedCategoryName = this.stalkerStore.getSelectedCategoryName();
|
||||
let categoryName = selectedCategoryName;
|
||||
|
||||
// For implicit "All" view, show a type-specific title so switching
|
||||
// between VOD/Series updates header text immediately.
|
||||
if (selectedCategoryId === '*') {
|
||||
categoryName = `${selectedTypeLabel} - ${this.translateService.instant(
|
||||
'PORTALS.ALL_CATEGORIES'
|
||||
)}`;
|
||||
} else if (!categoryName) {
|
||||
// Fallback while categories are loading or when no category is selected.
|
||||
categoryName = selectedTypeLabel;
|
||||
}
|
||||
|
||||
// Show page number when viewing category content (not detail view)
|
||||
if (
|
||||
!this.stalkerStore.selectedItem() &&
|
||||
!this.isContentLoading() &&
|
||||
this.stalkerStore.getTotalPages() > 1
|
||||
) {
|
||||
const currentPage = this.stalkerStore.page() + 1;
|
||||
|
||||
@@ -4,6 +4,7 @@ import { ActivatedRoute, Router, RouterOutlet } from '@angular/router';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { PlaylistActions, selectPlaylistById } from 'm3u-state';
|
||||
import { map, switchMap } from 'rxjs';
|
||||
import { createLogger } from '../../shared/utils/logger';
|
||||
import { NavigationComponent } from '../../xtream-tauri/navigation/navigation.component';
|
||||
import { NavigationItem } from '../../xtream-tauri/navigation/navigation.interface';
|
||||
import { XtreamStore } from '../../xtream-tauri/stores/xtream.store';
|
||||
@@ -17,6 +18,7 @@ import { StalkerStore } from '../stalker.store';
|
||||
providers: [XtreamStore],
|
||||
})
|
||||
export class StalkerShellComponent implements OnDestroy {
|
||||
private readonly logger = createLogger('StalkerShell');
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
private readonly router = inject(Router);
|
||||
readonly stalkerStore = inject(StalkerStore);
|
||||
@@ -64,7 +66,9 @@ export class StalkerShellComponent implements OnDestroy {
|
||||
const childRoute = this.route.snapshot.firstChild;
|
||||
const path = childRoute?.url[0]?.path;
|
||||
const validTypes = ['vod', 'series', 'itv'];
|
||||
const initialType = validTypes.includes(path) ? (path as any) : 'vod';
|
||||
const initialType = validTypes.includes(path)
|
||||
? (path as any)
|
||||
: 'vod';
|
||||
this.stalkerStore.setSelectedContentType(initialType);
|
||||
});
|
||||
|
||||
@@ -76,7 +80,7 @@ export class StalkerShellComponent implements OnDestroy {
|
||||
setContentType(type: 'vod' | 'live' | 'series' | 'itv') {
|
||||
if (type === 'live') type = 'itv';
|
||||
this.stalkerStore.setSelectedContentType(type);
|
||||
this.stalkerStore.setSelectedCategory(null);
|
||||
this.stalkerStore.setSelectedCategory(type === 'itv' ? null : '*');
|
||||
this.router.navigate([type], {
|
||||
relativeTo: this.route,
|
||||
});
|
||||
|
||||
@@ -20,6 +20,17 @@ export const stalkerRoutes: Route[] = [
|
||||
(c) => c.StalkerMainContainerComponent
|
||||
),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
data: {
|
||||
api: 'stalker',
|
||||
contentType: 'vod',
|
||||
},
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'../xtream-tauri/category-content-view/category-content-view.component'
|
||||
).then((c) => c.CategoryContentViewComponent),
|
||||
},
|
||||
{
|
||||
path: ':categoryId',
|
||||
data: {
|
||||
@@ -53,6 +64,17 @@ export const stalkerRoutes: Route[] = [
|
||||
(c) => c.StalkerMainContainerComponent
|
||||
),
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
loadComponent: () =>
|
||||
import(
|
||||
'../xtream-tauri/category-content-view/category-content-view.component'
|
||||
).then((c) => c.CategoryContentViewComponent),
|
||||
data: {
|
||||
api: 'stalker',
|
||||
contentType: 'series',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: ':categoryId',
|
||||
loadComponent: () =>
|
||||
|
||||
@@ -7,12 +7,14 @@ import {
|
||||
withProps,
|
||||
withState,
|
||||
} from '@ngrx/signals';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { DataService, StalkerSessionService } from 'services';
|
||||
import {
|
||||
Playlist,
|
||||
STALKER_REQUEST,
|
||||
StalkerPortalActions,
|
||||
} from 'shared-interfaces';
|
||||
import { createLogger } from '../../../shared/utils/logger';
|
||||
import {
|
||||
StalkerCategoryItem,
|
||||
StalkerContentItem,
|
||||
@@ -20,7 +22,6 @@ import {
|
||||
StalkerVodSource,
|
||||
} from '../../models';
|
||||
import { StalkerContentTypes } from '../../stalker-content-types';
|
||||
import { createLogger } from '../../../shared/utils/logger';
|
||||
import { toStalkerContentItem, toStalkerItvChannel } from '../utils';
|
||||
|
||||
/**
|
||||
@@ -52,7 +53,8 @@ export function withStalkerContent() {
|
||||
(
|
||||
store,
|
||||
dataService = inject(DataService),
|
||||
stalkerSession = inject(StalkerSessionService)
|
||||
stalkerSession = inject(StalkerSessionService),
|
||||
translateService = inject(TranslateService)
|
||||
) => ({
|
||||
getCategoryResource: resource({
|
||||
params: () => ({
|
||||
@@ -83,7 +85,8 @@ export function withStalkerContent() {
|
||||
break;
|
||||
}
|
||||
|
||||
const { portalUrl, macAddress } = params.currentPlaylist;
|
||||
const { portalUrl, macAddress } =
|
||||
params.currentPlaylist;
|
||||
|
||||
// Use makeAuthenticatedRequest for automatic retry on auth failure
|
||||
const playlist = params.currentPlaylist as Playlist;
|
||||
@@ -115,18 +118,37 @@ export function withStalkerContent() {
|
||||
|
||||
// Guard: ensure response has expected structure
|
||||
if (!response?.js || !Array.isArray(response.js)) {
|
||||
logger.warn('Invalid categories response', response);
|
||||
logger.warn(
|
||||
'Invalid categories response',
|
||||
response
|
||||
);
|
||||
return [];
|
||||
}
|
||||
|
||||
const categories = response.js
|
||||
.map((item): StalkerCategoryItem => ({
|
||||
category_name: item.title,
|
||||
category_id: String(item.id),
|
||||
}))
|
||||
.map(
|
||||
(item): StalkerCategoryItem => ({
|
||||
category_name: item.title,
|
||||
category_id: String(item.id),
|
||||
})
|
||||
)
|
||||
.sort((a, b) =>
|
||||
a.category_name.localeCompare(b.category_name)
|
||||
);
|
||||
if (
|
||||
categories.length > 0 &&
|
||||
!categories.some(
|
||||
(category) =>
|
||||
String(category.category_id) === '*'
|
||||
)
|
||||
) {
|
||||
categories.unshift({
|
||||
category_name: translateService.instant(
|
||||
'PORTALS.ALL_CATEGORIES'
|
||||
),
|
||||
category_id: '*',
|
||||
});
|
||||
}
|
||||
patchState(store, {
|
||||
[`${params.contentType}Categories`]: categories,
|
||||
});
|
||||
@@ -140,6 +162,21 @@ export function withStalkerContent() {
|
||||
action: StalkerPortalActions.GetOrderedList,
|
||||
search: (store as any).searchPhrase(),
|
||||
pageIndex: (store as any).page() + 1,
|
||||
availableCategoryCount: (() => {
|
||||
const contentType = (
|
||||
store as any
|
||||
).selectedContentType();
|
||||
const categories =
|
||||
contentType === 'vod'
|
||||
? store.vodCategories()
|
||||
: contentType === 'series'
|
||||
? store.seriesCategories()
|
||||
: store.itvCategories();
|
||||
return categories.filter(
|
||||
(category) =>
|
||||
String(category.category_id) !== '*'
|
||||
).length;
|
||||
})(),
|
||||
}),
|
||||
loader: async ({
|
||||
params,
|
||||
@@ -151,11 +188,22 @@ export function withStalkerContent() {
|
||||
) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
if (
|
||||
params.category === '*' &&
|
||||
(params.contentType === 'vod' ||
|
||||
params.contentType === 'series') &&
|
||||
params.availableCategoryCount === 0
|
||||
) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
const currentPlaylist = (store as any).currentPlaylist;
|
||||
|
||||
// Guard: ensure currentPlaylist is available (may not be during deep link init)
|
||||
if (!currentPlaylist() || !currentPlaylist().portalUrl) {
|
||||
if (
|
||||
!currentPlaylist() ||
|
||||
!currentPlaylist().portalUrl
|
||||
) {
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
// VOD uses 'genre' param, series uses 'category' param, itv uses both
|
||||
@@ -242,7 +290,8 @@ export function withStalkerContent() {
|
||||
const totalLoaded = store.itvChannels().length;
|
||||
patchState(store, {
|
||||
hasMoreChannels:
|
||||
totalLoaded < (response.js.total_items ?? 0),
|
||||
totalLoaded <
|
||||
(response.js.total_items ?? 0),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+107
-44
@@ -1,22 +1,27 @@
|
||||
import { Component, inject, OnInit, OnDestroy, computed, signal, effect } from '@angular/core';
|
||||
import {
|
||||
Component,
|
||||
computed,
|
||||
effect,
|
||||
inject,
|
||||
OnDestroy,
|
||||
OnInit,
|
||||
signal,
|
||||
} from '@angular/core';
|
||||
import { PageEvent } from '@angular/material/paginator';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { TranslatePipe } from '@ngx-translate/core';
|
||||
import { PlaylistsService } from 'services';
|
||||
import {
|
||||
VodDetailsItem,
|
||||
StalkerVodDetails,
|
||||
createStalkerVodItem,
|
||||
PlaybackPositionData,
|
||||
StalkerVodDetails,
|
||||
VodDetailsItem,
|
||||
} from 'shared-interfaces';
|
||||
import { DownloadsService } from '../../services/downloads.service';
|
||||
import { GridListComponent } from '../../shared/components/grid-list/grid-list.component';
|
||||
import { createLogger } from '../../shared/utils/logger';
|
||||
import { StalkerSeriesViewComponent } from '../../stalker/stalker-series-view/stalker-series-view.component';
|
||||
import { StalkerStore } from '../../stalker/stalker.store';
|
||||
import { VodDetailsComponent } from '../../xtream/vod-details/vod-details.component';
|
||||
import { XTREAM_DATA_SOURCE } from '../data-sources';
|
||||
import { PlaylistErrorViewComponent } from '../playlist-error-view/playlist-error-view.component';
|
||||
import { XtreamStore } from '../stores/xtream.store';
|
||||
import {
|
||||
buildStalkerSelectedVodItem,
|
||||
createPortalFavoritesResource,
|
||||
@@ -26,8 +31,11 @@ import {
|
||||
normalizeStalkerEntityIdAsNumber,
|
||||
toggleStalkerVodFavorite,
|
||||
} from '../../stalker/stalker-vod.utils';
|
||||
import { createLogger } from '../../shared/utils/logger';
|
||||
import { DownloadsService } from '../../services/downloads.service';
|
||||
import { StalkerStore } from '../../stalker/stalker.store';
|
||||
import { VodDetailsComponent } from '../../xtream/vod-details/vod-details.component';
|
||||
import { XTREAM_DATA_SOURCE } from '../data-sources';
|
||||
import { PlaylistErrorViewComponent } from '../playlist-error-view/playlist-error-view.component';
|
||||
import { XtreamStore } from '../stores/xtream.store';
|
||||
|
||||
@Component({
|
||||
selector: 'app-category-content-view',
|
||||
@@ -67,9 +75,13 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
readonly paginatedContent = this.store.getPaginatedContent;
|
||||
|
||||
/** Stalker playback positions (key: `${contentType}_${id}`) */
|
||||
private readonly stalkerPositions = signal<Map<string, PlaybackPositionData>>(new Map());
|
||||
private readonly stalkerPositions = signal<
|
||||
Map<string, PlaybackPositionData>
|
||||
>(new Map());
|
||||
/** Stalker series positions (key: seriesId, value: episode positions) */
|
||||
private readonly stalkerSeriesPositions = signal<Map<number, PlaybackPositionData[]>>(new Map());
|
||||
private readonly stalkerSeriesPositions = signal<
|
||||
Map<number, PlaybackPositionData[]>
|
||||
>(new Map());
|
||||
/** Track which playlist we've loaded positions for */
|
||||
private loadedPositionsForPlaylistId: string | null = null;
|
||||
|
||||
@@ -77,11 +89,16 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
// Effect to load Stalker positions when playlist becomes available
|
||||
if (this.isStalker) {
|
||||
effect(() => {
|
||||
const stalkerStore = this.store as InstanceType<typeof StalkerStore>;
|
||||
const stalkerStore = this.store as InstanceType<
|
||||
typeof StalkerStore
|
||||
>;
|
||||
const playlist = stalkerStore.currentPlaylist();
|
||||
const playlistId = playlist?._id;
|
||||
|
||||
if (playlistId && playlistId !== this.loadedPositionsForPlaylistId) {
|
||||
if (
|
||||
playlistId &&
|
||||
playlistId !== this.loadedPositionsForPlaylistId
|
||||
) {
|
||||
this.loadedPositionsForPlaylistId = playlistId;
|
||||
this.loadStalkerPositions(playlistId);
|
||||
}
|
||||
@@ -89,7 +106,9 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
|
||||
// Effect to load position for selected VOD item (ensures fresh data after playback)
|
||||
effect(() => {
|
||||
const stalkerStore = this.store as InstanceType<typeof StalkerStore>;
|
||||
const stalkerStore = this.store as InstanceType<
|
||||
typeof StalkerStore
|
||||
>;
|
||||
const item = this.selectedItem();
|
||||
const playlist = stalkerStore.currentPlaylist();
|
||||
|
||||
@@ -100,16 +119,22 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
|
||||
// Listen for real-time playback position updates from video player
|
||||
if (window.electron?.onPlaybackPositionUpdate) {
|
||||
this.unsubscribePositionUpdates = window.electron.onPlaybackPositionUpdate(
|
||||
(data: PlaybackPositionData) => {
|
||||
if (data.contentType === 'vod' && data.contentXtreamId) {
|
||||
const key = `vod_${data.contentXtreamId}`;
|
||||
const updated = new Map(this.stalkerPositions());
|
||||
updated.set(key, data);
|
||||
this.stalkerPositions.set(updated);
|
||||
this.unsubscribePositionUpdates =
|
||||
window.electron.onPlaybackPositionUpdate(
|
||||
(data: PlaybackPositionData) => {
|
||||
if (
|
||||
data.contentType === 'vod' &&
|
||||
data.contentXtreamId
|
||||
) {
|
||||
const key = `vod_${data.contentXtreamId}`;
|
||||
const updated = new Map(
|
||||
this.stalkerPositions()
|
||||
);
|
||||
updated.set(key, data);
|
||||
this.stalkerPositions.set(updated);
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -129,10 +154,15 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
|
||||
// Check if this item has series/episode progress (watched episodes)
|
||||
// This works even when is_series flag isn't set on the item
|
||||
const hasSeriesProgress = seriesPositions.has(id) && seriesPositions.get(id)!.length > 0;
|
||||
const hasSeriesProgress =
|
||||
seriesPositions.has(id) &&
|
||||
seriesPositions.get(id)!.length > 0;
|
||||
|
||||
// For series content type, or items with is_series flag
|
||||
const isSeries = contentType === 'series' || item.is_series === '1' || item.is_series === 1;
|
||||
const isSeries =
|
||||
contentType === 'series' ||
|
||||
item.is_series === '1' ||
|
||||
item.is_series === 1;
|
||||
|
||||
if (hasSeriesProgress) {
|
||||
return { ...item, hasSeriesProgress: true };
|
||||
@@ -157,7 +187,9 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
|
||||
return items.map((item: any) => {
|
||||
const isSeries = this.contentType() === 'series';
|
||||
const id = Number(item.xtream_id || item.series_id || item.stream_id);
|
||||
const id = Number(
|
||||
item.xtream_id || item.series_id || item.stream_id
|
||||
);
|
||||
|
||||
if (isSeries) {
|
||||
return {
|
||||
@@ -210,7 +242,9 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
this.playlistService,
|
||||
() => {
|
||||
if (!this.isStalker) return undefined;
|
||||
const stalkerStore = this.store as InstanceType<typeof StalkerStore>;
|
||||
const stalkerStore = this.store as InstanceType<
|
||||
typeof StalkerStore
|
||||
>;
|
||||
return stalkerStore.currentPlaylist()?._id;
|
||||
},
|
||||
() => this.favoritesRefresh.refreshVersion()
|
||||
@@ -245,8 +279,22 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
if (categoryId) {
|
||||
this.store.setSelectedCategory(categoryId);
|
||||
} else {
|
||||
// No categoryId in route means "All Items"
|
||||
this.store.setSelectedCategory(null);
|
||||
// Stalker uses "*" as the "All" category id
|
||||
if (this.isStalker) {
|
||||
(
|
||||
this.store as InstanceType<typeof StalkerStore>
|
||||
).setSelectedCategory('*');
|
||||
} else {
|
||||
this.store.setSelectedCategory(null);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.isStalker) {
|
||||
this.logger.warn('Stalker category init from route', {
|
||||
routeCategoryId: categoryId ?? null,
|
||||
selectedCategoryId: (this.store as any).selectedCategoryId?.(),
|
||||
selectedContentType: this.contentType(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,7 +302,8 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
* Load all playback positions for a Stalker portal
|
||||
*/
|
||||
private async loadStalkerPositions(playlistId: string): Promise<void> {
|
||||
const positions = await this.dataSource.getAllPlaybackPositions(playlistId);
|
||||
const positions =
|
||||
await this.dataSource.getAllPlaybackPositions(playlistId);
|
||||
|
||||
const positionsMap = new Map<string, PlaybackPositionData>();
|
||||
const seriesMap = new Map<number, PlaybackPositionData[]>();
|
||||
@@ -278,8 +327,15 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
* Load playback position for a single VOD item
|
||||
*/
|
||||
private async loadSingleVodPosition(playlistId: string, vodId: number): Promise<void> {
|
||||
const position = await this.dataSource.getPlaybackPosition(playlistId, vodId, 'vod');
|
||||
private async loadSingleVodPosition(
|
||||
playlistId: string,
|
||||
vodId: number
|
||||
): Promise<void> {
|
||||
const position = await this.dataSource.getPlaybackPosition(
|
||||
playlistId,
|
||||
vodId,
|
||||
'vod'
|
||||
);
|
||||
|
||||
if (position) {
|
||||
const key = `vod_${vodId}`;
|
||||
@@ -292,10 +348,13 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
/**
|
||||
* Calculate progress percentage from position data
|
||||
*/
|
||||
private calculateProgress(position: PlaybackPositionData | undefined): number {
|
||||
private calculateProgress(
|
||||
position: PlaybackPositionData | undefined
|
||||
): number {
|
||||
if (!position || !position.durationSeconds) return 0;
|
||||
|
||||
const percent = (position.positionSeconds / position.durationSeconds) * 100;
|
||||
const percent =
|
||||
(position.positionSeconds / position.durationSeconds) * 100;
|
||||
|
||||
// If watched > 10s but percent < 1, return 1 to show visual progress
|
||||
if (position.positionSeconds > 10 && percent < 1) {
|
||||
@@ -359,10 +418,9 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
removeFromFavorites(favoriteId: string, onDone?: () => void) {
|
||||
this.logger.debug('Remove from favorites', favoriteId);
|
||||
if (this.isStalker) {
|
||||
(this.store as InstanceType<typeof StalkerStore>).removeFromFavorites(
|
||||
favoriteId,
|
||||
onDone
|
||||
);
|
||||
(
|
||||
this.store as InstanceType<typeof StalkerStore>
|
||||
).removeFromFavorites(favoriteId, onDone);
|
||||
return;
|
||||
}
|
||||
this.store.removeFromFavorites(favoriteId);
|
||||
@@ -381,9 +439,14 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
}
|
||||
|
||||
/** Handle resume from vod-details component */
|
||||
onVodResume(event: { item: VodDetailsItem; positionSeconds: number }): void {
|
||||
onVodResume(event: {
|
||||
item: VodDetailsItem;
|
||||
positionSeconds: number;
|
||||
}): void {
|
||||
if (event.item.type === 'stalker') {
|
||||
const stalkerStore = this.store as InstanceType<typeof StalkerStore>;
|
||||
const stalkerStore = this.store as InstanceType<
|
||||
typeof StalkerStore
|
||||
>;
|
||||
stalkerStore.createLinkToPlayVod(
|
||||
event.item.cmd,
|
||||
event.item.data.info?.name,
|
||||
@@ -435,7 +498,8 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
cmdToUse.includes('/media/') &&
|
||||
!cmdToUse.includes('/media/file_')
|
||||
) {
|
||||
const fileId = await stalkerStore.fetchMovieFileId(normalizedItemId);
|
||||
const fileId =
|
||||
await stalkerStore.fetchMovieFileId(normalizedItemId);
|
||||
if (fileId) {
|
||||
cmdToUse = `/media/file_${fileId}.mpg`;
|
||||
}
|
||||
@@ -448,8 +512,7 @@ export class CategoryContentViewComponent implements OnInit, OnDestroy {
|
||||
);
|
||||
if (!url) return;
|
||||
|
||||
const numericId =
|
||||
normalizeStalkerEntityIdAsNumber(itemData?.id) ?? 0;
|
||||
const numericId = normalizeStalkerEntityIdAsNumber(itemData?.id) ?? 0;
|
||||
|
||||
await this.downloadsService.startDownload({
|
||||
playlistId: playlist._id,
|
||||
|
||||
Reference in new issue
Block a user