108 lines
3.1 KiB
TypeScript
108 lines
3.1 KiB
TypeScript
import { Component, inject, input, signal, OnInit } from '@angular/core';
|
|
import { CommonModule } from '@angular/common';
|
|
import { NzSpinModule } from 'ng-zorro-antd/spin';
|
|
import { NzToolTipModule } from 'ng-zorro-antd/tooltip';
|
|
import { ApiService } from '../../../core/services/api.service';
|
|
import { AuthService } from '../../../core/services/auth.service';
|
|
import { UserCacheService, ResolvedUser } from '../../../core/services/user-cache.service';
|
|
import { Subscription } from '../../../core/models';
|
|
|
|
@Component({
|
|
selector: 'app-channel-subscribers',
|
|
standalone: true,
|
|
imports: [CommonModule, NzSpinModule, NzToolTipModule],
|
|
template: `
|
|
@if (loading()) {
|
|
<nz-spin nzSimple nzSize="small"></nz-spin>
|
|
} @else if (subscribers().length === 0) {
|
|
<span class="text-muted">None</span>
|
|
} @else {
|
|
<div class="subscribers-list">
|
|
@for (sub of subscribers(); track sub.subscription_id) {
|
|
<span
|
|
class="subscriber"
|
|
[class.unconfirmed]="!sub.confirmed"
|
|
nz-tooltip
|
|
[nzTooltipTitle]="getTooltip(sub)"
|
|
>
|
|
{{ getDisplayName(sub.subscriber_user_id) }}
|
|
</span>
|
|
}
|
|
</div>
|
|
}
|
|
`,
|
|
styles: [`
|
|
.text-muted {
|
|
color: #999;
|
|
}
|
|
.subscribers-list {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 4px;
|
|
}
|
|
.subscriber {
|
|
background: #f0f0f0;
|
|
padding: 2px 8px;
|
|
border-radius: 4px;
|
|
font-size: 12px;
|
|
}
|
|
.subscriber.unconfirmed {
|
|
background: #fff7e6;
|
|
color: #d48806;
|
|
}
|
|
`]
|
|
})
|
|
export class ChannelSubscribersComponent implements OnInit {
|
|
private apiService = inject(ApiService);
|
|
private authService = inject(AuthService);
|
|
private userCacheService = inject(UserCacheService);
|
|
|
|
channelId = input.required<string>();
|
|
|
|
loading = signal(true);
|
|
subscribers = signal<Subscription[]>([]);
|
|
userNames = signal<Map<string, ResolvedUser>>(new Map());
|
|
|
|
ngOnInit(): void {
|
|
this.loadSubscribers();
|
|
}
|
|
|
|
private loadSubscribers(): void {
|
|
const userId = this.authService.getUserId();
|
|
if (!userId) {
|
|
this.loading.set(false);
|
|
return;
|
|
}
|
|
|
|
this.apiService.getChannelSubscriptions(userId, this.channelId()).subscribe({
|
|
next: (response) => {
|
|
this.subscribers.set(response.subscriptions);
|
|
this.loading.set(false);
|
|
this.resolveUserNames(response.subscriptions);
|
|
},
|
|
error: () => {
|
|
this.loading.set(false);
|
|
}
|
|
});
|
|
}
|
|
|
|
private resolveUserNames(subscriptions: Subscription[]): void {
|
|
const userIds = new Set(subscriptions.map(s => s.subscriber_user_id));
|
|
for (const userId of userIds) {
|
|
this.userCacheService.resolveUser(userId).subscribe(resolved => {
|
|
this.userNames.update(map => new Map(map).set(userId, resolved));
|
|
});
|
|
}
|
|
}
|
|
|
|
getDisplayName(userId: string): string {
|
|
const resolved = this.userNames().get(userId);
|
|
return resolved?.displayName || userId;
|
|
}
|
|
|
|
getTooltip(sub: Subscription): string {
|
|
const status = sub.confirmed ? 'Confirmed' : 'Pending';
|
|
return `${sub.subscriber_user_id} (${status})`;
|
|
}
|
|
}
|