- @if (!xtreamStore.selectedItem() && !xtreamStore.isLoadingDetails()) { + @if ( + !isWorkspaceLayout && + !xtreamStore.selectedItem() && + !xtreamStore.isLoadingDetails() + ) {

@@ -108,7 +119,11 @@ }
diff --git a/apps/web/src/app/xtream-electron/xtream-main-container.component.scss b/apps/web/src/app/xtream-electron/xtream-main-container.component.scss index 36a844d6d..810251856 100644 --- a/apps/web/src/app/xtream-electron/xtream-main-container.component.scss +++ b/apps/web/src/app/xtream-electron/xtream-main-container.component.scss @@ -14,6 +14,10 @@ align-items: center; app-region: drag; + &.sidebar-header--workspace { + justify-content: flex-end; + } + button { @include mat.form-field-density(-5); app-region: no-drag; diff --git a/apps/web/src/app/xtream-electron/xtream-main-container.component.ts b/apps/web/src/app/xtream-electron/xtream-main-container.component.ts index 156e1076c..c41644f89 100644 --- a/apps/web/src/app/xtream-electron/xtream-main-container.component.ts +++ b/apps/web/src/app/xtream-electron/xtream-main-container.component.ts @@ -58,6 +58,8 @@ export class XtreamMainContainerComponent implements OnInit { const type = this.xtreamStore.selectedContentType(); return hasCategorySelected && (type === 'vod' || type === 'series'); }); + readonly isWorkspaceLayout = + this.route.snapshot.data['layout'] === 'workspace'; readonly contentSortLabel = computed(() => { const mode = this.contentSortMode(); if (mode === 'date-asc') return 'Date Added (Oldest First)'; diff --git a/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.html b/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.html index 277eda051..adcfa1dbb 100644 --- a/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.html +++ b/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.html @@ -6,13 +6,12 @@ }
- + @if (!isWorkspaceLayout) { + + }
diff --git a/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.scss b/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.scss index bfdb442d5..d8e049852 100644 --- a/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.scss +++ b/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.scss @@ -10,8 +10,13 @@ flex: 1; overflow: hidden; min-height: 0; // Important for proper flex behavior + + > router-outlet { + + min-width: 0; + } } .navigation-sidebar { - border-right: 1px solid #333; + border-right: 1px solid var(--mat-sys-outline-variant); } diff --git a/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.ts b/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.ts index ed999261f..e46b08fc5 100644 --- a/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.ts +++ b/apps/web/src/app/xtream-electron/xtream-shell/xtream-shell.component.ts @@ -1,13 +1,18 @@ import { Component, effect, inject } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; -import { ActivatedRoute, Router, RouterOutlet } from '@angular/router'; +import { + ActivatedRoute, + NavigationEnd, + Router, + RouterOutlet, +} from '@angular/router'; import { Store } from '@ngrx/store'; import { TranslateModule } from '@ngx-translate/core'; import { PlaylistActions } from 'm3u-state'; import { LoadingOverlayComponent } from '../loading-overlay/loading-overlay.component'; import { NavigationComponent } from '../navigation/navigation.component'; -import { NavigationItem } from '../navigation/navigation.interface'; import { XtreamStore } from '../stores/xtream.store'; +import { filter } from 'rxjs'; @Component({ templateUrl: './xtream-shell.component.html', @@ -29,26 +34,11 @@ export class XtreamShellComponent { readonly isImporting = this.xtreamStore.isImporting; readonly itemsToImport = this.xtreamStore.itemsToImport; readonly portalStatus = this.xtreamStore.portalStatus; - - readonly mainNavigationItems: NavigationItem[] = [ - { - id: 'vod', - icon: 'movie', - labelKey: 'PORTALS.SIDEBAR.MOVIES', - }, - { - id: 'live', - icon: 'live_tv', - labelKey: 'PORTALS.SIDEBAR.LIVE_TV', - }, - { - id: 'series', - icon: 'tv', - labelKey: 'PORTALS.SIDEBAR.SERIES', - }, - ]; + readonly isWorkspaceLayout = + this.route.snapshot.data['layout'] === 'workspace'; private currentPlaylistId: string | null = null; + private currentSection: string | null = null; constructor() { // Subscribe to route params to handle switching between playlists @@ -77,6 +67,17 @@ export class XtreamShellComponent { await this.xtreamStore.checkPortalStatus(); }); + this.router.events + .pipe( + filter((event): event is NavigationEnd => event instanceof NavigationEnd), + takeUntilDestroyed() + ) + .subscribe(() => { + this.syncSectionFromRoute(); + }); + + this.syncSectionFromRoute(); + effect(() => { const playlist = this.xtreamStore.currentPlaylist(); const playlistId = this.xtreamStore.playlistId(); @@ -89,17 +90,30 @@ export class XtreamShellComponent { }); } - handleCategoryClick(category: 'vod' | 'live' | 'series') { - this.xtreamStore.setSelectedContentType(category); - this.router.navigate([category], { - relativeTo: this.route, - }); + private syncSectionFromRoute(): void { + const sectionFromSnapshot = + this.route.firstChild?.snapshot?.url?.[0]?.path ?? null; + const sectionFromUrl = this.getSectionFromUrl(this.router.url); + const section = sectionFromSnapshot ?? sectionFromUrl; + + if (!section || section === this.currentSection) { + return; + } + + this.currentSection = section; + + if (section === 'vod' || section === 'live' || section === 'series') { + this.xtreamStore.setSelectedContentType(section); + return; + } + + this.xtreamStore.setSelectedContentType(undefined); } - handlePageClick(page: 'search' | 'recent' | 'favorites' | 'recently-added') { - this.xtreamStore.setSelectedContentType(undefined); - this.router.navigate([page], { - relativeTo: this.route, - }); + private getSectionFromUrl(url: string): string | null { + const match = url.match( + /^\/(?:workspace\/)?xtreams\/[^\/\?]+\/([^\/\?]+)/ + ); + return match?.[1] ?? null; } -} \ No newline at end of file +}