Move toju-app into own its folder
This commit is contained in:
250
toju-app/src/app/store/users/users.reducer.ts
Normal file
250
toju-app/src/app/store/users/users.reducer.ts
Normal file
@@ -0,0 +1,250 @@
|
||||
import { createReducer, on } from '@ngrx/store';
|
||||
import {
|
||||
EntityState,
|
||||
EntityAdapter,
|
||||
createEntityAdapter
|
||||
} from '@ngrx/entity';
|
||||
import { User, BanEntry } from '../../shared-kernel';
|
||||
import { UsersActions } from './users.actions';
|
||||
|
||||
export interface UsersState extends EntityState<User> {
|
||||
currentUserId: string | null;
|
||||
hostId: string | null;
|
||||
loading: boolean;
|
||||
error: string | null;
|
||||
bans: BanEntry[];
|
||||
}
|
||||
|
||||
export const usersAdapter: EntityAdapter<User> = createEntityAdapter<User>({
|
||||
selectId: (user) => user.id,
|
||||
sortComparer: (userA, userB) => userA.username.localeCompare(userB.username)
|
||||
});
|
||||
|
||||
export const initialState: UsersState = usersAdapter.getInitialState({
|
||||
currentUserId: null,
|
||||
hostId: null,
|
||||
loading: false,
|
||||
error: null,
|
||||
bans: []
|
||||
});
|
||||
|
||||
export const usersReducer = createReducer(
|
||||
initialState,
|
||||
on(UsersActions.loadCurrentUser, (state) => ({
|
||||
...state,
|
||||
loading: true,
|
||||
error: null
|
||||
})),
|
||||
|
||||
on(UsersActions.loadCurrentUserSuccess, (state, { user }) =>
|
||||
usersAdapter.upsertOne(user, {
|
||||
...state,
|
||||
currentUserId: user.id,
|
||||
loading: false
|
||||
})
|
||||
),
|
||||
|
||||
on(UsersActions.loadCurrentUserFailure, (state, { error }) => ({
|
||||
...state,
|
||||
loading: false,
|
||||
error
|
||||
})),
|
||||
on(UsersActions.setCurrentUser, (state, { user }) =>
|
||||
usersAdapter.upsertOne(user, {
|
||||
...state,
|
||||
currentUserId: user.id
|
||||
})
|
||||
),
|
||||
on(UsersActions.updateCurrentUser, (state, { updates }) => {
|
||||
if (!state.currentUserId)
|
||||
return state;
|
||||
|
||||
return usersAdapter.updateOne(
|
||||
{
|
||||
id: state.currentUserId,
|
||||
changes: updates
|
||||
},
|
||||
state
|
||||
);
|
||||
}),
|
||||
on(UsersActions.loadRoomUsers, (state) => ({
|
||||
...state,
|
||||
loading: true,
|
||||
error: null
|
||||
})),
|
||||
|
||||
on(UsersActions.loadRoomUsersSuccess, (state, { users }) =>
|
||||
usersAdapter.upsertMany(users, {
|
||||
...state,
|
||||
loading: false
|
||||
})
|
||||
),
|
||||
|
||||
on(UsersActions.loadRoomUsersFailure, (state, { error }) => ({
|
||||
...state,
|
||||
loading: false,
|
||||
error
|
||||
})),
|
||||
on(UsersActions.userJoined, (state, { user }) =>
|
||||
usersAdapter.upsertOne(user, state)
|
||||
),
|
||||
on(UsersActions.userLeft, (state, { userId }) =>
|
||||
usersAdapter.removeOne(userId, state)
|
||||
),
|
||||
on(UsersActions.updateUser, (state, { userId, updates }) =>
|
||||
usersAdapter.updateOne(
|
||||
{
|
||||
id: userId,
|
||||
changes: updates
|
||||
},
|
||||
state
|
||||
)
|
||||
),
|
||||
on(UsersActions.updateUserRole, (state, { userId, role }) =>
|
||||
usersAdapter.updateOne(
|
||||
{
|
||||
id: userId,
|
||||
changes: { role }
|
||||
},
|
||||
state
|
||||
)
|
||||
),
|
||||
on(UsersActions.kickUserSuccess, (state, { userId }) =>
|
||||
usersAdapter.removeOne(userId, state)
|
||||
),
|
||||
on(UsersActions.banUserSuccess, (state, { userId, ban }) => {
|
||||
const newState = usersAdapter.removeOne(userId, state);
|
||||
|
||||
return {
|
||||
...newState,
|
||||
bans: [...state.bans, ban]
|
||||
};
|
||||
}),
|
||||
on(UsersActions.unbanUserSuccess, (state, { oderId }) => ({
|
||||
...state,
|
||||
bans: state.bans.filter((ban) => ban.oderId !== oderId)
|
||||
})),
|
||||
on(UsersActions.loadBansSuccess, (state, { bans }) => ({
|
||||
...state,
|
||||
bans
|
||||
})),
|
||||
on(UsersActions.adminMuteUser, (state, { userId }) =>
|
||||
usersAdapter.updateOne(
|
||||
{
|
||||
id: userId,
|
||||
changes: {
|
||||
voiceState: {
|
||||
...state.entities[userId]?.voiceState,
|
||||
isConnected: state.entities[userId]?.voiceState?.isConnected ?? false,
|
||||
isMuted: true,
|
||||
isDeafened: state.entities[userId]?.voiceState?.isDeafened ?? false,
|
||||
isSpeaking: false,
|
||||
isMutedByAdmin: true
|
||||
}
|
||||
}
|
||||
},
|
||||
state
|
||||
)
|
||||
),
|
||||
on(UsersActions.adminUnmuteUser, (state, { userId }) =>
|
||||
usersAdapter.updateOne(
|
||||
{
|
||||
id: userId,
|
||||
changes: {
|
||||
voiceState: {
|
||||
...state.entities[userId]?.voiceState,
|
||||
isConnected: state.entities[userId]?.voiceState?.isConnected ?? false,
|
||||
isMuted: state.entities[userId]?.voiceState?.isMuted ?? false,
|
||||
isDeafened: state.entities[userId]?.voiceState?.isDeafened ?? false,
|
||||
isSpeaking: state.entities[userId]?.voiceState?.isSpeaking ?? false,
|
||||
isMutedByAdmin: false
|
||||
}
|
||||
}
|
||||
},
|
||||
state
|
||||
)
|
||||
),
|
||||
on(UsersActions.updateVoiceState, (state, { userId, voiceState }) => {
|
||||
const prev = state.entities[userId]?.voiceState || {
|
||||
isConnected: false,
|
||||
isMuted: false,
|
||||
isDeafened: false,
|
||||
isSpeaking: false
|
||||
};
|
||||
|
||||
return usersAdapter.updateOne(
|
||||
{
|
||||
id: userId,
|
||||
changes: {
|
||||
voiceState: {
|
||||
isConnected: voiceState.isConnected ?? prev.isConnected,
|
||||
isMuted: voiceState.isMuted ?? prev.isMuted,
|
||||
isDeafened: voiceState.isDeafened ?? prev.isDeafened,
|
||||
isSpeaking: voiceState.isSpeaking ?? prev.isSpeaking,
|
||||
isMutedByAdmin: voiceState.isMutedByAdmin ?? prev.isMutedByAdmin,
|
||||
volume: voiceState.volume ?? prev.volume,
|
||||
// Use explicit undefined check - if undefined is passed, clear the value
|
||||
roomId: voiceState.roomId !== undefined ? voiceState.roomId : prev.roomId,
|
||||
serverId: voiceState.serverId !== undefined ? voiceState.serverId : prev.serverId
|
||||
}
|
||||
}
|
||||
},
|
||||
state
|
||||
);
|
||||
}),
|
||||
on(UsersActions.updateScreenShareState, (state, { userId, screenShareState }) => {
|
||||
const prev = state.entities[userId]?.screenShareState || {
|
||||
isSharing: false
|
||||
};
|
||||
|
||||
return usersAdapter.updateOne(
|
||||
{
|
||||
id: userId,
|
||||
changes: {
|
||||
screenShareState: {
|
||||
isSharing: screenShareState.isSharing ?? prev.isSharing,
|
||||
streamId: screenShareState.streamId ?? prev.streamId,
|
||||
sourceId: screenShareState.sourceId ?? prev.sourceId,
|
||||
sourceName: screenShareState.sourceName ?? prev.sourceName
|
||||
}
|
||||
}
|
||||
},
|
||||
state
|
||||
);
|
||||
}),
|
||||
on(UsersActions.syncUsers, (state, { users }) =>
|
||||
usersAdapter.upsertMany(users, state)
|
||||
),
|
||||
on(UsersActions.clearUsers, (state) => {
|
||||
const idsToRemove = Object.keys(state.entities).filter((id) => id !== state.currentUserId);
|
||||
|
||||
return usersAdapter.removeMany(idsToRemove, {
|
||||
...state,
|
||||
hostId: null
|
||||
});
|
||||
}),
|
||||
on(UsersActions.updateHost, (state, { userId }) => {
|
||||
let newState = state;
|
||||
|
||||
if (state.hostId && state.hostId !== userId) {
|
||||
newState = usersAdapter.updateOne(
|
||||
{
|
||||
id: state.hostId,
|
||||
changes: { role: 'member' }
|
||||
},
|
||||
state
|
||||
);
|
||||
}
|
||||
|
||||
return usersAdapter.updateOne(
|
||||
{
|
||||
id: userId,
|
||||
changes: { role: 'host' }
|
||||
},
|
||||
{
|
||||
...newState,
|
||||
hostId: userId
|
||||
}
|
||||
);
|
||||
})
|
||||
);
|
||||
Reference in New Issue
Block a user