From cb973b61aa8e31242f7baced6b1bdd75da25db71 Mon Sep 17 00:00:00 2001 From: zbettenbuk Date: Wed, 14 Feb 2018 10:21:52 -0600 Subject: [PATCH] Implement adaptive known domain list --- react/features/calendar-sync/actionTypes.js | 5 ++ react/features/calendar-sync/actions.js | 22 ++++++- react/features/calendar-sync/middleware.js | 70 ++++++++++++--------- react/features/calendar-sync/reducer.js | 45 ++++++++++++- 4 files changed, 109 insertions(+), 33 deletions(-) diff --git a/react/features/calendar-sync/actionTypes.js b/react/features/calendar-sync/actionTypes.js index 4b99407410..5ba7708cdd 100644 --- a/react/features/calendar-sync/actionTypes.js +++ b/react/features/calendar-sync/actionTypes.js @@ -4,3 +4,8 @@ * Action to update the current calendar entry list in the store. */ export const NEW_CALENDAR_ENTRY_LIST = Symbol('NEW_CALENDAR_ENTRY_LIST'); + +/** + * Action to add a new known domain to the list. + */ +export const NEW_KNOWN_DOMAIN = Symbol('NEW_KNOWN_DOMAIN'); diff --git a/react/features/calendar-sync/actions.js b/react/features/calendar-sync/actions.js index 7a2c12700a..bff0b19ed4 100644 --- a/react/features/calendar-sync/actions.js +++ b/react/features/calendar-sync/actions.js @@ -1,13 +1,13 @@ // @flow -import { NEW_CALENDAR_ENTRY_LIST } from './actionTypes'; +import { NEW_CALENDAR_ENTRY_LIST, NEW_KNOWN_DOMAIN } from './actionTypes'; /** * Sends an action to update the current calendar list in redux. * * @param {Array} events - The new list. * @returns {{ - * type: NEW_CALENDAR_ENTRY_LIST, - * events: Array + * type: NEW_CALENDAR_ENTRY_LIST, + * events: Array * }} */ export function updateCalendarEntryList(events: Array) { @@ -16,3 +16,19 @@ export function updateCalendarEntryList(events: Array) { events }; } + +/** + * Sends an action to add a new known domain if not present yet. + * + * @param {string} domainName - The new domain. + * @returns {{ + * type: NEW_KNOWN_DOMAIN, + * domainName: string + * }} + */ +export function maybeAddNewKnownDomain(domainName: string) { + return { + type: NEW_KNOWN_DOMAIN, + domainName + }; +} diff --git a/react/features/calendar-sync/middleware.js b/react/features/calendar-sync/middleware.js index 82b3452747..c132a27cb9 100644 --- a/react/features/calendar-sync/middleware.js +++ b/react/features/calendar-sync/middleware.js @@ -2,29 +2,29 @@ import Logger from 'jitsi-meet-logger'; import RNCalendarEvents from 'react-native-calendar-events'; +import { SET_ROOM } from '../base/conference'; import { MiddlewareRegistry } from '../base/redux'; +import { parseURIString } from '../base/util'; import { APP_WILL_MOUNT } from '../app'; -import { updateCalendarEntryList } from './actions'; +import { maybeAddNewKnownDomain, updateCalendarEntryList } from './actions'; const FETCH_END_DAYS = 10; const FETCH_START_DAYS = -1; const MAX_LIST_LENGTH = 10; const logger = Logger.getLogger(__filename); -// this is to be dynamic later. -const domainList = [ - 'meet.jit.si', - 'beta.meet.jit.si' -]; - MiddlewareRegistry.register(store => next => action => { const result = next(action); switch (action.type) { case APP_WILL_MOUNT: + _ensureDefaultServer(store); _fetchCalendarEntries(store); + break; + case SET_ROOM: + _parseAndAddDomain(store); } return result; @@ -64,6 +64,22 @@ function _ensureCalendarAccess() { }); } +/** + * Ensures presence of the default server in the known domains list. + * + * @private + * @param {Object} store - The redux store. + * @returns {Promise} + */ +function _ensureDefaultServer(store) { + const state = store.getState(); + const defaultURL = parseURIString( + state['features/app'].app._getDefaultURL() + ); + + store.dispatch(maybeAddNewKnownDomain(defaultURL.host)); +} + /** * Reads the user's calendar and updates the stored entries if need be. * @@ -86,11 +102,12 @@ function _fetchCalendarEntries(store) { [] ) .then(events => { + const { knownDomains } = store.getState()['features/calendar-sync']; const eventList = []; if (events && events.length) { for (const event of events) { - const jitsiURL = _getURLFromEvent(event); + const jitsiURL = _getURLFromEvent(event, knownDomains); const now = Date.now(); if (jitsiURL) { @@ -117,24 +134,6 @@ function _fetchCalendarEntries(store) { } } - // TEST events to check notification popup. - // TODO: Remove this before a PR. - eventList.push({ - endDate: Date.now() + (60 * 60 * 1000), - id: -1, - startDate: Date.now() + (80 * 1000), - title: 'ShipIt 41', - url: 'https://meet.jit.si/shipit41' - }); - - eventList.push({ - endDate: Date.now() + (2 * 60 * 60 * 1000), - id: -2, - startDate: Date.now() + (60 * 60 * 1000), - title: 'ShipIt 41 demo', - url: 'https://meet.jit.si/shipit41' - }); - store.dispatch(updateCalendarEntryList(eventList.sort((a, b) => a.startDate - b.startDate ).slice(0, MAX_LIST_LENGTH))); @@ -153,12 +152,13 @@ function _fetchCalendarEntries(store) { * * @private * @param {Object} event - The event to parse. + * @param {Array} knownDomains - The known domain names. * @returns {string} * */ -function _getURLFromEvent(event) { +function _getURLFromEvent(event, knownDomains) { const urlRegExp - = new RegExp(`http(s)?://(${domainList.join('|')})/[^\\s<>$]+`, 'gi'); + = new RegExp(`http(s)?://(${knownDomains.join('|')})/[^\\s<>$]+`, 'gi'); const fieldsToSearch = [ event.title, event.url, @@ -180,3 +180,17 @@ function _getURLFromEvent(event) { return null; } + +/** + * Retreives the domain name of a room upon join and stores it + * in the known domain list, if not present yet. + * + * @private + * @param {Object} store - The redux store. + * @returns {Promise} + */ +function _parseAndAddDomain(store) { + const { locationURL } = store.getState()['features/base/connection']; + + store.dispatch(maybeAddNewKnownDomain(locationURL.host)); +} diff --git a/react/features/calendar-sync/reducer.js b/react/features/calendar-sync/reducer.js index 5c99378923..17a946bce6 100644 --- a/react/features/calendar-sync/reducer.js +++ b/react/features/calendar-sync/reducer.js @@ -1,28 +1,69 @@ // @flow import { ReducerRegistry } from '../base/redux'; +import { PersistenceRegistry } from '../base/storage'; -import { NEW_CALENDAR_ENTRY_LIST } from './actionTypes'; +import { NEW_CALENDAR_ENTRY_LIST, NEW_KNOWN_DOMAIN } from './actionTypes'; /** * ZB: this is an object, as further data is to come here, like: * - known domain list */ const DEFAULT_STATE = { - events: [] + events: [], + knownDomains: [] }; + +const MAX_DOMAIN_LIST_SIZE = 10; + const STORE_NAME = 'features/calendar-sync'; +PersistenceRegistry.register(STORE_NAME, { + knownDomains: true +}); + ReducerRegistry.register( STORE_NAME, (state = DEFAULT_STATE, action) => { switch (action.type) { case NEW_CALENDAR_ENTRY_LIST: return { + ...state, events: action.events }; + case NEW_KNOWN_DOMAIN: + return _maybeAddNewDomain(state, action); + default: return state; } }); + +/** + * Adds a new domain to the known domain list if not present yet. + * + * @private + * @param {Object} state - The redux state. + * @param {Object} action - The redux action. + * @returns {Object} + */ +function _maybeAddNewDomain(state, action) { + let { domainName } = action; + const { knownDomains } = state; + + if (domainName && domainName.length) { + domainName = domainName.toLowerCase(); + if (knownDomains.indexOf(domainName) === -1) { + knownDomains.push(domainName); + + // Ensure the list doesn't exceed a/the maximum size. + knownDomains.splice(0, knownDomains.length - MAX_DOMAIN_LIST_SIZE); + } + } + + return { + ...state, + knownDomains + }; +}