WebApp: Fix channel-detail page for non-owned channels
Build Docker and Deploy / Build Docker Container (push) Successful in 1m48s
Build Docker and Deploy / Run Unit-Tests (push) Successful in 4m11s
Build Docker and Deploy / Deploy to Server (push) Successful in 22s

This commit is contained in:
2026-03-26 17:05:51 +01:00
parent 9352ff5c2c
commit 1f9abb8574
11 changed files with 248 additions and 115 deletions
@@ -21,7 +21,7 @@ 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, Subscription, Message } from '../../../core/models';
import { ChannelWithSubscription, ChannelPreview, Subscription, Message } from '../../../core/models';
import { RelativeTimePipe } from '../../../shared/pipes/relative-time.pipe';
import { CopyToClipboardDirective } from '../../../shared/directives/copy-to-clipboard.directive';
import { QrCodeDisplayComponent } from '../../../shared/components/qr-code-display/qr-code-display.component';
@@ -68,9 +68,11 @@ export class ChannelDetailComponent implements OnInit {
private userCacheService = inject(UserCacheService);
channel = signal<ChannelWithSubscription | null>(null);
channelPreview = signal<ChannelPreview | null>(null);
subscriptions = signal<Subscription[]>([]);
messages = signal<Message[]>([]);
userNames = signal<Map<string, ResolvedUser>>(new Map());
resolvedOwner = signal<ResolvedUser | null>(null);
loading = signal(true);
loadingSubscriptions = signal(false);
loadingMessages = signal(false);
@@ -115,14 +117,26 @@ export class ChannelDetailComponent implements OnInit {
if (!userId) return;
this.loading.set(true);
this.apiService.getChannel(userId, channelId).subscribe({
next: (channel) => {
this.channel.set(channel);
this.loading.set(false);
if (this.isOwner()) {
this.loadSubscriptions(channelId);
this.apiService.getChannelPreview(channelId).subscribe({
next: (preview) => {
this.channelPreview.set(preview);
this.resolveOwner(preview.owner_user_id);
if (preview.owner_user_id === userId) {
this.apiService.getChannel(userId, channelId).subscribe({
next: (channel) => {
this.channel.set(channel);
this.loading.set(false);
this.loadSubscriptions(channelId);
this.loadMessages(channelId);
},
error: () => {
this.loading.set(false);
}
});
} else {
this.loading.set(false);
this.loadMessages(channelId);
}
this.loadMessages(channelId);
},
error: () => {
this.loading.set(false);
@@ -148,14 +162,13 @@ export class ChannelDetailComponent implements OnInit {
}
loadMessages(channelId: string, nextPageToken?: string): void {
const userId = this.authService.getUserId();
if (!userId) return;
this.loadingMessages.set(true);
this.apiService.getChannelMessages(userId, channelId, {
this.apiService.getMessages({
channel_id: [channelId],
page_size: this.messagesPageSize,
next_page_token: nextPageToken,
trimmed: true
trimmed: true,
subscription_status: 'all'
}).subscribe({
next: (response) => {
this.messages.set(response.messages);
@@ -210,6 +223,12 @@ export class ChannelDetailComponent implements OnInit {
}
}
private resolveOwner(ownerId: string): void {
this.userCacheService.resolveUser(ownerId).subscribe(resolved => {
this.resolvedOwner.set(resolved);
});
}
private resolveUserNames(subscriptions: Subscription[]): void {
const userIds = new Set<string>();
for (const sub of subscriptions) {
@@ -232,9 +251,16 @@ export class ChannelDetailComponent implements OnInit {
}
isOwner(): boolean {
const channel = this.channel();
const userId = this.authService.getUserId();
return channel?.owner_user_id === userId;
const channel = this.channel();
if (channel) return channel.owner_user_id === userId;
const preview = this.channelPreview();
if (preview) return preview.owner_user_id === userId;
return false;
}
channelData() {
return this.channel() ?? this.channelPreview();
}
// Edit methods
@@ -290,18 +316,20 @@ export class ChannelDetailComponent implements OnInit {
}
getSubscriptionStatus(): { label: string; color: string } {
const channel = this.channel();
if (!channel) return { label: 'Unknown', color: 'default' };
const data = this.channelData();
if (!data) return { label: 'Unknown', color: 'default' };
const subscription = 'subscribe_key' in data ? data.subscription : data.subscription;
if (this.isOwner()) {
if (channel.subscription) {
if (subscription) {
return { label: 'Owned & Subscribed', color: 'green' };
}
return { label: 'Owned', color: 'blue' };
}
if (channel.subscription) {
if (channel.subscription.confirmed) {
if (subscription) {
if (subscription.confirmed) {
return { label: 'Subscribed', color: 'green' };
}
return { label: 'Pending', color: 'orange' };
@@ -377,7 +405,7 @@ export class ChannelDetailComponent implements OnInit {
}
isUserSubscribed(): boolean {
return this.channel()?.subscription !== null;
return this.channelData()?.subscription !== null && this.channelData()?.subscription !== undefined;
}
toggleSelfSubscription(): void {