mirror of
https://github.com/4gray/iptvnator.git
synced 2026-10-08 09:01:03 -08:00
feat(xtream): refactor layout structure and add new shell component for improved navigation
This commit is contained in:
1 parent
483f0525f3
commit
e4569556a1
6 files changed
+123
-129
No files matched your search
@@ -1,46 +1,23 @@
|
||||
@if (xtreamStore.isImporting()) {
|
||||
<app-loading-overlay
|
||||
[current]="xtreamStore.getImportCount()"
|
||||
[total]="xtreamStore.itemsToImport()"
|
||||
/>
|
||||
}
|
||||
|
||||
<div class="xtream-container">
|
||||
<div class="sidebar navigation-sidebar">
|
||||
<app-navigation />
|
||||
</div>
|
||||
|
||||
@if (
|
||||
xtreamStore.selectedContentType() === 'vod' ||
|
||||
xtreamStore.selectedContentType() === 'series'
|
||||
) {
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<h2>Categories</h2>
|
||||
</div>
|
||||
<app-category-view (categoryClicked)="categoryClicked($event)" />
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="main-content">
|
||||
@if (
|
||||
xtreamStore.selectedContentType() === 'vod' ||
|
||||
xtreamStore.selectedContentType() === 'series'
|
||||
) {
|
||||
<div class="content-header">
|
||||
<h2>
|
||||
@if (xtreamStore.selectedItem()) {
|
||||
<button mat-icon-button (click)="historyBack()">
|
||||
<mat-icon>chevron_left</mat-icon>
|
||||
</button>
|
||||
}
|
||||
{{ getContentLabel() }}
|
||||
</h2>
|
||||
</div>
|
||||
}
|
||||
<div class="scrollable-content">
|
||||
<router-outlet />
|
||||
</div>
|
||||
<app-mpv-player-bar />
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<h2>Categories</h2>
|
||||
</div>
|
||||
<app-category-view (categoryClicked)="categoryClicked($event)" />
|
||||
</div>
|
||||
|
||||
<div class="main-content">
|
||||
<div class="content-header">
|
||||
<h2>
|
||||
@if (xtreamStore.selectedItem()) {
|
||||
<button mat-icon-button (click)="historyBack()">
|
||||
<mat-icon>chevron_left</mat-icon>
|
||||
</button>
|
||||
}
|
||||
{{ getContentLabel() }}
|
||||
</h2>
|
||||
</div>
|
||||
<div class="scrollable-content">
|
||||
<router-outlet />
|
||||
</div>
|
||||
<app-mpv-player-bar />
|
||||
</div>
|
||||
@@ -1,37 +1,9 @@
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: row; // Changed from column to row
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.xtream-container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
min-height: 0; // Important for proper flex behavior
|
||||
}
|
||||
|
||||
.sidebar {
|
||||
width: 300px;
|
||||
border-right: 1px solid #333;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.sidebar-header {
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navigation-sidebar {
|
||||
width: 200px;
|
||||
width: 100%; // Added to ensure full width
|
||||
}
|
||||
|
||||
.main-content {
|
||||
@@ -39,23 +11,23 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0; // Important for proper flex behavior
|
||||
}
|
||||
|
||||
.content-header {
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
||||
.content-header {
|
||||
padding: 16px;
|
||||
border-bottom: 1px solid rgba(0, 0, 0, 0.12);
|
||||
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
h2 {
|
||||
margin: 0;
|
||||
font-size: 1.2rem;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.scrollable-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
}
|
||||
.scrollable-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, effect, inject } from '@angular/core';
|
||||
import { Component, inject } from '@angular/core';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { CategoryViewComponent } from './category-view/category-view.component';
|
||||
|
||||
@@ -8,27 +8,21 @@ import { ActivatedRoute, Router, RouterOutlet } from '@angular/router';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import { XtreamCategory } from '../../../shared/xtream-category.interface';
|
||||
import { MpvPlayerBarComponent } from '../shared/components/mpv-player-bar/mpv-player-bar.component';
|
||||
import * as PlaylistActions from '../state/actions';
|
||||
import { LoadingOverlayComponent } from './loading-overlay/loading-overlay.component';
|
||||
import { NavigationComponent } from './navigation/navigation.component';
|
||||
import { XtreamStore } from './xtream.store';
|
||||
|
||||
@Component({
|
||||
selector: 'app-xtream-main-container',
|
||||
templateUrl: './xtream-main-container.component.html',
|
||||
styleUrls: ['./xtream-main-container.component.scss'],
|
||||
styleUrls: ['./xtream-main-container.component.scss', './sidebar.scss'],
|
||||
standalone: true,
|
||||
imports: [
|
||||
CategoryViewComponent,
|
||||
TranslateModule,
|
||||
RouterOutlet,
|
||||
NavigationComponent,
|
||||
LoadingOverlayComponent,
|
||||
MpvPlayerBarComponent,
|
||||
MatIcon,
|
||||
MatIconButton,
|
||||
],
|
||||
providers: [XtreamStore],
|
||||
})
|
||||
export class XtreamMainContainerComponent {
|
||||
readonly xtreamStore = inject(XtreamStore);
|
||||
@@ -38,33 +32,10 @@ export class XtreamMainContainerComponent {
|
||||
constructor(
|
||||
private router: Router,
|
||||
private route: ActivatedRoute
|
||||
) {
|
||||
effect(
|
||||
() => {
|
||||
if (this.xtreamStore.currentPlaylist() !== null) {
|
||||
console.log(
|
||||
'Initializing content...',
|
||||
this.xtreamStore.currentPlaylist()
|
||||
);
|
||||
this.xtreamStore.initializeContent();
|
||||
}
|
||||
},
|
||||
{ allowSignalWrites: true }
|
||||
);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.store.dispatch(
|
||||
PlaylistActions.setActivePlaylist({
|
||||
playlistId: this.route.snapshot.params.id,
|
||||
})
|
||||
);
|
||||
//this.xtreamStore.fetchXtreamPlaylist();
|
||||
}
|
||||
) {}
|
||||
|
||||
categoryClicked(category: XtreamCategory) {
|
||||
const categoryId = (category as any).category_id ?? category.id;
|
||||
console.log('Category clicked:', category);
|
||||
this.xtreamStore.setSelectedCategory(Number(categoryId));
|
||||
|
||||
this.router.navigate([categoryId], {
|
||||
@@ -79,8 +50,6 @@ export class XtreamMainContainerComponent {
|
||||
) {
|
||||
return 'Select a category';
|
||||
} else {
|
||||
// TODO: Fix this
|
||||
//console.log(this.xtreamStore.getSelectedCategory());
|
||||
const selectedCategory = this.xtreamStore.getSelectedCategory();
|
||||
return selectedCategory
|
||||
? `Content for ${(selectedCategory as any).name}`
|
||||
@@ -89,10 +58,8 @@ export class XtreamMainContainerComponent {
|
||||
}
|
||||
|
||||
historyBack() {
|
||||
this.router.navigate([
|
||||
'./xtreams',
|
||||
this.xtreamStore.currentPlaylist().id,
|
||||
this.xtreamStore.selectedCategoryId(),
|
||||
]);
|
||||
this.router.navigate(['.', this.xtreamStore.selectedCategoryId()], {
|
||||
relativeTo: this.route,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
@if (isImporting()) {
|
||||
<app-loading-overlay
|
||||
[current]="getImportCount()"
|
||||
[total]="itemsToImport()"
|
||||
/>
|
||||
}
|
||||
|
||||
<div class="xtream-container">
|
||||
<app-navigation class="navigation-sidebar" />
|
||||
<router-outlet />
|
||||
</div>
|
||||
@@ -0,0 +1,18 @@
|
||||
:host {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.xtream-container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
min-height: 0; // Important for proper flex behavior
|
||||
}
|
||||
|
||||
.navigation-sidebar {
|
||||
width: 200px;
|
||||
border-right: 1px solid #333;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
import { Component, effect, inject } from '@angular/core';
|
||||
import { ActivatedRoute, RouterOutlet } from '@angular/router';
|
||||
import { Store } from '@ngrx/store';
|
||||
import { TranslateModule } from '@ngx-translate/core';
|
||||
import * as PlaylistActions from '../../state/actions';
|
||||
import { LoadingOverlayComponent } from '../loading-overlay/loading-overlay.component';
|
||||
import { NavigationComponent } from '../navigation/navigation.component';
|
||||
import { XtreamStore } from '../xtream.store';
|
||||
|
||||
@Component({
|
||||
templateUrl: './xtream-shell.component.html',
|
||||
styleUrls: ['./xtream-shell.component.scss'],
|
||||
standalone: true,
|
||||
imports: [
|
||||
LoadingOverlayComponent,
|
||||
NavigationComponent,
|
||||
RouterOutlet,
|
||||
TranslateModule,
|
||||
],
|
||||
providers: [XtreamStore],
|
||||
})
|
||||
export class XtreamShellComponent {
|
||||
private readonly route = inject(ActivatedRoute);
|
||||
private readonly store = inject(Store);
|
||||
private readonly xtreamStore = inject(XtreamStore);
|
||||
|
||||
readonly getImportCount = this.xtreamStore.getImportCount;
|
||||
readonly isImporting = this.xtreamStore.isImporting;
|
||||
readonly itemsToImport = this.xtreamStore.itemsToImport;
|
||||
|
||||
constructor() {
|
||||
effect(
|
||||
() => {
|
||||
if (this.xtreamStore.currentPlaylist() !== null) {
|
||||
this.xtreamStore.initializeContent();
|
||||
}
|
||||
},
|
||||
{ allowSignalWrites: true }
|
||||
);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.store.dispatch(
|
||||
PlaylistActions.setActivePlaylist({
|
||||
playlistId: this.route.snapshot.params.id,
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user