jiti-meet/react/features/recent-list/reducer.ts

154 lines
4.6 KiB
TypeScript
Raw Normal View History

2022-09-01 11:00:49 +00:00
/* eslint-disable lines-around-comment */
import { getURLWithoutParamsNormalized } from '../base/connection/utils';
import PersistenceRegistry from '../base/redux/PersistenceRegistry';
import ReducerRegistry from '../base/redux/ReducerRegistry';
2018-01-29 22:20:38 +00:00
2018-01-17 11:19:10 +00:00
import {
_STORE_CURRENT_CONFERENCE,
2018-09-25 12:48:03 +00:00
_UPDATE_CONFERENCE_DURATION,
DELETE_RECENT_LIST_ENTRY
2018-01-17 11:19:10 +00:00
} from './actionTypes';
2022-09-01 11:00:49 +00:00
// @ts-ignore
import { isRecentListEnabled } from './functions';
2018-02-02 18:13:33 +00:00
2022-09-01 11:00:49 +00:00
interface IRecent {
conference: string;
date: number;
duration: number;
}
export type IRecentListState = IRecent[];
/**
* The default/initial redux state of the feature {@code recent-list}.
*
2022-09-01 11:00:49 +00:00
* @type {IRecentListState}
*/
2022-09-01 11:00:49 +00:00
const DEFAULT_STATE: IRecentListState = [];
2018-01-17 11:19:10 +00:00
/**
2018-02-02 18:13:33 +00:00
* The max size of the list.
*
* @type {number}
*/
export const MAX_LIST_SIZE = 30;
/**
* The redux subtree of this feature.
2018-01-17 11:19:10 +00:00
*/
const STORE_NAME = 'features/recent-list';
/**
* Sets up the persistence of the feature {@code recent-list}.
2018-01-17 11:19:10 +00:00
*/
PersistenceRegistry.register(STORE_NAME);
2018-01-17 11:19:10 +00:00
/**
* Reduces redux actions for the purposes of the feature {@code recent-list}.
2018-02-02 18:13:33 +00:00
*/
2022-09-05 09:05:07 +00:00
ReducerRegistry.register<IRecentListState>(STORE_NAME, (state = DEFAULT_STATE, action): IRecentListState => {
if (isRecentListEnabled()) {
switch (action.type) {
case DELETE_RECENT_LIST_ENTRY:
return _deleteRecentListEntry(state, action.entryId);
case _STORE_CURRENT_CONFERENCE:
return _storeCurrentConference(state, action);
case _UPDATE_CONFERENCE_DURATION:
return _updateConferenceDuration(state, action);
default:
return state;
2018-02-02 18:13:33 +00:00
}
}
return state;
});
2018-02-02 18:13:33 +00:00
2018-09-25 12:48:03 +00:00
/**
* Deletes a recent list entry based on the url and date of the item.
*
2022-09-01 11:00:49 +00:00
* @param {IRecentListState} state - The Redux state.
2018-09-25 12:48:03 +00:00
* @param {Object} entryId - The ID object of the entry.
2022-09-01 11:00:49 +00:00
* @returns {IRecentListState}
2018-09-25 12:48:03 +00:00
*/
function _deleteRecentListEntry(
2022-09-01 11:00:49 +00:00
state: Array<IRecent>, entryId: { date: number; url: string; }): Array<IRecent> {
2018-09-25 12:48:03 +00:00
return state.filter(entry =>
entry.conference !== entryId.url || entry.date !== entryId.date);
}
2018-01-17 11:19:10 +00:00
/**
* Adds a new list entry to the redux store.
*
2022-09-01 11:00:49 +00:00
* @param {IRecentListState} state - The redux state of the feature {@code recent-list}.
* @param {Object} action - The redux action.
* @returns {Object}
*/
function _storeCurrentConference(state: IRecentListState, { locationURL }: { locationURL: { href: string; }; }) {
2018-01-17 11:19:10 +00:00
const conference = locationURL.href;
// If the current conference is already in the list, we remove it to re-add
// it to the top.
const nextState
= state.filter(e => !_urlStringEquals(e.conference, conference));
2018-01-17 11:19:10 +00:00
2018-02-02 18:13:33 +00:00
// The list is a reverse-sorted (i.e. the newer elements are at the end).
nextState.push({
2018-01-17 11:19:10 +00:00
conference,
date: Date.now(),
duration: 0 // We don't have the duration yet!
2018-01-17 11:19:10 +00:00
});
2018-02-02 18:13:33 +00:00
// Ensure the list doesn't exceed a/the maximum size.
nextState.splice(0, nextState.length - MAX_LIST_SIZE);
2018-01-17 11:19:10 +00:00
return nextState;
2018-01-17 11:19:10 +00:00
}
/**
* Updates the conference length when left.
*
2022-09-01 11:00:49 +00:00
* @param {IRecentListState} state - The redux state of the feature {@code recent-list}.
2018-01-17 11:19:10 +00:00
* @param {Object} action - The redux action.
* @returns {Object} The next redux state of the feature {@code recent-list}.
2018-01-17 11:19:10 +00:00
*/
function _updateConferenceDuration(state: IRecentListState, { locationURL }: { locationURL: { href: string; }; }) {
if (locationURL?.href && state.length) {
const mostRecentIndex = state.length - 1;
const mostRecent = state[mostRecentIndex];
if (_urlStringEquals(mostRecent.conference, locationURL.href)) {
// The last conference start was stored so we need to update the
// length.
const nextMostRecent = {
...mostRecent,
duration: Date.now() - mostRecent.date
};
2018-01-17 11:19:10 +00:00
// Shallow copy to avoid in-place modification.
const nextState = state.slice();
2018-01-17 11:19:10 +00:00
nextState[mostRecentIndex] = nextMostRecent;
2018-01-17 11:19:10 +00:00
return nextState;
2018-01-17 11:19:10 +00:00
}
}
return state;
}
/**
* Determines whether two specific URL {@code strings} are equal in the sense
* that they identify one and the same conference resource (irrespective of
* time) for the purposes of the feature {@code recent-list}.
*
* @param {string} a - The URL {@code string} to test for equality to {@code b}.
* @param {string} b - The URL {@code string} to test for equality to {@code a}.
* @returns {boolean}
*/
function _urlStringEquals(a: string, b: string) {
2018-04-04 19:54:42 +00:00
const aHref = getURLWithoutParamsNormalized(new URL(a));
const bHref = getURLWithoutParamsNormalized(new URL(b));
return aHref === bHref;
}