refactor(logging): replace console.error and console.warn with logger utility in multiple components and services

This commit is contained in:
4gray committed 2026-02-14 11:45:56 +01:00
1 parent b9ac1ade78
commit 52947bdfac
15 files changed
+69 -42

No files matched your search

@@ -7,6 +7,7 @@ import { TranslatePipe } from '@ngx-translate/core';
import { selectActivePlaylist } from 'm3u-state';
import { XtreamApiService } from '../services/xtream-api.service';
import { XtreamAccountInfo } from './account-info.interface';
import { createLogger } from '../../shared/utils/logger';
@Component({
selector: 'app-account-info',
@@ -22,6 +23,7 @@ export class AccountInfoComponent {
}>(MAT_DIALOG_DATA);
private readonly xtreamApiService = inject(XtreamApiService);
private readonly store = inject(Store);
private readonly logger = createLogger('XtreamAccountInfo');
accountInfo: XtreamAccountInfo;
formattedExpDate: string;
@@ -59,7 +61,7 @@ export class AccountInfoComponent {
).toLocaleDateString();
}
} catch (error) {
console.error('Failed to fetch account info:', error);
this.logger.error('Failed to fetch account info', error);
}
}
@@ -70,4 +72,4 @@ export class AccountInfoComponent {
get isTrial(): boolean {
return this.accountInfo?.user_info?.is_trial === '1';
}
}
}
@@ -14,6 +14,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { MatSnackBar } from '@angular/material/snack-bar';
import { TranslatePipe } from '@ngx-translate/core';
import { DatabaseService, XCategoryFromDb } from 'services';
import { createLogger } from '../../shared/utils/logger';
export interface CategoryManagementDialogData {
playlistId: string;
@@ -47,6 +48,7 @@ export class CategoryManagementDialogComponent implements OnInit {
MatDialogRef<CategoryManagementDialogComponent>
);
readonly data = inject<CategoryManagementDialogData>(MAT_DIALOG_DATA);
private readonly logger = createLogger('CategoryManagementDialog');
readonly isLoading = signal(true);
readonly isSaving = signal(false);
@@ -95,7 +97,7 @@ export class CategoryManagementDialogComponent implements OnInit {
}))
);
} catch (error) {
console.error('Error loading categories:', error);
this.logger.error('Error loading categories', error);
} finally {
this.isLoading.set(false);
}
@@ -175,7 +177,7 @@ export class CategoryManagementDialogComponent implements OnInit {
this.dialogRef.close(true);
} catch (error) {
console.error('Error saving category visibility:', error);
this.logger.error('Error saving category visibility', error);
inject(MatSnackBar).open(
'Failed to save category visibility',
'Close',
@@ -14,6 +14,7 @@ import {
XtreamContentItem,
XtreamPlaylistData,
} from './xtream-data-source.interface';
import { createLogger } from '../../shared/utils/logger';
/**
* LocalStorage keys for PWA persistence
@@ -33,6 +34,7 @@ const STORAGE_KEYS = {
@Injectable({ providedIn: 'root' })
export class PwaXtreamDataSource implements IXtreamDataSource {
private readonly apiService = inject(XtreamApiService);
private readonly logger = createLogger('PwaXtreamDataSource');
// In-memory cache for the current session
private categoryCache = new Map<string, XtreamCategory[]>();
@@ -151,7 +153,7 @@ export class PwaXtreamDataSource implements IXtreamDataSource {
hidden: boolean
): Promise<void> {
// Category visibility is not supported in PWA mode
console.warn('Category visibility not supported in PWA mode');
this.logger.warn('Category visibility not supported in PWA mode');
}
// =========================================================================
@@ -7,6 +7,7 @@ import { ActivatedRoute, Router } from '@angular/router';
import groupBy from 'lodash/groupBy';
import { ContentCardComponent } from '../../shared/components/content-card/content-card.component';
import { XtreamStore } from '../stores/xtream.store';
import { createLogger } from '../../shared/utils/logger';
@Component({
selector: 'app-recently-viewed',
@@ -26,6 +27,7 @@ export class RecentlyViewedComponent {
private activatedRoute = inject(ActivatedRoute);
private router = inject(Router);
private dialogData = inject(MAT_DIALOG_DATA, { optional: true });
private readonly logger = createLogger('XtreamRecentlyViewed');
readonly isGlobal = this.dialogData?.isGlobal ?? false;
readonly recentItems = computed(() =>
@@ -51,7 +53,7 @@ export class RecentlyViewedComponent {
try {
await this.xtreamStore.loadGlobalRecentItems();
} catch (error) {
console.error('Error loading global items:', error);
this.logger.error('Error loading global items', error);
}
}
@@ -28,6 +28,7 @@ import { ContentCardComponent } from '../../shared/components/content-card/conte
import { SearchLayoutComponent } from '../../shared/components/search-layout/search-layout.component';
import { XtreamStore } from '../stores/xtream.store';
import { SearchFilters } from '../stores/features/with-search.feature';
import { createLogger } from '../../shared/utils/logger';
interface SearchResultsData {
isGlobalSearch: boolean;
@@ -55,6 +56,7 @@ export class SearchResultsComponent implements AfterViewInit {
readonly router = inject(Router);
readonly activatedRoute = inject(ActivatedRoute);
readonly databaseService = inject(DatabaseService);
private readonly logger = createLogger('XtreamSearchResults');
/** Search term from store */
readonly searchTerm = this.xtreamStore.searchTerm;
@@ -182,7 +184,7 @@ export class SearchResultsComponent implements AfterViewInit {
this.xtreamStore.setIsSearching(false);
}
} catch (error) {
console.error('Error in global search:', error);
this.logger.error('Error in global search', error);
this.xtreamStore.resetSearchResults();
}
}
@@ -12,6 +12,7 @@ import { StalkerStore } from '../../stalker/stalker.store';
import { ProgressCapsuleComponent } from '../shared/progress-capsule/progress-capsule.component';
import { WatchedBadgeComponent } from '../shared/watched-badge/watched-badge.component';
import { DownloadsService } from '../../services/downloads.service';
import { createLogger } from '../../shared/utils/logger';
type EpisodeViewMode = 'grid' | 'list';
const EPISODE_VIEW_MODE_KEY = 'iptvnator_episode_view_mode';
@@ -36,6 +37,7 @@ export class SeasonContainerComponent implements OnInit {
private readonly xtreamStore = inject(XtreamStore);
private readonly stalkerStore = inject(StalkerStore);
private readonly downloadsService = inject(DownloadsService);
private readonly logger = createLogger('SeasonContainer');
readonly seasons = input.required<Record<string, XtreamSerieEpisode[]>>();
readonly seriesId = input.required<number>();
@@ -177,7 +179,7 @@ export class SeasonContainerComponent implements OnInit {
event.stopPropagation();
const playlistId = this.getPlaylistId(episode);
if (!playlistId) {
console.warn('[SeasonContainer] Cannot toggle watched: no playlist ID');
this.logger.warn('Cannot toggle watched: no playlist ID');
return;
}
@@ -218,9 +220,11 @@ export class SeasonContainerComponent implements OnInit {
const contentId = this.getEpisodeContentId(episode);
const inProgress = this.xtreamStore.isInProgress(contentId, 'episode');
if (inProgress) {
console.log(
`[SeasonContainer] Episode ${episode.title} (contentId=${contentId}, originalId=${(episode as any).originalId}) is IN PROGRESS`
);
this.logger.debug('Episode in progress', {
title: episode.title,
contentId,
originalId: (episode as any).originalId,
});
}
return inProgress;
}
@@ -354,11 +358,11 @@ export class SeasonContainerComponent implements OnInit {
episode.episode_num // series param for episode number
);
if (!url) {
console.error('[SeasonContainer] Failed to resolve Stalker stream URL');
this.logger.error('Failed to resolve Stalker stream URL');
return;
}
} catch (error) {
console.error('[SeasonContainer] Error resolving Stalker stream URL:', error);
this.logger.error('Error resolving Stalker stream URL', error);
return;
}
@@ -2,6 +2,7 @@ import { inject, Injectable, OnDestroy } from '@angular/core';
import { Subject } from 'rxjs';
import { EpgItem } from 'shared-interfaces';
import { XtreamApiService, XtreamCredentials } from './xtream-api.service';
import { createLogger } from '../../shared/utils/logger';
interface CacheEntry {
data: EpgItem[];
@@ -17,6 +18,7 @@ interface CacheEntry {
@Injectable({ providedIn: 'root' })
export class EpgQueueService implements OnDestroy {
private readonly apiService = inject(XtreamApiService);
private readonly logger = createLogger('EpgQueueService');
private readonly cache = new Map<number, CacheEntry>();
private queue: number[] = [];
@@ -115,8 +117,8 @@ export class EpgQueueService implements OnDestroy {
});
this.epgResult$.next({ streamId, items });
} catch (error) {
console.error(
`EpgQueueService: failed to load EPG for stream ${streamId}:`,
this.logger.error(
`Failed to load EPG for stream ${streamId}`,
error
);
} finally {
@@ -18,6 +18,7 @@ import {
} from '../../data-sources/xtream-data-source.interface';
import { XtreamCredentials } from '../../services/xtream-api.service';
import { ContentType } from '../../xtream-state';
import { createLogger } from '../../../shared/utils/logger';
/**
* Content state for managing categories and streams
@@ -61,6 +62,7 @@ const initialContentState: ContentState = {
* - Import progress tracking
*/
export function withContent() {
const logger = createLogger('withContent');
return signalStoreFeature(
withState<ContentState>(initialContentState),
@@ -174,7 +176,7 @@ export function withContent() {
isLoadingCategories: false,
});
} catch (error) {
console.error('Error fetching categories:', error);
logger.error('Error fetching categories', error);
patchState(store, { isLoadingCategories: false });
}
},
@@ -234,7 +236,7 @@ export function withContent() {
isLoadingContent: false,
});
} catch (error) {
console.error('Error fetching content:', error);
logger.error('Error fetching content', error);
patchState(store, { isLoadingContent: false });
}
},
@@ -275,10 +277,7 @@ export function withContent() {
);
localStorage.removeItem(restoreKey);
} catch (err) {
console.error(
'Error restoring user data:',
err
);
logger.error('Error restoring user data', err);
}
}
} finally {
@@ -318,7 +317,7 @@ export function withContent() {
serialCategories: series,
});
} catch (error) {
console.error('Error reloading categories:', error);
logger.error('Error reloading categories', error);
}
},
@@ -10,6 +10,7 @@ import {
XtreamApiService,
XtreamCredentials,
} from '../../services/xtream-api.service';
import { createLogger } from '../../../shared/utils/logger';
/**
* EPG state for managing Electronic Program Guide data
@@ -34,6 +35,7 @@ const initialEpgState: EpgState = {
* - Loading channel EPG for preview
*/
export function withEpg() {
const logger = createLogger('withEpg');
return signalStoreFeature(
withState<EpgState>(initialEpgState),
@@ -94,7 +96,7 @@ export function withEpg() {
return epgItems;
} catch (error) {
console.error('Error loading EPG:', error);
logger.error('Error loading EPG', error);
patchState(store, {
epgItems: [],
isLoadingEpg: false,
@@ -119,7 +121,7 @@ export function withEpg() {
1
);
} catch (error) {
console.error('Error loading channel EPG:', error);
logger.error('Error loading channel EPG', error);
return [];
}
},
@@ -17,6 +17,7 @@ import {
XtreamCredentials,
} from '../../services/xtream-api.service';
import { PortalStatusType } from '../../xtream-state';
import { createLogger } from '../../../shared/utils/logger';
/**
* Portal state for managing playlist and portal status
@@ -44,6 +45,7 @@ const initialPortalState: PortalState = {
* - Checking portal status (active, inactive, expired, unavailable)
*/
export function withPortal() {
const logger = createLogger('withPortal');
return signalStoreFeature(
withState<PortalState>(initialPortalState),
@@ -98,7 +100,7 @@ export function withPortal() {
}
}
} catch (error) {
console.error('Error fetching playlist:', error);
logger.error('Error fetching playlist', error);
}
},
@@ -140,7 +142,7 @@ export function withPortal() {
patchState(store, { portalStatus: 'inactive' });
}
} catch (error) {
console.error('Error checking portal status:', error);
logger.error('Error checking portal status', error);
patchState(store, { portalStatus: 'unavailable' });
}
},
@@ -10,6 +10,7 @@ import {
XTREAM_DATA_SOURCE,
XtreamContentItem,
} from '../../data-sources/xtream-data-source.interface';
import { createLogger } from '../../../shared/utils/logger';
/**
* Search filters configuration
@@ -58,6 +59,7 @@ const initialSearchState: SearchState = {
* - Global search results from external sources
*/
export function withSearch() {
const logger = createLogger('withSearch');
return signalStoreFeature(
withState<SearchState>(initialSearchState),
@@ -99,7 +101,7 @@ export function withSearch() {
return results;
} catch (error) {
console.error('Error searching content:', error);
logger.error('Error searching content', error);
patchState(store, {
searchResults: [],
isSearching: false,
@@ -28,6 +28,7 @@ import {
withPlayer,
withPlaybackPositions,
} from './features';
import { createLogger } from '../../shared/utils/logger';
/**
* XtreamStore - Facade composing all feature stores.
@@ -80,6 +81,7 @@ export const XtreamStore = signalStore(
withMethods((store) => {
const xtreamApiService = inject(XtreamApiService);
const ngrxStore = inject(Store);
const logger = createLogger('XtreamStore');
const searchContent = (store as any)
.searchContent as (term: string, types: string[], excludeHidden?: boolean) => Promise<unknown>;
@@ -143,7 +145,7 @@ export const XtreamStore = signalStore(
stream_id: params.vodId,
});
}).catch((error: unknown) => {
console.error('Error fetching VOD details:', error);
logger.error('Error fetching VOD details', error);
store.setDetailsError(
error instanceof Error ? error.message : 'Unknown error'
);
@@ -175,7 +177,7 @@ export const XtreamStore = signalStore(
series_id: params.serialId,
});
}).catch((error: unknown) => {
console.error('Error fetching series details:', error);
logger.error('Error fetching series details', error);
store.setDetailsError(
error instanceof Error ? error.message : 'Unknown error'
);
@@ -192,11 +194,11 @@ export const XtreamStore = signalStore(
},
addToFavorites(item: unknown): void {
console.log('Legacy addToFavorites called', item);
logger.debug('Legacy addToFavorites called', item);
},
removeFromFavorites(favoriteId: string): void {
console.log('Legacy removeFromFavorites called', favoriteId);
logger.debug('Legacy removeFromFavorites called', favoriteId);
},
// Alias methods for backward compatibility
@@ -10,6 +10,7 @@ import { DownloadsService } from '../../services/downloads.service';
import { SettingsStore } from '../../services/settings-store.service';
import { XtreamStore } from '../stores/xtream.store';
import { SafePipe } from '@iptvnator/pipes';
import { createLogger } from '../../shared/utils/logger';
/**
* Route-based VOD details container for Xtream.
@@ -39,6 +40,7 @@ export class VodDetailsRouteComponent implements OnInit, OnDestroy {
private route = inject(ActivatedRoute);
private readonly xtreamStore = inject(XtreamStore);
private readonly downloadsService = inject(DownloadsService);
private readonly logger = createLogger('VodDetailsRoute');
readonly theme = this.settingsStore.theme;
readonly isElectron = this.downloadsService.isAvailable;
@@ -51,9 +53,10 @@ export class VodDetailsRouteComponent implements OnInit, OnDestroy {
readonly hasPlaybackPosition = computed(() => {
const vodId = this.route.snapshot.params.vodId;
const inProgress = this.xtreamStore.isInProgress(Number(vodId), 'vod');
console.log(
`[VodDetails] hasPlaybackPosition check: vodId=${vodId}, inProgress=${inProgress}`
);
this.logger.debug('hasPlaybackPosition check', {
vodId,
inProgress,
});
return inProgress;
});
@@ -106,7 +109,7 @@ export class VodDetailsRouteComponent implements OnInit, OnDestroy {
vodItem.movie_data?.stream_id || (vodItem as any).stream_id
);
console.log(`[VodDetails] playVod: Resolved ID=${id} for item`, vodItem);
this.logger.debug('playVod resolved ID', { id, vodItem });
const contentInfo = {
playlistId: this.xtreamStore.currentPlaylist().id,
@@ -7,8 +7,10 @@ import {
} from '@ngrx/signals';
import { DatabaseService } from 'services';
import { FavoritesService } from './services/favorites.service';
import { createLogger } from '../shared/utils/logger';
export const withFavorites = function () {
const logger = createLogger('withFavorites');
return signalStoreFeature(
withState({
isFavorite: false,
@@ -30,8 +32,8 @@ export const withFavorites = function () {
playlistId
);
if (!content) {
console.error(
'Content not found for xtream ID:',
logger.error(
'Content not found for xtream ID',
xtreamId
);
return false;
@@ -8,6 +8,7 @@ import {
import { rxMethod } from '@ngrx/signals/rxjs-interop';
import { pipe, switchMap, tap } from 'rxjs';
import { DatabaseService } from 'services';
import { createLogger } from '../shared/utils/logger';
export interface RecentlyViewedItem {
id: number;
@@ -22,6 +23,7 @@ export interface RecentlyViewedItem {
}
export const withRecentItems = function () {
const logger = createLogger('withRecentItems');
return signalStoreFeature(
withState({
recentItems: [],
@@ -110,7 +112,7 @@ export const withRecentItems = function () {
recentItems: items || [],
});
} catch (error) {
console.error('Error loading global recent items:', error);
logger.error('Error loading global recent items', error);
patchState(store, { recentItems: [] });
}
},
@@ -119,10 +121,7 @@ export const withRecentItems = function () {
await dbService.clearGlobalRecentlyViewed();
patchState(store, { recentItems: [] });
} catch (error) {
console.error(
'Error clearing global recently viewed:',
error
);
logger.error('Error clearing global recently viewed', error);
}
},
}))