mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-16 22:26:16 -08:00
- Consolidated SCSS styles for the live stream layout, reducing redundancy and improving maintainability. - Introduced a new portal layout mixin for better structure. - Enhanced sidebar and content container styles for improved user experience. - Updated TypeScript component to utilize new styles and improve readability. - Refactored channel list and recently viewed components for consistency in design. - Optimized playlist service and store interactions for better performance. - Added new translations for enhanced user interface clarity. - Improved database schema with additional indexing for EPG programs.
144 lines
5.3 KiB
HTML
144 lines
5.3 KiB
HTML
@let isEmbeddedPlayer =
|
|
player() === 'videojs' || player() === 'html5' || player() === 'artplayer';
|
|
|
|
@if (!isWorkspaceLayout || stalkerStore.selectedCategoryId()) {
|
|
<div
|
|
class="sidebar"
|
|
appResizable
|
|
[minWidth]="250"
|
|
[maxWidth]="600"
|
|
[defaultWidth]="400"
|
|
storageKey="sidebar-width"
|
|
>
|
|
@if (stalkerStore.selectedCategoryId() || !isWorkspaceLayout) {
|
|
<div class="sidebar-header">
|
|
@if (stalkerStore.selectedCategoryId()) {
|
|
<button mat-icon-button (click)="backToCategories()">
|
|
<mat-icon>chevron_left</mat-icon>
|
|
</button>
|
|
<h2>{{ selectedCategoryTitle() }}</h2>
|
|
} @else {
|
|
<app-playlist-switcher
|
|
class="switcher"
|
|
[currentTitle]="currentPlaylist()?.title || 'Portal'"
|
|
[subtitle]="'Stalker Portal'"
|
|
/>
|
|
}
|
|
</div>
|
|
}
|
|
|
|
@if (stalkerStore.selectedCategoryId()) {
|
|
<!-- <div class="search-panel">
|
|
<mat-form-field class="search-bar" subscriptSizing="dynamic">
|
|
<mat-icon matPrefix>search</mat-icon>
|
|
<input
|
|
matInput
|
|
[placeholder]="'PORTALS.SIDEBAR.SEARCH' | translate"
|
|
[ngModel]="searchString()"
|
|
(ngModelChange)="searchString.set($event)"
|
|
/>
|
|
@if (searchString()) {
|
|
<button matSuffix mat-icon-button (click)="searchString.set('')">
|
|
<mat-icon>close</mat-icon>
|
|
</button>
|
|
}
|
|
</mat-form-field>
|
|
</div> -->
|
|
<div #scrollContainer class="channels-list">
|
|
@for (item of itvChannels(); track item.id ?? $index) {
|
|
<app-channel-list-item
|
|
[name]="item.o_name || item.name"
|
|
[logo]="item.logo"
|
|
[selected]="isSelectedChannel(item)"
|
|
[epgProgram]="
|
|
epgPreviewPrograms.get(
|
|
normalizeStalkerEntityId(item.id)
|
|
) ?? null
|
|
"
|
|
[progressPercentage]="
|
|
currentProgramsProgress.get(
|
|
normalizeStalkerEntityId(item.id)
|
|
) ?? 0
|
|
"
|
|
[showFavoriteButton]="true"
|
|
[showProgramInfoButton]="false"
|
|
[isFavorite]="
|
|
favorites.get(normalizeStalkerEntityId(item.id)) ??
|
|
false
|
|
"
|
|
(clicked)="playChannel(item)"
|
|
(favoriteToggled)="toggleFavorite(item)"
|
|
/>
|
|
}
|
|
|
|
@if (isLoadingMore()) {
|
|
<div class="loading-indicator">
|
|
<mat-spinner diameter="24" />
|
|
</div>
|
|
}
|
|
</div>
|
|
} @else {
|
|
@if (isCategoryLoading()) {
|
|
<ngx-skeleton-loader
|
|
count="20"
|
|
[theme]="{
|
|
width: '95%',
|
|
height: '48px',
|
|
borderRadius: '40px',
|
|
}"
|
|
/>
|
|
} @else if (isCategoryFailed()) {
|
|
<app-playlist-error-view
|
|
[title]="
|
|
'PORTALS.ERROR_VIEW.UNKNOWN_ERROR.TITLE' | translate
|
|
"
|
|
[description]="
|
|
'PORTALS.ERROR_VIEW.UNKNOWN_ERROR.DESCRIPTION'
|
|
| translate
|
|
"
|
|
/>
|
|
} @else {
|
|
<app-category-view
|
|
[items]="categories()"
|
|
[selectedCategoryId]="
|
|
$any(stalkerStore.selectedCategoryId())
|
|
"
|
|
(categoryClicked)="selectCategory($event)"
|
|
/>
|
|
}
|
|
}
|
|
</div>
|
|
}
|
|
|
|
<div class="content-container">
|
|
@if (streamUrl && isEmbeddedPlayer) {
|
|
<div class="video-player">
|
|
<app-web-player-view [streamUrl]="streamUrl" />
|
|
</div>
|
|
}
|
|
@if (stalkerStore.selectedItem()) {
|
|
<div class="epg">
|
|
<div class="epg-content">
|
|
<app-epg-view [epgItems]="epgItems()" />
|
|
@if (isLoadingEpg()) {
|
|
<div class="loading-indicator">
|
|
<mat-spinner diameter="24" />
|
|
</div>
|
|
}
|
|
@if (hasMoreEpg() && !isLoadingEpg()) {
|
|
<div class="load-more-epg">
|
|
<button mat-button (click)="loadMoreEpg()">
|
|
{{ 'CHANNELS.LOAD_MORE' | translate }}
|
|
</button>
|
|
</div>
|
|
}
|
|
</div>
|
|
</div>
|
|
} @else {
|
|
<app-portal-empty-state
|
|
icon="live_tv"
|
|
[message]="'CHANNELS.SELECT_CHANNEL_PLAYBACK' | translate"
|
|
/>
|
|
}
|
|
</div>
|