Files
jitsi-meet/react/features/polls/reducer.ts
Дамян Минков 469406d7cd feat(polls): Move polls to using a component (#16406)
* squash: Renames module.

* squash: Loads polls component.

* squash: Attach needed logic when components/hosts load.

* squash: Moves to use component.

* squash: Uses json-message format with types.

* squash: Checks for polls support.

* squash: Fixes comments and moves validate polls to backend.

* squash: Fix debian build.

* fix(polls): Fixes polls in breakout rooms.

* squash: Further simplify types.

Separate type that needs to go into ljm and those used only for the UI part.
Simplify answer/voter type to be unified across operations which simplifies and its logic.

* squash: Change voters structure to be {id, name}.

* squash: Update react/features/conference/functions.any.ts

Co-authored-by: Saúl Ibarra Corretgé <saghul@jitsi.org>

* squash: Drops roomJid from messages. Uses the connection information as breakout does.

---------

Co-authored-by: Saúl Ibarra Corretgé <saghul@jitsi.org>
2025-09-25 16:46:06 -05:00

187 lines
4.5 KiB
TypeScript

import ReducerRegistry from '../base/redux/ReducerRegistry';
import {
CHANGE_VOTE,
CLEAR_POLLS,
EDIT_POLL,
RECEIVE_ANSWER,
RECEIVE_POLL,
REGISTER_VOTE,
REMOVE_POLL,
RESET_NB_UNREAD_POLLS,
SAVE_POLL
} from './actionTypes';
import { IIncomingAnswerData, IPollData } from './types';
const INITIAL_STATE = {
polls: {},
// Number of not read message
nbUnreadPolls: 0
};
export interface IPollsState {
nbUnreadPolls: number;
polls: {
[pollId: string]: IPollData;
};
}
const STORE_NAME = 'features/polls';
ReducerRegistry.register<IPollsState>(STORE_NAME, (state = INITIAL_STATE, action): IPollsState => {
switch (action.type) {
case CHANGE_VOTE: {
const { pollId, value } = action;
return {
...state,
polls: {
...state.polls,
[pollId]: {
...state.polls[pollId],
changingVote: value,
showResults: !value
}
}
};
}
case CLEAR_POLLS: {
return {
...state,
...INITIAL_STATE
};
}
// Reducer triggered when a poll is received or saved.
case RECEIVE_POLL: {
return {
...state,
polls: {
...state.polls,
[action.poll.pollId]: action.poll
},
nbUnreadPolls: state.nbUnreadPolls + 1
};
}
case SAVE_POLL: {
return {
...state,
polls: {
...state.polls,
[action.poll.pollId]: action.poll
}
};
}
// Reducer triggered when an answer is received
// The answer is added to an existing poll
case RECEIVE_ANSWER: {
const { answer }: { answer: IIncomingAnswerData; } = action;
const pollId = answer.pollId;
const poll = state.polls[pollId];
// if the poll doesn't exist
if (!(pollId in state.polls)) {
console.warn('requested poll does not exist: pollId ', pollId);
return state;
}
// if the poll exists, we update it with the incoming answer
for (let i = 0; i < poll.answers.length; i++) {
// if the answer was chosen, we add the senderId to the array of voters of this answer
let voters = poll.answers[i].voters || [];
if (voters.find(user => user.id === answer.senderId)) {
if (!answer.answers[i]) {
voters = voters.filter(user => user.id !== answer.senderId);
}
} else if (answer.answers[i]) {
voters.push({
id: answer.senderId,
name: answer.voterName
});
}
poll.answers[i].voters = voters?.length ? voters : undefined;
}
// finally we update the state by returning the updated poll
return {
...state,
polls: {
...state.polls,
[pollId]: {
...poll,
answers: [ ...poll.answers ]
}
}
};
}
case REGISTER_VOTE: {
const { answers, pollId }: { answers: Array<boolean> | null; pollId: string; } = action;
return {
...state,
polls: {
...state.polls,
[pollId]: {
...state.polls[pollId],
changingVote: false,
lastVote: answers,
showResults: true
}
}
};
}
case RESET_NB_UNREAD_POLLS: {
return {
...state,
nbUnreadPolls: 0
};
}
case EDIT_POLL: {
return {
...state,
polls: {
...state.polls,
[action.pollId]: {
...state.polls[action.pollId],
editing: action.editing
}
}
};
}
case REMOVE_POLL: {
if (Object.keys(state.polls ?? {})?.length === 1) {
return {
...state,
...INITIAL_STATE
};
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { [action.poll.pollId]: _removedPoll, ...newState } = state.polls;
return {
...state,
polls: {
...newState
}
};
}
default:
return state;
}
});