diff --git a/toju-app/src/app/domains/server-directory/feature/invite/invite.component.ts b/toju-app/src/app/domains/server-directory/feature/invite/invite.component.ts index 4dc2fab..6c7aab7 100644 --- a/toju-app/src/app/domains/server-directory/feature/invite/invite.component.ts +++ b/toju-app/src/app/domains/server-directory/feature/invite/invite.component.ts @@ -139,7 +139,12 @@ export class InviteComponent implements OnInit { RoomsActions.joinRoom({ roomId: joinResponse.server.id, serverInfo: { + ...invite.server, ...joinResponse.server, + channels: + Array.isArray(joinResponse.server.channels) && joinResponse.server.channels.length > 0 + ? joinResponse.server.channels + : invite.server.channels, sourceId: context.endpoint.id, sourceName: context.endpoint.name, sourceUrl: context.sourceUrl diff --git a/toju-app/src/app/domains/server-directory/feature/server-search/server-search.component.ts b/toju-app/src/app/domains/server-directory/feature/server-search/server-search.component.ts index b8ee74f..38a4f89 100644 --- a/toju-app/src/app/domains/server-directory/feature/server-search/server-search.component.ts +++ b/toju-app/src/app/domains/server-directory/feature/server-search/server-search.component.ts @@ -241,6 +241,7 @@ export class ServerSearchComponent implements OnInit { maxUsers: room.maxUsers ?? 50, hasPassword: typeof room.hasPassword === 'boolean' ? room.hasPassword : !!room.password, isPrivate: room.isPrivate, + channels: room.channels, createdAt: room.createdAt, ownerId: room.hostId, sourceId: room.sourceId, @@ -272,7 +273,14 @@ export class ServerSearchComponent implements OnInit { sourceId: server.sourceId, sourceUrl: server.sourceUrl })); - const resolvedServer = response.server ?? server; + const resolvedServer = { + ...server, + ...response.server, + channels: + Array.isArray(response.server.channels) && response.server.channels.length > 0 + ? response.server.channels + : server.channels + }; this.closePasswordDialog(); this.store.dispatch( diff --git a/toju-app/src/app/features/servers/servers-rail.component.ts b/toju-app/src/app/features/servers/servers-rail.component.ts index 1136471..dc3de66 100644 --- a/toju-app/src/app/features/servers/servers-rail.component.ts +++ b/toju-app/src/app/features/servers/servers-rail.component.ts @@ -311,7 +311,11 @@ export class ServersRailComponent { roomId: room.id, serverInfo: { ...this.toServerInfo(room), - ...response.server + ...response.server, + channels: + Array.isArray(response.server.channels) && response.server.channels.length > 0 + ? response.server.channels + : room.channels } }) ); @@ -370,6 +374,7 @@ export class ServersRailComponent { isPrivate: room.isPrivate, createdAt: room.createdAt, ownerId: room.hostId, + channels: room.channels, sourceId: room.sourceId, sourceName: room.sourceName, sourceUrl: room.sourceUrl diff --git a/toju-app/src/app/store/rooms/rooms.effects.ts b/toju-app/src/app/store/rooms/rooms.effects.ts index 30c3940..eb6ccb2 100644 --- a/toju-app/src/app/store/rooms/rooms.effects.ts +++ b/toju-app/src/app/store/rooms/rooms.effects.ts @@ -117,6 +117,26 @@ function resolveUserDisplayName(user: Pick | n return user?.username?.trim() || 'User'; } +function hasPersistedChannels(channels: Room['channels'] | undefined): channels is NonNullable { + return Array.isArray(channels) && channels.length > 0; +} + +/** Keep cached channels until directory metadata provides a concrete replacement. */ +function resolveRoomChannels( + cachedChannels: Room['channels'] | undefined, + incomingChannels: Room['channels'] | undefined +): Room['channels'] | undefined { + if (hasPersistedChannels(incomingChannels)) { + return incomingChannels; + } + + if (hasPersistedChannels(cachedChannels)) { + return cachedChannels; + } + + return undefined; +} + interface RoomPresenceSignalingMessage { type: string; reason?: string; @@ -302,7 +322,7 @@ export class RoomsEffects { const resolvedRoom: Room = { ...room, isPrivate: typeof serverInfo?.isPrivate === 'boolean' ? serverInfo.isPrivate : room.isPrivate, - channels: Array.isArray(serverInfo?.channels) ? serverInfo.channels : room.channels, + channels: resolveRoomChannels(room.channels, serverInfo?.channels), sourceId: serverInfo?.sourceId ?? room.sourceId, sourceName: serverInfo?.sourceName ?? room.sourceName, sourceUrl: serverInfo?.sourceUrl ?? room.sourceUrl, @@ -336,7 +356,7 @@ export class RoomsEffects { createdAt: Date.now(), userCount: 1, maxUsers: 50, - channels: Array.isArray(serverInfo.channels) ? serverInfo.channels : undefined, + channels: resolveRoomChannels(undefined, serverInfo.channels), sourceId: serverInfo.sourceId, sourceName: serverInfo.sourceName, sourceUrl: serverInfo.sourceUrl @@ -361,7 +381,7 @@ export class RoomsEffects { createdAt: serverData.createdAt || Date.now(), userCount: serverData.userCount, maxUsers: serverData.maxUsers, - channels: Array.isArray(serverData.channels) ? serverData.channels : undefined, + channels: resolveRoomChannels(undefined, serverData.channels), sourceId: serverData.sourceId, sourceName: serverData.sourceName, sourceUrl: serverData.sourceUrl @@ -428,7 +448,7 @@ export class RoomsEffects { hasPassword: !!serverData.hasPassword, isPrivate: serverData.isPrivate, maxUsers: serverData.maxUsers, - channels: Array.isArray(serverData.channels) ? serverData.channels : room.channels, + channels: resolveRoomChannels(room.channels, serverData.channels), sourceId: serverData.sourceId ?? room.sourceId, sourceName: serverData.sourceName ?? room.sourceName, sourceUrl: serverData.sourceUrl ?? room.sourceUrl