fix(branding): Fix dynamic logo display
* Display of the logo has been reworked (simplified). * The logo will not be displayed if the call to `branding` endpoint fails. * Add more docs.
This commit is contained in:
parent
ed6e75b241
commit
d2ec0ea6f3
|
@ -24,35 +24,19 @@ const _RIGHT_WATERMARK_STYLE = {
|
|||
type Props = {
|
||||
|
||||
/**
|
||||
* The user selected url used to navigate to on logo click.
|
||||
* The link used to navigate to on logo click.
|
||||
*/
|
||||
_customLogoLink: string,
|
||||
_logoLink: string,
|
||||
|
||||
/**
|
||||
* The url of the user selected logo.
|
||||
* The url for the logo.
|
||||
*/
|
||||
_customLogoUrl: string,
|
||||
_logoUrl: string,
|
||||
|
||||
/**
|
||||
* Whether or not the current user is logged in through a JWT.
|
||||
* If the Jitsi watermark should be displayed or not.
|
||||
*/
|
||||
_isGuest: boolean,
|
||||
|
||||
/**
|
||||
* Whether or not the current meeting is a vpaas one.
|
||||
*/
|
||||
_isVpaas: boolean,
|
||||
|
||||
/**
|
||||
* Flag used to signal that the logo can be displayed.
|
||||
* It becomes true after the user customization options are fetched.
|
||||
*/
|
||||
_readyToDisplayJitsiWatermark: boolean,
|
||||
|
||||
/**
|
||||
* Returns true if welcome page is visible at the moment.
|
||||
*/
|
||||
_welcomePageIsVisible: boolean,
|
||||
_showJitsiWatermark: boolean,
|
||||
|
||||
/**
|
||||
* The default value for the Jitsi logo URL.
|
||||
|
@ -75,27 +59,11 @@ type State = {
|
|||
*/
|
||||
brandWatermarkLink: string,
|
||||
|
||||
/**
|
||||
* The url to open when clicking the Jitsi watermark.
|
||||
*/
|
||||
jitsiWatermarkLink: string,
|
||||
|
||||
/**
|
||||
* Whether or not the brand watermark should be displayed.
|
||||
*/
|
||||
showBrandWatermark: boolean,
|
||||
|
||||
/**
|
||||
* Whether or not the Jitsi watermark should be displayed.
|
||||
*/
|
||||
showJitsiWatermark: boolean,
|
||||
|
||||
/**
|
||||
* Whether or not the Jitsi watermark should be displayed for users not
|
||||
* logged in through a JWT.
|
||||
*/
|
||||
showJitsiWatermarkForGuests: boolean,
|
||||
|
||||
/**
|
||||
* Whether or not the show the "powered by Jitsi.org" link.
|
||||
*/
|
||||
|
@ -117,29 +85,17 @@ class Watermarks extends Component<Props, State> {
|
|||
super(props);
|
||||
|
||||
let showBrandWatermark;
|
||||
let showJitsiWatermark;
|
||||
let showJitsiWatermarkForGuests;
|
||||
|
||||
if (interfaceConfig.filmStripOnly) {
|
||||
showBrandWatermark = false;
|
||||
showJitsiWatermark = false;
|
||||
showJitsiWatermarkForGuests = false;
|
||||
} else {
|
||||
showBrandWatermark = interfaceConfig.SHOW_BRAND_WATERMARK;
|
||||
showJitsiWatermark = interfaceConfig.SHOW_JITSI_WATERMARK;
|
||||
showJitsiWatermarkForGuests
|
||||
= interfaceConfig.SHOW_WATERMARK_FOR_GUESTS;
|
||||
}
|
||||
|
||||
this.state = {
|
||||
brandWatermarkLink:
|
||||
showBrandWatermark ? interfaceConfig.BRAND_WATERMARK_LINK : '',
|
||||
jitsiWatermarkLink:
|
||||
showJitsiWatermark || showJitsiWatermarkForGuests
|
||||
? interfaceConfig.JITSI_WATERMARK_LINK : '',
|
||||
showBrandWatermark,
|
||||
showJitsiWatermark,
|
||||
showJitsiWatermarkForGuests,
|
||||
showPoweredBy: interfaceConfig.SHOW_POWERED_BY
|
||||
};
|
||||
}
|
||||
|
@ -166,55 +122,6 @@ class Watermarks extends Component<Props, State> {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the watermark is ready to be displayed.
|
||||
*
|
||||
* @private
|
||||
* @returns {boolean}
|
||||
*/
|
||||
_canDisplayJitsiWatermark() {
|
||||
const {
|
||||
showJitsiWatermark,
|
||||
showJitsiWatermarkForGuests
|
||||
} = this.state;
|
||||
const {
|
||||
_isGuest,
|
||||
_readyToDisplayJitsiWatermark,
|
||||
_welcomePageIsVisible
|
||||
} = this.props;
|
||||
|
||||
return (_readyToDisplayJitsiWatermark
|
||||
&& (showJitsiWatermark || (_isGuest && showJitsiWatermarkForGuests)))
|
||||
|| _welcomePageIsVisible;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the background image style.
|
||||
*
|
||||
* @private
|
||||
* @returns {string}
|
||||
*/
|
||||
_getBackgroundImageStyle() {
|
||||
const {
|
||||
_customLogoUrl,
|
||||
_isVpaas,
|
||||
defaultJitsiLogoURL
|
||||
} = this.props;
|
||||
let style = 'none';
|
||||
|
||||
if (_isVpaas) {
|
||||
if (_customLogoUrl) {
|
||||
style = `url(${_customLogoUrl})`;
|
||||
}
|
||||
} else {
|
||||
style = `url(${_customLogoUrl
|
||||
|| defaultJitsiLogoURL
|
||||
|| interfaceConfig.DEFAULT_LOGO_URL})`;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a brand watermark if it is enabled.
|
||||
*
|
||||
|
@ -254,33 +161,28 @@ class Watermarks extends Component<Props, State> {
|
|||
* @returns {ReactElement|null}
|
||||
*/
|
||||
_renderJitsiWatermark() {
|
||||
const {
|
||||
_logoLink,
|
||||
_logoUrl,
|
||||
_showJitsiWatermark
|
||||
} = this.props;
|
||||
let reactElement = null;
|
||||
|
||||
if (this._canDisplayJitsiWatermark()) {
|
||||
const backgroundImage = this._getBackgroundImageStyle();
|
||||
const link = this.props._customLogoLink || this.state.jitsiWatermarkLink;
|
||||
const additionalStyles = {};
|
||||
|
||||
if (backgroundImage === 'none') {
|
||||
additionalStyles.height = 0;
|
||||
additionalStyles.width = 0;
|
||||
}
|
||||
|
||||
if (_showJitsiWatermark) {
|
||||
const style = {
|
||||
backgroundImage,
|
||||
backgroundImage: `url(${_logoUrl})`,
|
||||
maxWidth: 140,
|
||||
maxHeight: 70,
|
||||
...additionalStyles
|
||||
maxHeight: 70
|
||||
};
|
||||
|
||||
reactElement = (<div
|
||||
className = 'watermark leftwatermark'
|
||||
style = { style } />);
|
||||
|
||||
if (link) {
|
||||
if (_logoLink) {
|
||||
reactElement = (
|
||||
<a
|
||||
href = { link }
|
||||
href = { _logoLink }
|
||||
target = '_new'>
|
||||
{ reactElement }
|
||||
</a>
|
||||
|
@ -319,27 +221,52 @@ class Watermarks extends Component<Props, State> {
|
|||
* Maps parts of Redux store to component prop types.
|
||||
*
|
||||
* @param {Object} state - Snapshot of Redux store.
|
||||
* @param {Object} ownProps - Component's own props.
|
||||
* @returns {Props}
|
||||
*/
|
||||
function _mapStateToProps(state) {
|
||||
function _mapStateToProps(state, ownProps) {
|
||||
const { isGuest } = state['features/base/jwt'];
|
||||
const { customizationReady, logoClickUrl, logoImageUrl } = state['features/dynamic-branding'];
|
||||
const { room } = state['features/base/conference'];
|
||||
const {
|
||||
customizationReady,
|
||||
customizationFailed,
|
||||
defaultBranding,
|
||||
useDynamicBrandingData,
|
||||
logoClickUrl,
|
||||
logoImageUrl
|
||||
} = state['features/dynamic-branding'];
|
||||
const isValidRoom = state['features/base/conference'].room;
|
||||
const {
|
||||
DEFAULT_LOGO_URL,
|
||||
JITSI_WATERMARK_LINK,
|
||||
SHOW_JITSI_WATERMARK,
|
||||
SHOW_JITSI_WATERMARK_FOR_GUESTS,
|
||||
filmStripOnly
|
||||
} = interfaceConfig;
|
||||
let _showJitsiWatermark = (!filmStripOnly
|
||||
&& (customizationReady && !customizationFailed)
|
||||
&& (SHOW_JITSI_WATERMARK || (isGuest && SHOW_JITSI_WATERMARK_FOR_GUESTS)))
|
||||
|| !isValidRoom;
|
||||
let _logoUrl = logoImageUrl;
|
||||
let _logoLink = logoClickUrl;
|
||||
|
||||
if (useDynamicBrandingData) {
|
||||
if (isVpaasMeeting(state)) {
|
||||
// don't show logo if request fails or no logo set for vpaas meetings
|
||||
_showJitsiWatermark = !customizationFailed && Boolean(logoImageUrl);
|
||||
} else if (defaultBranding) {
|
||||
_logoUrl = DEFAULT_LOGO_URL;
|
||||
_logoLink = JITSI_WATERMARK_LINK;
|
||||
}
|
||||
} else {
|
||||
// When there is no custom branding data use defaults
|
||||
_logoUrl = ownProps.defaultJitsiLogoURL || DEFAULT_LOGO_URL;
|
||||
_logoLink = JITSI_WATERMARK_LINK;
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* The indicator which determines whether the local participant is a
|
||||
* guest in the conference.
|
||||
*
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
_customLogoLink: logoClickUrl,
|
||||
_customLogoUrl: logoImageUrl,
|
||||
_isGuest: isGuest,
|
||||
_isVpaas: isVpaasMeeting(state),
|
||||
_readyToDisplayJitsiWatermark: customizationReady,
|
||||
_welcomePageIsVisible: !room
|
||||
_logoLink,
|
||||
_logoUrl,
|
||||
_showJitsiWatermark
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,11 @@
|
|||
*/
|
||||
export const SET_DYNAMIC_BRANDING_DATA = 'SET_DYNAMIC_BRANDING_DATA';
|
||||
|
||||
/**
|
||||
* Action used to signal the customization failed.
|
||||
*/
|
||||
export const SET_DYNAMIC_BRANDING_FAILED = 'SET_DYNAMIC_BRANDING_FAILED';
|
||||
|
||||
/**
|
||||
* Action used to signal the branding elements are ready to be displayed
|
||||
*/
|
||||
|
|
|
@ -4,7 +4,11 @@ import { getLogger } from 'jitsi-meet-logger';
|
|||
|
||||
import { doGetJSON } from '../base/util';
|
||||
|
||||
import { SET_DYNAMIC_BRANDING_DATA, SET_DYNAMIC_BRANDING_READY } from './actionTypes';
|
||||
import {
|
||||
SET_DYNAMIC_BRANDING_DATA,
|
||||
SET_DYNAMIC_BRANDING_FAILED,
|
||||
SET_DYNAMIC_BRANDING_READY
|
||||
} from './actionTypes';
|
||||
import { extractFqnFromPath } from './functions';
|
||||
|
||||
const logger = getLogger(__filename);
|
||||
|
@ -32,6 +36,8 @@ export function fetchCustomBrandingData() {
|
|||
return dispatch(setDynamicBrandingData(res));
|
||||
} catch (err) {
|
||||
logger.error('Error fetching branding data', err);
|
||||
|
||||
return dispatch(setDynamicBrandingFailed());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -63,3 +69,14 @@ function setDynamicBrandingReady() {
|
|||
type: SET_DYNAMIC_BRANDING_READY
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Action used to signal the branding request failed.
|
||||
*
|
||||
* @returns {Object}
|
||||
*/
|
||||
function setDynamicBrandingFailed() {
|
||||
return {
|
||||
type: SET_DYNAMIC_BRANDING_FAILED
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,7 +2,11 @@
|
|||
|
||||
import { ReducerRegistry } from '../base/redux';
|
||||
|
||||
import { SET_DYNAMIC_BRANDING_DATA, SET_DYNAMIC_BRANDING_READY } from './actionTypes';
|
||||
import {
|
||||
SET_DYNAMIC_BRANDING_DATA,
|
||||
SET_DYNAMIC_BRANDING_FAILED,
|
||||
SET_DYNAMIC_BRANDING_READY
|
||||
} from './actionTypes';
|
||||
|
||||
/**
|
||||
* The name of the redux store/state property which is the root of the redux
|
||||
|
@ -11,12 +15,80 @@ import { SET_DYNAMIC_BRANDING_DATA, SET_DYNAMIC_BRANDING_READY } from './actionT
|
|||
const STORE_NAME = 'features/dynamic-branding';
|
||||
|
||||
const DEFAULT_STATE = {
|
||||
/**
|
||||
* The custom background color for the LargeVideo.
|
||||
*
|
||||
* @public
|
||||
* @type {string}
|
||||
*/
|
||||
backgroundColor: '',
|
||||
|
||||
/**
|
||||
* The custom background image used on the LargeVideo.
|
||||
*
|
||||
* @public
|
||||
* @type {string}
|
||||
*/
|
||||
backgroundImageUrl: '',
|
||||
|
||||
/**
|
||||
* Flag indicating that the logo (JitsiWatermark) can be displayed.
|
||||
* This is used in order to avoid image flickering.
|
||||
*
|
||||
* @public
|
||||
* @type {boolean}
|
||||
*/
|
||||
customizationReady: false,
|
||||
|
||||
/**
|
||||
* Flag indicating that the dynamic branding data request has failed.
|
||||
* When the request fails there is no logo (JitsiWatermark) displayed.
|
||||
*
|
||||
* @public
|
||||
* @type {boolean}
|
||||
*/
|
||||
customizationFailed: false,
|
||||
|
||||
/**
|
||||
* Flag indicating that the dynamic branding has not been modified and should use
|
||||
* the default options.
|
||||
*
|
||||
* @public
|
||||
* @type {boolean}
|
||||
*/
|
||||
defaultBranding: true,
|
||||
|
||||
/**
|
||||
* The custom invite domain.
|
||||
*
|
||||
* @public
|
||||
* @type {string}
|
||||
*/
|
||||
inviteDomain: '',
|
||||
|
||||
/**
|
||||
* The custom url used when the user clicks the logo.
|
||||
*
|
||||
* @public
|
||||
* @type {string}
|
||||
*/
|
||||
logoClickUrl: '',
|
||||
logoImageUrl: ''
|
||||
|
||||
/**
|
||||
* The custom logo (JitisWatermark).
|
||||
*
|
||||
* @public
|
||||
* @type {string}
|
||||
*/
|
||||
logoImageUrl: '',
|
||||
|
||||
/**
|
||||
* Flag used to signal if the app should use a custom logo or not
|
||||
*
|
||||
* @public
|
||||
* @type {boolean}
|
||||
*/
|
||||
useDynamicBrandingData: false
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -25,15 +97,33 @@ const DEFAULT_STATE = {
|
|||
ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
|
||||
switch (action.type) {
|
||||
case SET_DYNAMIC_BRANDING_DATA: {
|
||||
const { backgroundColor, backgroundImageUrl, inviteDomain, logoClickUrl, logoImageUrl } = action.value;
|
||||
const {
|
||||
backgroundColor,
|
||||
backgroundImageUrl,
|
||||
defaultBranding,
|
||||
inviteDomain,
|
||||
logoClickUrl,
|
||||
logoImageUrl
|
||||
} = action.value;
|
||||
|
||||
return {
|
||||
backgroundColor,
|
||||
backgroundImageUrl,
|
||||
defaultBranding,
|
||||
inviteDomain,
|
||||
logoClickUrl,
|
||||
logoImageUrl,
|
||||
customizationReady: true
|
||||
customizationFailed: false,
|
||||
customizationReady: true,
|
||||
useDynamicBrandingData: true
|
||||
};
|
||||
}
|
||||
case SET_DYNAMIC_BRANDING_FAILED: {
|
||||
return {
|
||||
...state,
|
||||
customizationReady: true,
|
||||
customizationFailed: true,
|
||||
useDynamicBrandingData: true
|
||||
};
|
||||
}
|
||||
case SET_DYNAMIC_BRANDING_READY:
|
||||
|
@ -41,7 +131,6 @@ ReducerRegistry.register(STORE_NAME, (state = DEFAULT_STATE, action) => {
|
|||
...state,
|
||||
customizationReady: true
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
return state;
|
||||
|
|
Loading…
Reference in New Issue