feat: (speaker-stats) fix refresh and minor refactoring
This commit is contained in:
parent
827e8201d4
commit
8ef48a8a1d
|
@ -99,10 +99,10 @@ export const IOS_SCREENSHARING_ENABLED = 'ios.screensharing.enabled';
|
|||
export const ANDROID_SCREENSHARING_ENABLED = 'android.screensharing.enabled';
|
||||
|
||||
/**
|
||||
* Flag indicating if speaker statistics should be enabled in android.
|
||||
* Flag indicating if speaker statistics should be enabled.
|
||||
* Default: enabled (true).
|
||||
*/
|
||||
export const ANDROID_SPEAKERSTATS_ENABLED = 'android.speakerstats.enabled';
|
||||
export const SPEAKERSTATS_ENABLED = 'speakerstats.enabled';
|
||||
|
||||
/**
|
||||
* Flag indicating if kickout is enabled.
|
||||
|
|
|
@ -14,17 +14,17 @@ import {
|
|||
* Component that renders the list of speaker stats.
|
||||
*
|
||||
* @param {Function} speakerStatsItem - React element tu use when rendering.
|
||||
* @param {boolean} [isWeb=false] - Is for web in browser.
|
||||
* @returns {Function}
|
||||
*/
|
||||
const abstractSpeakerStatsList = (speakerStatsItem: Function, isWeb: boolean = true): Function[] => {
|
||||
const abstractSpeakerStatsList = (speakerStatsItem: Function): Function[] => {
|
||||
const dispatch = useDispatch();
|
||||
const { t } = useTranslation();
|
||||
const conference = useSelector(state => state['features/base/conference'].conference);
|
||||
const speakerStats = useSelector(state => state['features/speaker-stats'].stats);
|
||||
const localParticipant = useSelector(getLocalParticipant);
|
||||
const { enableFacialRecognition } = isWeb ? useSelector(state => state['features/base/config']) : {};
|
||||
const { facialExpressions: localFacialExpressions } = isWeb
|
||||
? useSelector(state => state['features/facial-recognition']) : {};
|
||||
const { enableFacialRecognition } = useSelector(state => state['features/base/config']) || {};
|
||||
const { facialExpressions: localFacialExpressions } = useSelector(
|
||||
state => state['features/facial-recognition']) || {};
|
||||
|
||||
/**
|
||||
* Update the internal state with the latest speaker stats.
|
||||
|
@ -62,21 +62,22 @@ const abstractSpeakerStatsList = (speakerStatsItem: Function, isWeb: boolean = t
|
|||
});
|
||||
|
||||
const updateStats = useCallback(
|
||||
() => dispatch(initUpdateStats(
|
||||
() => getLocalSpeakerStats())), [ dispatch, initUpdateStats() ]);
|
||||
() => dispatch(initUpdateStats(getLocalSpeakerStats)),
|
||||
[ dispatch, initUpdateStats ]);
|
||||
|
||||
useEffect(() => {
|
||||
const updateInterval = setInterval(() => updateStats(), SPEAKER_STATS_RELOAD_INTERVAL);
|
||||
const intervalId = setInterval(() => {
|
||||
updateStats();
|
||||
}, SPEAKER_STATS_RELOAD_INTERVAL);
|
||||
|
||||
return () => {
|
||||
clearInterval(updateInterval);
|
||||
};
|
||||
}, [ dispatch, conference ]);
|
||||
return () => clearInterval(intervalId);
|
||||
}, []);
|
||||
|
||||
const userIds = Object.keys(getLocalSpeakerStats());
|
||||
const localSpeakerStats = Object.keys(speakerStats).length === 0 ? getLocalSpeakerStats() : speakerStats;
|
||||
const userIds = Object.keys(localSpeakerStats);
|
||||
|
||||
return userIds.map(userId => {
|
||||
const statsModel = getLocalSpeakerStats()[userId];
|
||||
const statsModel = localSpeakerStats[userId];
|
||||
|
||||
if (!statsModel || statsModel.hidden) {
|
||||
return null;
|
||||
|
@ -85,6 +86,7 @@ const abstractSpeakerStatsList = (speakerStatsItem: Function, isWeb: boolean = t
|
|||
|
||||
props.isDominantSpeaker = statsModel.isDominantSpeaker();
|
||||
props.dominantSpeakerTime = statsModel.getTotalDominantSpeakerTime();
|
||||
props.participantId = userId;
|
||||
props.hasLeft = statsModel.hasLeft();
|
||||
if (enableFacialRecognition) {
|
||||
props.facialExpressions = statsModel.getFacialExpressions();
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
// @flow
|
||||
|
||||
import { createToolbarEvent, sendAnalytics } from '../../../analytics';
|
||||
import { getFeatureFlag, SPEAKERSTATS_ENABLED } from '../../../base/flags';
|
||||
import { translate } from '../../../base/i18n';
|
||||
import { connect } from '../../../base/redux';
|
||||
import { navigate } from '../../../conference/components/native/ConferenceNavigationContainerRef';
|
||||
|
@ -25,4 +26,23 @@ class SpeakerStatsButton extends AbstractSpeakerStatsButton {
|
|||
}
|
||||
}
|
||||
|
||||
export default translate(connect()(SpeakerStatsButton));
|
||||
/**
|
||||
* Maps (parts of) the redux state to the associated props for the
|
||||
* {@code SpeakerStatsButton} component.
|
||||
*
|
||||
* @param {Object} state - The Redux state.
|
||||
* @private
|
||||
* @returns {{
|
||||
* visible: boolean
|
||||
* }}
|
||||
*/
|
||||
function _mapStateToProps(state): Object {
|
||||
const enabled = getFeatureFlag(state, SPEAKERSTATS_ENABLED, true);
|
||||
|
||||
return {
|
||||
visible: enabled
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
export default translate(connect(_mapStateToProps)(SpeakerStatsButton));
|
||||
|
|
|
@ -20,6 +20,11 @@ type Props = {
|
|||
*/
|
||||
dominantSpeakerTime: number,
|
||||
|
||||
/**
|
||||
* The id of the user.
|
||||
*/
|
||||
participantId: string,
|
||||
|
||||
/**
|
||||
* True if the participant is no longer in the meeting.
|
||||
*/
|
||||
|
@ -41,7 +46,7 @@ const SpeakerStatsItem = (props: Props) => {
|
|||
|
||||
return (
|
||||
<View
|
||||
key = { props.displayName + props.dominantSpeakerTime }
|
||||
key = { props.participantId }
|
||||
style = { style.speakerStatsItemContainer }>
|
||||
<View style = { style.speakerStatsItemStatus }>
|
||||
<View style = { [ style.speakerStatsItemStatusDot, { backgroundColor: dotColor } ] } />
|
||||
|
|
|
@ -13,7 +13,7 @@ import SpeakerStatsItem from './SpeakerStatsItem';
|
|||
* @returns {React$Element<any>}
|
||||
*/
|
||||
const SpeakerStatsList = () => {
|
||||
const items = abstractSpeakerStatsList(SpeakerStatsItem, false);
|
||||
const items = abstractSpeakerStatsList(SpeakerStatsItem);
|
||||
|
||||
return (
|
||||
<View>
|
||||
|
|
|
@ -35,6 +35,11 @@ type Props = {
|
|||
*/
|
||||
dominantSpeakerTime: number,
|
||||
|
||||
/**
|
||||
* The id of the user.
|
||||
*/
|
||||
participantId: string,
|
||||
|
||||
/**
|
||||
* True if the participant is no longer in the meeting.
|
||||
*/
|
||||
|
@ -68,7 +73,7 @@ const SpeakerStatsItem = (props: Props) => {
|
|||
return (
|
||||
<div
|
||||
className = { rowDisplayClass }
|
||||
key = { props.displayName } >
|
||||
key = { props.participantId } >
|
||||
<div className = 'speaker-stats-item__status'>
|
||||
<span className = { speakerStatusClass } />
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1 @@
|
|||
export const SPEAKER_STATS_RELOAD_INTERVAL = 1000;
|
||||
|
||||
export const SPEAKER_STATS_VIEW_MODEL_ID = 'speakerStats';
|
||||
|
|
|
@ -10,7 +10,8 @@ import {
|
|||
createToolbarEvent,
|
||||
sendAnalytics
|
||||
} from '../../../analytics';
|
||||
import { getToolbarButtons, isToolbarButtonEnabled } from '../../../base/config';
|
||||
import { getToolbarButtons } from '../../../base/config';
|
||||
import { isToolbarButtonEnabled } from '../../../base/config/functions.web';
|
||||
import { openDialog, toggleDialog } from '../../../base/dialog';
|
||||
import { isIosMobileBrowser, isMobileBrowser } from '../../../base/environment/utils';
|
||||
import { translate } from '../../../base/i18n';
|
||||
|
|
Loading…
Reference in New Issue