import { Component, inject, signal, computed, OnInit } from '@angular/core'; import { CommonModule, DatePipe } from '@angular/common'; import { Router, RouterLink } from '@angular/router'; import { NzTableModule } from 'ng-zorro-antd/table'; import { NzButtonModule } from 'ng-zorro-antd/button'; import { NzIconModule } from 'ng-zorro-antd/icon'; import { NzTagModule } from 'ng-zorro-antd/tag'; import { NzBadgeModule } from 'ng-zorro-antd/badge'; import { NzEmptyModule } from 'ng-zorro-antd/empty'; import { NzCardModule } from 'ng-zorro-antd/card'; import { NzToolTipModule } from 'ng-zorro-antd/tooltip'; import { NzTabsModule } from 'ng-zorro-antd/tabs'; import { NzAlertModule } from 'ng-zorro-antd/alert'; import { ApiService } from '../../../core/services/api.service'; import { AuthService } from '../../../core/services/auth.service'; import { NotificationService } from '../../../core/services/notification.service'; import { SettingsService } from '../../../core/services/settings.service'; import { UserCacheService, ResolvedUser } from '../../../core/services/user-cache.service'; import { ChannelWithSubscription } from '../../../core/models'; import { RelativeTimePipe } from '../../../shared/pipes/relative-time.pipe'; import { ChannelSubscribersComponent } from '../channel-subscribers/channel-subscribers.component'; type ChannelTab = 'all' | 'owned' | 'foreign'; @Component({ selector: 'app-channel-list', standalone: true, imports: [ CommonModule, DatePipe, RouterLink, NzTableModule, NzButtonModule, NzIconModule, NzTagModule, NzBadgeModule, NzEmptyModule, NzCardModule, NzToolTipModule, NzTabsModule, NzAlertModule, RelativeTimePipe, ChannelSubscribersComponent, ], templateUrl: './channel-list.component.html', styleUrl: './channel-list.component.scss' }) export class ChannelListComponent implements OnInit { private apiService = inject(ApiService); private authService = inject(AuthService); private notification = inject(NotificationService); private settingsService = inject(SettingsService); private userCacheService = inject(UserCacheService); private router = inject(Router); allChannels = signal([]); ownerNames = signal>(new Map()); loading = signal(false); expertMode = this.settingsService.expertMode; activeTab = signal('all'); channels = computed(() => { const userId = this.authService.getUserId(); const all = this.allChannels(); const tab = this.activeTab(); switch (tab) { case 'owned': return all.filter(c => c.owner_user_id === userId); case 'foreign': return all.filter(c => c.owner_user_id !== userId); default: return all; } }); ngOnInit(): void { this.loadChannels(); } loadChannels(): void { const userId = this.authService.getUserId(); if (!userId) return; this.loading.set(true); this.apiService.getChannels(userId, 'all_any').subscribe({ next: (response) => { this.allChannels.set(response.channels); this.loading.set(false); this.resolveOwnerNames(response.channels); }, error: () => { this.loading.set(false); } }); } onTabChange(index: number): void { const tabs: ChannelTab[] = ['all', 'owned', 'foreign']; this.activeTab.set(tabs[index]); } getTabDescription(): string | null { switch (this.activeTab()) { case 'owned': return 'Channels that you own and can configure.'; case 'foreign': return 'Channels owned by other users that you are subscribed to.'; default: return null; } } private resolveOwnerNames(channels: ChannelWithSubscription[]): void { const uniqueOwnerIds = [...new Set(channels.map(c => c.owner_user_id))]; for (const ownerId of uniqueOwnerIds) { this.userCacheService.resolveUser(ownerId).subscribe(resolved => { this.ownerNames.update(map => new Map(map).set(ownerId, resolved)); }); } } getOwnerDisplayName(ownerId: string): string { const resolved = this.ownerNames().get(ownerId); return resolved?.displayName || ownerId; } isOwned(channel: ChannelWithSubscription): boolean { return channel.owner_user_id === this.authService.getUserId(); } viewChannel(channel: ChannelWithSubscription): void { this.router.navigate(['/channels', channel.channel_id]); } getSubscriptionStatus(channel: ChannelWithSubscription): { label: string; color: string } { const userId = this.authService.getUserId(); if (channel.owner_user_id === userId) { if (channel.subscription) { return { label: 'Owned & Subscribed', color: 'green' }; } return { label: 'Owned', color: 'blue' }; } if (channel.subscription) { if (channel.subscription.confirmed) { return { label: 'Subscribed', color: 'green' }; } return { label: 'Pending', color: 'orange' }; } return { label: 'Not Subscribed', color: 'default' }; } toggleSelfSubscription(channel: ChannelWithSubscription, event: Event): void { event.stopPropagation(); const userId = this.authService.getUserId(); if (!userId) return; if (channel.subscription) { // Unsubscribe this.apiService.deleteSubscription(userId, channel.subscription.subscription_id).subscribe({ next: () => { this.notification.success('Unsubscribed from channel'); this.loadChannels(); } }); } else { // Subscribe this.apiService.createSubscription(userId, { channel_id: channel.channel_id }).subscribe({ next: () => { this.notification.success('Subscribed to channel'); this.loadChannels(); } }); } } }