snapshot of https://github.com/jitsi/jitsi-meet.git @ fd1749dd28f4138aa80234fc7f311b19aaffa0e7 (2026-09-15)
This commit is contained in:
29
react/features/client-requirements/functions.native.ts
Normal file
29
react/features/client-requirements/functions.native.ts
Normal file
@@ -0,0 +1,29 @@
|
||||
import { BUTTON_TYPES } from '../base/ui/constants.native';
|
||||
import { openURLInBrowser } from '../base/util/openURLInBrowser';
|
||||
import { INotificationProps } from '../notifications/types';
|
||||
|
||||
/**
|
||||
* Builds the description of a notification about missing capabilities. A URL is shown as a button, because the native
|
||||
* notification renders text only, and we do not want to show a URL to the user.
|
||||
*
|
||||
* @param {string} text - The text which describes the missing capabilities.
|
||||
* @param {string|undefined} url - A URL with more information, if the server sent one.
|
||||
* @param {Function} _t - The translation function. Not needed here, the button uses a translation key.
|
||||
* @returns {Object} The description properties of the notification.
|
||||
*/
|
||||
export function getDescriptionProps(text: string, url: string | undefined, _t: Function): INotificationProps {
|
||||
if (!url) {
|
||||
return { description: text };
|
||||
}
|
||||
|
||||
return {
|
||||
customActionHandler: [ () => {
|
||||
openURLInBrowser(url);
|
||||
|
||||
return false;
|
||||
} ],
|
||||
customActionNameKey: [ 'clientRequirements.seeDetails' ],
|
||||
customActionType: [ BUTTON_TYPES.PRIMARY ],
|
||||
description: text
|
||||
};
|
||||
}
|
||||
32
react/features/client-requirements/functions.web.tsx
Normal file
32
react/features/client-requirements/functions.web.tsx
Normal file
@@ -0,0 +1,32 @@
|
||||
import React from 'react';
|
||||
|
||||
import { INotificationProps } from '../notifications/types';
|
||||
|
||||
/**
|
||||
* Builds the description of a notification about missing capabilities. The link is rendered around a part of the
|
||||
* text, so that no URL is shown to the user.
|
||||
*
|
||||
* @param {string} text - The text which describes the missing capabilities.
|
||||
* @param {string|undefined} url - A URL with more information, if the server sent one.
|
||||
* @param {Function} t - The translation function.
|
||||
* @returns {Object} The description properties of the notification.
|
||||
*/
|
||||
export function getDescriptionProps(text: string, url: string | undefined, t: Function): INotificationProps {
|
||||
if (!url) {
|
||||
return { description: text };
|
||||
}
|
||||
|
||||
return {
|
||||
description: (
|
||||
<span>
|
||||
{ `${text} ` }
|
||||
<a
|
||||
href = { url }
|
||||
rel = 'noopener noreferrer'
|
||||
target = '_blank'>
|
||||
{ t('clientRequirements.seeDetails') }
|
||||
</a>
|
||||
</span>
|
||||
)
|
||||
};
|
||||
}
|
||||
3
react/features/client-requirements/logger.ts
Normal file
3
react/features/client-requirements/logger.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import { getLogger } from '../base/logging/functions';
|
||||
|
||||
export default getLogger('app:clientRequirements');
|
||||
93
react/features/client-requirements/middleware.ts
Normal file
93
react/features/client-requirements/middleware.ts
Normal file
@@ -0,0 +1,93 @@
|
||||
import i18n from 'i18next';
|
||||
|
||||
import { IStore } from '../app/types';
|
||||
import { CONFERENCE_JOINED } from '../base/conference/actionTypes';
|
||||
import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
|
||||
import MiddlewareRegistry from '../base/redux/MiddlewareRegistry';
|
||||
import { showErrorNotification, showWarningNotification } from '../notifications/actions';
|
||||
import { NOTIFICATION_TIMEOUT_TYPE } from '../notifications/constants';
|
||||
|
||||
import { getDescriptionProps } from './functions';
|
||||
import logger from './logger';
|
||||
import { IClientRequirements, IMissingFeature } from './types';
|
||||
|
||||
/**
|
||||
* Middleware that handles the server signaling that this client does not advertise capabilities that the deployment
|
||||
* requires.
|
||||
*
|
||||
* @param {IStore} store - The redux store.
|
||||
* @returns {Function}
|
||||
*/
|
||||
MiddlewareRegistry.register((store: IStore) => (next: Function) => (action: any) => {
|
||||
switch (action.type) {
|
||||
case CONFERENCE_JOINED: {
|
||||
action.conference.on(
|
||||
JitsiConferenceEvents.CLIENT_REQUIREMENTS_NOT_MET,
|
||||
(requirements: IClientRequirements) => _onClientRequirements(store, requirements));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return next(action);
|
||||
});
|
||||
|
||||
/**
|
||||
* Describes a missing capability to the user. Uses a translation for the capability if this client has one, and
|
||||
* otherwise the description that the server sent.
|
||||
*
|
||||
* @param {IMissingFeature} missingFeature - The missing capability.
|
||||
* @returns {string}
|
||||
*/
|
||||
function _getFeatureText(missingFeature: IMissingFeature): string {
|
||||
const key = `clientRequirements.features.${missingFeature.name}`;
|
||||
|
||||
if (missingFeature.name && i18n.exists(key)) {
|
||||
return i18n.t(key);
|
||||
}
|
||||
|
||||
return missingFeature.details ?? missingFeature.name ?? missingFeature.feature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifies the user that this client does not advertise capabilities that the deployment requires.
|
||||
*
|
||||
* @param {IStore} store - The redux store.
|
||||
* @param {IClientRequirements} requirements - The capabilities that the client is missing, and what the server did
|
||||
* about it.
|
||||
* @returns {void}
|
||||
*/
|
||||
function _onClientRequirements({ dispatch, getState }: IStore, requirements: IClientRequirements) {
|
||||
const { action, features } = requirements;
|
||||
|
||||
if (!features?.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
logger.warn(`This client is missing required capabilities (action=${action}): `
|
||||
+ `${features.map(f => f.name ?? f.feature).join(', ')}`);
|
||||
|
||||
const isReject = action === 'reject';
|
||||
|
||||
if (!isReject && getState()['features/base/config'].hideMissingCapabilityWarnings) {
|
||||
return;
|
||||
}
|
||||
|
||||
const descriptionKey = isReject ? 'clientRequirements.rejectDescription' : 'clientRequirements.warnDescription';
|
||||
const text = [ i18n.t(descriptionKey) ].concat(features.map(_getFeatureText)).join(' ');
|
||||
|
||||
// The first URL that the server sent, if any.
|
||||
const url = features.find(feature => feature.url)?.url;
|
||||
const notification = {
|
||||
...getDescriptionProps(text, url, i18n.t.bind(i18n)),
|
||||
hideErrorSupportLink: true,
|
||||
titleKey: isReject ? 'clientRequirements.rejectTitle' : 'clientRequirements.warnTitle'
|
||||
};
|
||||
|
||||
if (isReject) {
|
||||
// We are not in the conference and can not send or receive media. Show this even if warnings are hidden.
|
||||
dispatch(showErrorNotification(notification, NOTIFICATION_TIMEOUT_TYPE.STICKY));
|
||||
} else {
|
||||
dispatch(showWarningNotification(notification, NOTIFICATION_TIMEOUT_TYPE.LONG));
|
||||
}
|
||||
}
|
||||
46
react/features/client-requirements/types.ts
Normal file
46
react/features/client-requirements/types.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* A capability that this client does not advertise, but the deployment requires.
|
||||
*/
|
||||
export interface IMissingFeature {
|
||||
|
||||
/**
|
||||
* Text (in English) from the server, which describes how to add support for the capability.
|
||||
*/
|
||||
details?: string;
|
||||
|
||||
/**
|
||||
* The XMPP feature (the disco#info "var"), e.g. "http://jitsi.org/ssrc-rewriting-1".
|
||||
*/
|
||||
feature: string;
|
||||
|
||||
/**
|
||||
* How severe the missing capability is. With 'hard' the client is not invited to the conference.
|
||||
*/
|
||||
level: string;
|
||||
|
||||
/**
|
||||
* A stable symbolic name for the capability, e.g. "SSRC_REWRITING_V1". Used as a translation key.
|
||||
*/
|
||||
name?: string;
|
||||
|
||||
/**
|
||||
* A URL with more information.
|
||||
*/
|
||||
url?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* The capabilities that this client is missing, and what the server did about it.
|
||||
*/
|
||||
export interface IClientRequirements {
|
||||
|
||||
/**
|
||||
* Either 'reject' (this client is not invited to the conference, i.e. it can not send or receive media) or 'warn'.
|
||||
*/
|
||||
action: string;
|
||||
|
||||
/**
|
||||
* The capabilities that this client does not advertise.
|
||||
*/
|
||||
features: IMissingFeature[];
|
||||
}
|
||||
Reference in New Issue
Block a user