feat(video-quality): persist.

This commit is contained in:
Hristo Terezov 2020-09-01 16:45:59 -05:00
parent 43f36c8cfd
commit 25839b18d2
5 changed files with 73 additions and 14 deletions

View File

@ -12,6 +12,7 @@ import {
} from '../../base/icons'; } from '../../base/icons';
import { connect } from '../../base/redux'; import { connect } from '../../base/redux';
import { VIDEO_QUALITY_LEVELS } from '../constants'; import { VIDEO_QUALITY_LEVELS } from '../constants';
import { findNearestQualityLevel } from '../functions';
/** /**
* A map of of selectable receive resolutions to corresponding icons. * A map of of selectable receive resolutions to corresponding icons.
@ -69,9 +70,10 @@ class OverflowMenuVideoQualityItem extends Component<Props> {
*/ */
render() { render() {
const { _audioOnly, _videoQuality } = this.props; const { _audioOnly, _videoQuality } = this.props;
const icon = _audioOnly || !_videoQuality const videoQualityLevel = findNearestQualityLevel(_videoQuality);
const icon = _audioOnly || !videoQualityLevel
? IconVideoQualityAudioOnly ? IconVideoQualityAudioOnly
: VIDEO_QUALITY_TO_ICON[_videoQuality]; : VIDEO_QUALITY_TO_ICON[videoQualityLevel];
return ( return (
<li <li

View File

@ -316,10 +316,13 @@ class VideoQualitySlider extends Component<Props> {
return _sliderOptions.indexOf(audioOnlyOption); return _sliderOptions.indexOf(audioOnlyOption);
} }
const matchingOption = _sliderOptions.find( for (let i = 0; i < _sliderOptions.length; i++) {
({ videoQuality }) => videoQuality === _sendrecvVideoQuality); if (_sliderOptions[i].videoQuality >= _sendrecvVideoQuality) {
return i;
}
}
return _sliderOptions.indexOf(matchingOption); return -1;
} }
_onSliderChange: () => void; _onSliderChange: () => void;

View File

@ -2,6 +2,26 @@
import { CFG_LVL_TO_APP_QUALITY_LVL, VIDEO_QUALITY_LEVELS } from './constants'; import { CFG_LVL_TO_APP_QUALITY_LVL, VIDEO_QUALITY_LEVELS } from './constants';
const { LOW, STANDARD, HIGH } = VIDEO_QUALITY_LEVELS;
const videoQualityLevels = [ LOW, STANDARD, HIGH ];
/**
* Finds the nearest video quality level to the passed video quality.
*
* @param {number} videoQuality - The video quality.
* @returns {number|undefined} - The found quality level.
*/
export function findNearestQualityLevel(videoQuality: number) {
for (let i = 0; i < videoQualityLevels.length; i++) {
const level = videoQualityLevels[i];
if (level >= videoQuality) {
return level;
}
}
return undefined;
}
/** /**
* Selects {@code VIDEO_QUALITY_LEVELS} for the given {@link availableHeight} and threshold to quality mapping. * Selects {@code VIDEO_QUALITY_LEVELS} for the given {@link availableHeight} and threshold to quality mapping.

View File

@ -4,6 +4,7 @@ import {
CONFERENCE_JOINED, CONFERENCE_JOINED,
DATA_CHANNEL_OPENED DATA_CHANNEL_OPENED
} from '../base/conference'; } from '../base/conference';
import { SET_CONFIG } from '../base/config';
import { getParticipantCount } from '../base/participants'; import { getParticipantCount } from '../base/participants';
import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux'; import { MiddlewareRegistry, StateListenerRegistry } from '../base/redux';
import { shouldDisplayTileView } from '../video-layout'; import { shouldDisplayTileView } from '../video-layout';
@ -39,6 +40,18 @@ MiddlewareRegistry.register(({ dispatch, getState }) => next => action => {
} }
break; break;
} }
case SET_CONFIG: {
const state = getState();
const { videoQuality = {} } = state['features/base/config'];
if (videoQuality.persist) {
dispatch(
setPreferredVideoQuality(
state['features/video-quality-persistent-storage'].persistedPrefferedVideoQuality));
}
break;
}
} }
return result; return result;

View File

@ -1,13 +1,11 @@
import { SET_CONFIG } from '../base/config'; import { SET_CONFIG } from '../base/config';
import { ReducerRegistry, set } from '../base/redux'; import { PersistenceRegistry, ReducerRegistry, set } from '../base/redux';
import { SET_MAX_RECEIVER_VIDEO_QUALITY, SET_PREFERRED_VIDEO_QUALITY } from './actionTypes'; import { SET_MAX_RECEIVER_VIDEO_QUALITY, SET_PREFERRED_VIDEO_QUALITY } from './actionTypes';
import { VIDEO_QUALITY_LEVELS } from './constants'; import { VIDEO_QUALITY_LEVELS } from './constants';
import { validateMinHeightForQualityLvl } from './functions'; import { validateMinHeightForQualityLvl } from './functions';
import logger from './logger'; import logger from './logger';
const STORE_NAME = 'features/video-quality';
const DEFAULT_STATE = { const DEFAULT_STATE = {
maxReceiverVideoQuality: VIDEO_QUALITY_LEVELS.HIGH, maxReceiverVideoQuality: VIDEO_QUALITY_LEVELS.HIGH,
minHeightForQualityLvl: new Map(), minHeightForQualityLvl: new Map(),
@ -17,7 +15,27 @@ const DEFAULT_STATE = {
DEFAULT_STATE.minHeightForQualityLvl.set(360, VIDEO_QUALITY_LEVELS.STANDARD); DEFAULT_STATE.minHeightForQualityLvl.set(360, VIDEO_QUALITY_LEVELS.STANDARD);
DEFAULT_STATE.minHeightForQualityLvl.set(720, VIDEO_QUALITY_LEVELS.HIGH); DEFAULT_STATE.minHeightForQualityLvl.set(720, VIDEO_QUALITY_LEVELS.HIGH);
ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
// When the persisted state is initialized the current state (for example the deafault state) is erased.
// In order to workaround this issue we need additional state for the persisted properties.
PersistenceRegistry.register('features/video-quality-persistent-storage');
ReducerRegistry.register('features/video-quality-persistent-storage', (state = {}, action) => {
switch (action.type) {
case SET_PREFERRED_VIDEO_QUALITY: {
const { preferredVideoQuality } = action;
return {
...state,
persistedPrefferedVideoQuality: preferredVideoQuality
};
}
}
return state;
});
ReducerRegistry.register('features/video-quality', (state = DEFAULT_STATE, action) => {
switch (action.type) { switch (action.type) {
case SET_CONFIG: case SET_CONFIG:
return _setConfig(state, action); return _setConfig(state, action);
@ -26,11 +44,14 @@ ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
state, state,
'maxReceiverVideoQuality', 'maxReceiverVideoQuality',
action.maxReceiverVideoQuality); action.maxReceiverVideoQuality);
case SET_PREFERRED_VIDEO_QUALITY: case SET_PREFERRED_VIDEO_QUALITY: {
return set( const { preferredVideoQuality } = action;
state,
'preferredVideoQuality', return {
action.preferredVideoQuality); ...state,
preferredVideoQuality
};
}
} }
return state; return state;