diff --git a/apps/web/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.html b/apps/web/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.html index b0c7b31b0..dc1290fb4 100644 --- a/apps/web/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.html +++ b/apps/web/src/app/xtream-tauri/live-stream-layout/live-stream-layout.component.html @@ -14,7 +14,37 @@ -

{{ selectedCategoryInfo()?.name }} ({{ selectedCategoryInfo()?.count }})

+

+ {{ selectedCategoryInfo()?.name }} ({{ selectedCategoryInfo()?.count }}) +

+ + + + + + } @else { @if (selectedCategoryId()) { - + } @else { ('server'); + readonly liveChannelSortLabel = computed(() => { + const mode = this.liveChannelSortMode(); + if (mode === 'name-asc') return 'Name A-Z'; + if (mode === 'name-desc') return 'Name Z-A'; + return 'Server Order'; + }); readonly selectedCategoryInfo = computed(() => { const categoryId = this.selectedCategoryId(); @@ -173,4 +185,8 @@ export class LiveStreamLayoutComponent implements OnInit { } }); } + + setLiveChannelSortMode(mode: LiveChannelSortMode): void { + this.liveChannelSortMode.set(mode); + } } diff --git a/apps/web/src/app/xtream-tauri/portal-channels-list/portal-channels-list.component.html b/apps/web/src/app/xtream-tauri/portal-channels-list/portal-channels-list.component.html index 2e1adf225..9534e50fd 100644 --- a/apps/web/src/app/xtream-tauri/portal-channels-list/portal-channels-list.component.html +++ b/apps/web/src/app/xtream-tauri/portal-channels-list/portal-channels-list.component.html @@ -18,7 +18,7 @@ >
(); + readonly sortMode = input('server'); readonly xtreamStore = inject(XtreamStore); private readonly favoritesService = inject(FavoritesService); private readonly epgQueueService = inject(EpgQueueService); private readonly route = inject(ActivatedRoute); readonly channels = this.xtreamStore.selectItemsFromSelectedCategory; + readonly sortedChannels = computed(() => { + const mode = this.sortMode(); + const channels = this.channels(); + if (mode === 'server') { + return channels; + } + + const collator = new Intl.Collator(undefined, { + numeric: true, + sensitivity: 'base', + }); + + return [...channels].sort((a: any, b: any) => { + const titleA = a.title ?? a.name ?? ''; + const titleB = b.title ?? b.name ?? ''; + const result = collator.compare(titleA, titleB); + return mode === 'name-asc' ? result : -result; + }); + }); favorites = new Map(); searchString = signal(''); @@ -117,7 +141,7 @@ export class PortalChannelsListComponent implements AfterViewInit, OnDestroy { vp.renderedRangeStream .pipe(debounceTime(300)) .subscribe((range) => { - const visibleChannels = this.channels().slice( + const visibleChannels = this.sortedChannels().slice( range.start, range.end );