diff --git a/libs/ui/epg/src/lib/epg-list/epg-item-description/epg-item-description.component.scss b/libs/ui/epg/src/lib/epg-list/epg-item-description/epg-item-description.component.scss
index 2cf554704..1fbdcf550 100644
--- a/libs/ui/epg/src/lib/epg-list/epg-item-description/epg-item-description.component.scss
+++ b/libs/ui/epg/src/lib/epg-list/epg-item-description/epg-item-description.component.scss
@@ -13,7 +13,7 @@ $border-subtle: rgba(255, 255, 255, 0.08);
background: linear-gradient(180deg, $bg-surface 0%, $bg-deep 100%);
color: $text-primary;
min-width: 380px;
- max-width: 480px;
+ max-width: 800px;
border-radius: 16px;
overflow: hidden;
position: relative;
diff --git a/libs/ui/epg/src/lib/epg-list/epg-list-item/epg-list-item.component.ts b/libs/ui/epg/src/lib/epg-list/epg-list-item/epg-list-item.component.ts
index 2e53fa099..705f4e35b 100644
--- a/libs/ui/epg/src/lib/epg-list/epg-list-item/epg-list-item.component.ts
+++ b/libs/ui/epg/src/lib/epg-list/epg-list-item/epg-list-item.component.ts
@@ -31,6 +31,7 @@ export class EpgListItemComponent {
*/
showDescription(program: EpgProgram): void {
this.dialog.open(EpgItemDescriptionComponent, {
+ width: '800px',
data: program,
});
}
diff --git a/libs/ui/epg/src/lib/epg-list/epg-list.component.html b/libs/ui/epg/src/lib/epg-list/epg-list.component.html
index b72043b33..06612168c 100644
--- a/libs/ui/epg/src/lib/epg-list/epg-list.component.html
+++ b/libs/ui/epg/src/lib/epg-list/epg-list.component.html
@@ -3,34 +3,6 @@
diff --git a/libs/ui/epg/src/lib/epg-list/epg-list.component.scss b/libs/ui/epg/src/lib/epg-list/epg-list.component.scss
index 2277c2367..4ba1c56e9 100644
--- a/libs/ui/epg/src/lib/epg-list/epg-list.component.scss
+++ b/libs/ui/epg/src/lib/epg-list/epg-list.component.scss
@@ -8,91 +8,6 @@
background: transparent;
}
-.header-divider {
- height: 1px;
- background: rgba(255, 255, 255, 0.08);
-}
-
-#channel-header {
- display: flex;
- flex-direction: column;
- background:
- linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0)),
- rgba(127, 127, 127, 0.05);
- border-bottom: 1px solid rgba(255, 255, 255, 0.06);
-
- .channel-info {
- display: flex;
- align-items: center;
- padding: 14px 16px 12px;
- gap: 14px;
- }
-}
-
-.channel-icon-shell {
- position: relative;
- width: 52px;
- height: 52px;
- flex-shrink: 0;
- border-radius: 12px;
- overflow: hidden;
- display: grid;
- place-items: center;
- background:
- linear-gradient(180deg, rgba(255, 255, 255, 0.12), rgba(255, 255, 255, 0)),
- rgba(127, 127, 127, 0.12);
- box-shadow:
- inset 0 0 0 1px rgba(255, 255, 255, 0.08),
- inset 0 1px 1px rgba(0, 0, 0, 0.15);
-
- img {
- position: relative;
- z-index: 1;
- width: 100%;
- height: 100%;
- object-fit: contain;
- padding: 6px;
- box-sizing: border-box;
- }
-}
-
-.channel-icon-fallback {
- position: absolute;
- inset: 0;
- margin: auto;
- width: 20px;
- height: 20px;
- font-size: 20px;
- opacity: 0.46;
-}
-
-.channel-details {
- flex: 1;
- min-width: 0;
- display: flex;
- flex-direction: column;
- gap: 3px;
-}
-
-.channel-name {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- font-size: 1rem;
- line-height: 1.2;
- font-weight: 600;
- letter-spacing: 0.01em;
-}
-
-.program-name {
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
- font-size: 0.84rem;
- line-height: 1.2;
- opacity: 0.82;
-}
-
#date-navigator {
display: flex;
justify-content: space-between;
@@ -206,6 +121,16 @@
-webkit-box-orient: vertical;
}
+.epg-item__description {
+ font-size: 0.82rem;
+ line-height: 1.4;
+ opacity: 0.74;
+ display: -webkit-box;
+ overflow: hidden;
+ -webkit-line-clamp: 2;
+ -webkit-box-orient: vertical;
+}
+
.program-progress {
padding-top: 2px;
}
diff --git a/libs/ui/epg/src/lib/epg-list/epg-list.component.ts b/libs/ui/epg/src/lib/epg-list/epg-list.component.ts
index 714ef7105..20a431785 100644
--- a/libs/ui/epg/src/lib/epg-list/epg-list.component.ts
+++ b/libs/ui/epg/src/lib/epg-list/epg-list.component.ts
@@ -3,8 +3,8 @@ import {
ChangeDetectionStrategy,
ChangeDetectorRef,
Component,
- ElementRef,
effect,
+ ElementRef,
inject,
Injector,
OnInit,
@@ -14,14 +14,11 @@ import { FormsModule } from '@angular/forms';
import { MatIconButton } from '@angular/material/button';
import { MatIcon } from '@angular/material/icon';
import { MatTooltip } from '@angular/material/tooltip';
+import { EpgService } from '@iptvnator/epg/data-access';
import { MomentDatePipe } from '@iptvnator/pipes';
import { Store } from '@ngrx/store';
import { TranslatePipe } from '@ngx-translate/core';
-import { EpgService } from '@iptvnator/epg/data-access';
-import {
- selectActive,
- EpgActions,
-} from 'm3u-state';
+import { EpgActions, selectActive } from 'm3u-state';
import moment from 'moment';
import { BehaviorSubject, combineLatest, map } from 'rxjs';
import { EpgChannel, EpgProgram } from 'shared-interfaces';
@@ -73,8 +70,6 @@ export class EpgListComponent implements OnInit {
/** EPG selected program */
playingNow: EpgProgram | undefined;
- channelIconFailed = false;
-
/** Selected date */
selectedDate!: string;
@@ -96,7 +91,6 @@ export class EpgListComponent implements OnInit {
url: active?.url ? [active.url] : [],
icon: icons,
};
- this.channelIconFailed = false;
return (
active?.tvg?.rec || active?.timeshift || active?.catchup?.days
);
@@ -125,45 +119,6 @@ export class EpgListComponent implements OnInit {
)
);
- /**
- * Helper function to get channel display name
- */
- getChannelDisplayName(channel: EpgChannel): string {
- if (
- !channel ||
- !channel.displayName ||
- channel.displayName.length === 0
- ) {
- return '';
- }
- // Return first available display name
- return channel.displayName[0]?.value || '';
- }
-
- /**
- * Helper function to get channel icon
- */
- getChannelIcon(channel: EpgChannel): string {
- if (!channel || !channel.icon || channel.icon.length === 0) {
- return '';
- }
- // Return first available icon src
- return channel.icon[0]?.src || '';
- }
-
- showChannelIconFallback(channel: EpgChannel): boolean {
- return !this.getChannelIcon(channel) || this.channelIconFailed;
- }
-
- onChannelIconError(event: Event): void {
- this.channelIconFailed = true;
- (event.target as HTMLImageElement | null)?.style.setProperty(
- 'display',
- 'none'
- );
- this.cdr.markForCheck();
- }
-
/**
* Subscribe for values from the store on component init
*/
diff --git a/libs/ui/epg/src/lib/multi-epg/multi-epg-container.component.ts b/libs/ui/epg/src/lib/multi-epg/multi-epg-container.component.ts
index 71a91f423..283d03ad4 100644
--- a/libs/ui/epg/src/lib/multi-epg/multi-epg-container.component.ts
+++ b/libs/ui/epg/src/lib/multi-epg/multi-epg-container.component.ts
@@ -54,12 +54,12 @@ interface ProgramSearchResult extends EpgProgram {
@Component({
imports: [
- MatButtonModule,
- MatIcon,
- MatTooltip,
- MomentDatePipe,
- TranslatePipe
-],
+ MatButtonModule,
+ MatIcon,
+ MatTooltip,
+ MomentDatePipe,
+ TranslatePipe,
+ ],
selector: 'app-multi-epg-container',
templateUrl: './multi-epg-container.component.html',
styleUrls: ['./multi-epg-container.component.scss'],
@@ -117,7 +117,7 @@ export class MultiEpgContainerComponent
return allChannels;
}
- return allChannels.filter(channel => {
+ return allChannels.filter((channel) => {
const name = this.getChannelName(channel).toLowerCase();
return name.includes(filter);
});
@@ -151,7 +151,7 @@ export class MultiEpgContainerComponent
this.interval = setInterval(() => {
// Force recomputation by updating hourWidth to same value
// This triggers the computed signal to recalculate
- this.hourWidth.update(v => v);
+ this.hourWidth.update((v) => v);
}, 60000);
}
@@ -317,7 +317,10 @@ export class MultiEpgContainerComponent
if (typeof channel.displayName === 'string') {
return channel.displayName;
}
- if (Array.isArray(channel.displayName) && channel.displayName.length > 0) {
+ if (
+ Array.isArray(channel.displayName) &&
+ channel.displayName.length > 0
+ ) {
return channel.displayName[0].value;
}
return '';
@@ -338,16 +341,16 @@ export class MultiEpgContainerComponent
zoomIn(): void {
if (this.hourWidth() >= 800) return;
- this.hourWidth.update(v => v + 50);
+ this.hourWidth.update((v) => v + 50);
}
zoomOut(): void {
if (this.hourWidth() <= 50) return;
- this.hourWidth.update(v => v - 50);
+ this.hourWidth.update((v) => v - 50);
}
toggleSearch(): void {
- this.isSearchExpanded.update(v => !v);
+ this.isSearchExpanded.update((v) => !v);
if (!this.isSearchExpanded()) {
this.channelFilter.set('');
}
@@ -373,13 +376,14 @@ export class MultiEpgContainerComponent
showDescription(program: EpgProgram): void {
this.dialog.open(EpgItemDescriptionComponent, {
+ width: '600px',
data: program,
});
}
// Program search methods
toggleProgramSearch(): void {
- this.isProgramSearchOpen.update(v => !v);
+ this.isProgramSearchOpen.update((v) => !v);
if (!this.isProgramSearchOpen()) {
this.programSearchQuery.set('');
this.programSearchResults.set([]);
@@ -406,7 +410,10 @@ export class MultiEpgContainerComponent
this.searchDebounceTimer = setTimeout(async () => {
this.isSearchingPrograms.set(true);
try {
- const results = await window.electron.searchEpgPrograms(query, 20);
+ const results = await window.electron.searchEpgPrograms(
+ query,
+ 20
+ );
this.programSearchResults.set(
(results as ProgramSearchResult[]) || []
);
@@ -429,11 +436,12 @@ export class MultiEpgContainerComponent
const channelId = program.channel_id || program.channel;
// Find channel name
- const channel = this.channels().find(ch => ch.id === channelId);
+ const channel = this.channels().find((ch) => ch.id === channelId);
const channelName = channel ? this.getChannelName(channel) : null;
// Open the program details dialog with channel name
this.dialog.open(EpgItemDescriptionComponent, {
+ width: '800px',
data: { ...program, channelName },
});
}