feat: Allow admin to create new text channels
This commit is contained in:
@@ -1,35 +1,18 @@
|
||||
import { createReducer, on } from '@ngrx/store';
|
||||
import {
|
||||
Room,
|
||||
RoomSettings,
|
||||
Channel
|
||||
RoomSettings
|
||||
} from '../../shared-kernel';
|
||||
import { type ServerInfo } from '../../domains/server-directory';
|
||||
import { RoomsActions } from './rooms.actions';
|
||||
import { defaultChannels } from './room-channels.defaults';
|
||||
import {
|
||||
isChannelNameTaken,
|
||||
normalizeChannelName,
|
||||
normalizeRoomChannels
|
||||
} from './room-channels.rules';
|
||||
import { pruneRoomMembers } from './room-members.helpers';
|
||||
|
||||
/** Default channels for a new server */
|
||||
export function defaultChannels(): Channel[] {
|
||||
return [
|
||||
{ id: 'general',
|
||||
name: 'general',
|
||||
type: 'text',
|
||||
position: 0 },
|
||||
{ id: 'random',
|
||||
name: 'random',
|
||||
type: 'text',
|
||||
position: 1 },
|
||||
{ id: 'vc-general',
|
||||
name: 'General',
|
||||
type: 'voice',
|
||||
position: 0 },
|
||||
{ id: 'vc-afk',
|
||||
name: 'AFK',
|
||||
type: 'voice',
|
||||
position: 1 }
|
||||
];
|
||||
}
|
||||
|
||||
/** Deduplicate rooms by id, keeping the last occurrence */
|
||||
function deduplicateRooms(rooms: Room[]): Room[] {
|
||||
const seen = new Map<string, Room>();
|
||||
@@ -46,11 +29,23 @@ function enrichRoom(room: Room): Room {
|
||||
return {
|
||||
...room,
|
||||
hasPassword: typeof room.hasPassword === 'boolean' ? room.hasPassword : !!room.password,
|
||||
channels: room.channels || defaultChannels(),
|
||||
channels: normalizeRoomChannels(room.channels) || defaultChannels(),
|
||||
members: pruneRoomMembers(room.members || [])
|
||||
};
|
||||
}
|
||||
|
||||
function resolveActiveTextChannelId(channels: Room['channels'], currentActiveChannelId: string): string {
|
||||
const textChannels = (channels ?? []).filter((channel) => channel.type === 'text');
|
||||
|
||||
return textChannels.some((channel) => channel.id === currentActiveChannelId)
|
||||
? currentActiveChannelId
|
||||
: (textChannels[0]?.id ?? 'general');
|
||||
}
|
||||
|
||||
function getDefaultTextChannelId(room: Room): string {
|
||||
return resolveActiveTextChannelId(enrichRoom(room).channels, 'general');
|
||||
}
|
||||
|
||||
/** Upsert a room into a saved-rooms list (add or replace by id) */
|
||||
function upsertRoom(savedRooms: Room[], room: Room): Room[] {
|
||||
const normalizedRoom = enrichRoom(room);
|
||||
@@ -169,7 +164,7 @@ export const roomsReducer = createReducer(
|
||||
isSignalServerReconnecting: false,
|
||||
signalServerCompatibilityError: null,
|
||||
isConnected: true,
|
||||
activeChannelId: 'general'
|
||||
activeChannelId: getDefaultTextChannelId(enriched)
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -198,7 +193,7 @@ export const roomsReducer = createReducer(
|
||||
isSignalServerReconnecting: false,
|
||||
signalServerCompatibilityError: null,
|
||||
isConnected: true,
|
||||
activeChannelId: 'general'
|
||||
activeChannelId: getDefaultTextChannelId(enriched)
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -242,7 +237,7 @@ export const roomsReducer = createReducer(
|
||||
isConnecting: false,
|
||||
signalServerCompatibilityError: null,
|
||||
isConnected: true,
|
||||
activeChannelId: 'general'
|
||||
activeChannelId: getDefaultTextChannelId(enriched)
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -317,7 +312,8 @@ export const roomsReducer = createReducer(
|
||||
savedRooms: upsertRoom(state.savedRooms, room),
|
||||
isSignalServerReconnecting: false,
|
||||
signalServerCompatibilityError: null,
|
||||
isConnected: true
|
||||
isConnected: true,
|
||||
activeChannelId: getDefaultTextChannelId(room)
|
||||
})),
|
||||
|
||||
// Clear current room
|
||||
@@ -375,7 +371,8 @@ export const roomsReducer = createReducer(
|
||||
return {
|
||||
...state,
|
||||
currentRoom: updatedRoom,
|
||||
savedRooms: upsertRoom(state.savedRooms, updatedRoom)
|
||||
savedRooms: upsertRoom(state.savedRooms, updatedRoom),
|
||||
activeChannelId: resolveActiveTextChannelId(updatedRoom.channels, state.activeChannelId)
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -412,14 +409,22 @@ export const roomsReducer = createReducer(
|
||||
return state;
|
||||
|
||||
const existing = state.currentRoom.channels || defaultChannels();
|
||||
const updatedChannels = [...existing, channel];
|
||||
const normalizedName = normalizeChannelName(channel.name);
|
||||
|
||||
if (!normalizedName || existing.some((entry) => entry.id === channel.id) || isChannelNameTaken(existing, normalizedName)) {
|
||||
return state;
|
||||
}
|
||||
|
||||
const updatedChannels = [...existing, { ...channel,
|
||||
name: normalizedName }];
|
||||
const updatedRoom = { ...state.currentRoom,
|
||||
channels: updatedChannels };
|
||||
|
||||
return {
|
||||
...state,
|
||||
currentRoom: updatedRoom,
|
||||
savedRooms: upsertRoom(state.savedRooms, updatedRoom)
|
||||
savedRooms: upsertRoom(state.savedRooms, updatedRoom),
|
||||
activeChannelId: resolveActiveTextChannelId(updatedRoom.channels, state.activeChannelId)
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -436,7 +441,7 @@ export const roomsReducer = createReducer(
|
||||
...state,
|
||||
currentRoom: updatedRoom,
|
||||
savedRooms: upsertRoom(state.savedRooms, updatedRoom),
|
||||
activeChannelId: state.activeChannelId === channelId ? 'general' : state.activeChannelId
|
||||
activeChannelId: resolveActiveTextChannelId(updatedRoom.channels, state.activeChannelId)
|
||||
};
|
||||
}),
|
||||
|
||||
@@ -445,8 +450,14 @@ export const roomsReducer = createReducer(
|
||||
return state;
|
||||
|
||||
const existing = state.currentRoom.channels || defaultChannels();
|
||||
const normalizedName = normalizeChannelName(name);
|
||||
|
||||
if (!normalizedName || isChannelNameTaken(existing, normalizedName, channelId)) {
|
||||
return state;
|
||||
}
|
||||
|
||||
const updatedChannels = existing.map(channel => channel.id === channelId ? { ...channel,
|
||||
name } : channel);
|
||||
name: normalizedName } : channel);
|
||||
const updatedRoom = { ...state.currentRoom,
|
||||
channels: updatedChannels };
|
||||
|
||||
|
||||
Reference in New Issue
Block a user