Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(dynamic-branding): Add config options that represent URLs. #15364

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions react/features/base/premeeting/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -254,8 +254,9 @@ export function getConnectionData(state: IReduxState) {
*/
export function isPreCallTestEnabled(state: IReduxState): boolean {
const { prejoinConfig } = state['features/base/config'];
const { preCallTest } = state['features/dynamic-branding'];

return prejoinConfig?.preCallTestEnabled ?? false;
return preCallTest?.enabled ?? prejoinConfig?.preCallTestEnabled ?? false;
}

/**
Expand All @@ -266,6 +267,7 @@ export function isPreCallTestEnabled(state: IReduxState): boolean {
*/
export function getPreCallICEUrl(state: IReduxState): string | undefined {
const { prejoinConfig } = state['features/base/config'];
const { preCallTest } = state['features/dynamic-branding'];

return prejoinConfig?.preCallTestICEUrl;
return preCallTest?.iceUrl || prejoinConfig?.preCallTestICEUrl;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use ?? everywhere. It makes sense because it won't fall trough if the chosen value is false for example.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My worry is that ?? won't catch the '' value and we tend to return '' in the backend service if the value is missing. Of course we can change the backend service and actually there is an effort in the direction to return only what the client have set but even then I don't think it is a bad thing to guarded for ''.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If that's the case it might be better to filter the empty strings when we parse the backend response so we don't need to do check everywhere no?

}
12 changes: 10 additions & 2 deletions react/features/dynamic-branding/middleware.native.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,14 @@ MiddlewareRegistry.register(store => next => action => {
backgroundImageUrl,
brandedIcons,
didPageUrl,
downloadAppsUrl,
inviteDomain,
labels,
liveStreamingDialogUrls,
salesforceUrl,
sharedVideoAllowedURLDomains,
supportUrl
supportUrl,
userDocumentationUrl
} = action.value;

action.value = {
Expand All @@ -35,10 +39,14 @@ MiddlewareRegistry.register(store => next => action => {
backgroundImageUrl,
brandedIcons,
didPageUrl,
downloadAppsUrl,
inviteDomain,
labels,
liveStreamingDialogUrls,
salesforceUrl,
sharedVideoAllowedURLDomains,
supportUrl
supportUrl,
userDocumentationUrl
};

// The backend may send an empty string, make sure we skip that.
Expand Down
22 changes: 22 additions & 0 deletions react/features/dynamic-branding/reducer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,16 +152,28 @@ export interface IDynamicBrandingState {
defaultBranding: boolean;
defaultTranscriptionLanguage?: boolean;
didPageUrl: string;
downloadAppsUrl?: string;
inviteDomain: string;
labels: Object | null;
liveStreamingDialogUrls?: {
dataPrivacyUrl?: string;
helpUrl?: string;
termsUrl?: string;
};
logoClickUrl: string;
logoImageUrl: string;
muiBrandedTheme?: boolean;
preCallTest?: {
enabled?: boolean;
iceUrl?: string;
};
premeetingBackground: string;
salesforceUrl?: string;
sharedVideoAllowedURLDomains?: Array<string>;
showGiphyIntegration?: boolean;
supportUrl?: string;
useDynamicBrandingData: boolean;
userDocumentationUrl?: string;
virtualBackgrounds: Array<Image>;
}

Expand All @@ -178,15 +190,20 @@ ReducerRegistry.register<IDynamicBrandingState>(STORE_NAME, (state = DEFAULT_STA
brandedIcons,
defaultBranding,
didPageUrl,
downloadAppsUrl,
inviteDomain,
labels,
liveStreamingDialogUrls,
logoClickUrl,
logoImageUrl,
muiBrandedTheme,
preCallTest,
premeetingBackground,
salesforceUrl,
sharedVideoAllowedURLDomains,
showGiphyIntegration,
supportUrl,
userDocumentationUrl,
virtualBackgrounds
} = action.value;

Expand All @@ -197,18 +214,23 @@ ReducerRegistry.register<IDynamicBrandingState>(STORE_NAME, (state = DEFAULT_STA
brandedIcons,
defaultBranding,
didPageUrl,
downloadAppsUrl,
inviteDomain,
labels,
liveStreamingDialogUrls,
logoClickUrl,
logoImageUrl,
muiBrandedTheme,
preCallTest,
premeetingBackground,
salesforceUrl,
sharedVideoAllowedURLDomains,
showGiphyIntegration,
supportUrl,
customizationFailed: false,
customizationReady: true,
useDynamicBrandingData: true,
userDocumentationUrl,
virtualBackgrounds: formatImages(virtualBackgrounds || [])
};
}
Expand Down
11 changes: 8 additions & 3 deletions react/features/recording/components/LiveStream/functions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,18 @@ import {
*/
export function getLiveStreaming(state: IReduxState) {
const { liveStreaming = {} } = state['features/base/config'];
const { liveStreamingDialogUrls = {} } = state['features/dynamic-branding'];
const regexp = liveStreaming.validatorRegExpString && new RegExp(liveStreaming.validatorRegExpString);

return {
enabled: Boolean(liveStreaming.enabled),
helpURL: sanitizeUrl(liveStreaming.helpLink || JITSI_LIVE_STREAMING_HELP_LINK)?.toString(),
termsURL: sanitizeUrl(liveStreaming.termsLink || YOUTUBE_TERMS_URL)?.toString(),
dataPrivacyURL: sanitizeUrl(liveStreaming.dataPrivacyLink || GOOGLE_PRIVACY_POLICY)?.toString(),
helpURL: sanitizeUrl(
liveStreamingDialogUrls.helpUrl || liveStreaming.helpLink || JITSI_LIVE_STREAMING_HELP_LINK)?.toString(),
termsURL: sanitizeUrl(
liveStreamingDialogUrls.termsUrl || liveStreaming.termsLink || YOUTUBE_TERMS_URL)?.toString(),
dataPrivacyURL: sanitizeUrl(
liveStreamingDialogUrls.dataPrivacyUrl || liveStreaming.dataPrivacyLink || GOOGLE_PRIVACY_POLICY
)?.toString(),
streamLinkRegexp: regexp || FOUR_GROUPS_DASH_SEPARATED
};
}
20 changes: 17 additions & 3 deletions react/features/salesforce/functions.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { IReduxState } from '../app/types';
import { IStateful } from '../base/app/types';
import { toState } from '../base/redux/functions';
import { doGetJSON } from '../base/util/httpUtils';
import { isInBreakoutRoom } from '../breakout-rooms/functions';

Expand All @@ -9,12 +11,24 @@ import { isInBreakoutRoom } from '../breakout-rooms/functions';
* {@code getState} function, or the redux state itself.
* @returns {boolean}
*/
export const isSalesforceEnabled = (state: IReduxState) => {
const { salesforceUrl } = state['features/base/config'];
export function isSalesforceEnabled(state: IReduxState) {
const salesforceUrl = getSalesforceUrl(state);
const isBreakoutRoom = isInBreakoutRoom(state);

return Boolean(salesforceUrl) && !isBreakoutRoom;
};
}

/**
* Returns the salesforce integration URL.
*
* @param {Function|Object} stateful - The redux store or {@code getState} function.
* @returns {URL} - The salesforce integration URL.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retusns a string.

*/
export function getSalesforceUrl(stateful: IStateful) {
const state = toState(stateful);

return state['features/dynamic-branding'].salesforceUrl || state['features/base/config'].salesforceUrl;
}

/**
* Fetches the Salesforce records that were most recently interacted with.
Expand Down
3 changes: 2 additions & 1 deletion react/features/salesforce/useSalesforceLinkDialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
import {
executeLinkMeetingRequest,
getRecentSessionRecords,
getSalesforceUrl,
getSessionRecordDetails,
searchSessionRecords
} from './functions';
Expand All @@ -40,7 +41,7 @@ export const useSalesforceLinkDialog = () => {
const [ hasDetailsErrors, setDetailsErrors ] = useState(false);
const conference = useSelector(getCurrentConference);
const sessionId = conference?.getMeetingUniqueId();
const { salesforceUrl = '' } = useSelector((state: IReduxState) => state['features/base/config']);
const salesforceUrl = useSelector((state: IReduxState) => getSalesforceUrl(state) ?? '');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const salesforceUrl = useSelector((state: IReduxState) => getSalesforceUrl(state) ?? '');
const salesforceUrl = useSelector(getSalesforceUrl);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need a default value here? Make getSalesforceUrl always return a string then?

const { jwt = '' } = useSelector((state: IReduxState) => state['features/base/jwt']);
const showSearchResults = searchTerm && searchTerm.length > 1;
const showNoResults = showSearchResults && records.length === 0;
Expand Down
3 changes: 2 additions & 1 deletion react/features/toolbox/components/DownloadButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { translate } from '../../base/i18n/functions';
import { IconDownload } from '../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../base/toolbox/components/AbstractButton';
import { openURLInBrowser } from '../../base/util/openURLInBrowser';
import { getDownloadAppsUrl } from '../functions.any';

interface IProps extends AbstractButtonProps {

Expand Down Expand Up @@ -47,7 +48,7 @@ class DownloadButton extends AbstractButton<IProps> {
* @returns {Object}
*/
function _mapStateToProps(state: IReduxState) {
const { downloadAppsUrl } = state['features/base/config'].deploymentUrls || {};
const downloadAppsUrl = getDownloadAppsUrl(state);
const visible = typeof downloadAppsUrl === 'string';

return {
Expand Down
3 changes: 2 additions & 1 deletion react/features/toolbox/components/HelpButton.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { translate } from '../../base/i18n/functions';
import { IconHelp } from '../../base/icons/svg';
import AbstractButton, { IProps as AbstractButtonProps } from '../../base/toolbox/components/AbstractButton';
import { openURLInBrowser } from '../../base/util/openURLInBrowser';
import { getUserDocumentationUrl } from '../functions.any';

interface IProps extends AbstractButtonProps {

Expand Down Expand Up @@ -49,7 +50,7 @@ class HelpButton extends AbstractButton<IProps> {
* @returns {Object}
*/
function _mapStateToProps(state: IReduxState) {
const { userDocumentationURL } = state['features/base/config'].deploymentUrls || {};
const userDocumentationURL = getUserDocumentationUrl(state);
const enabled = getFeatureFlag(state, HELP_BUTTON_ENABLED, true);
const visible = typeof userDocumentationURL === 'string' && enabled;

Expand Down
31 changes: 31 additions & 0 deletions react/features/toolbox/functions.any.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { IReduxState } from '../app/types';
import { IStateful } from '../base/app/types';
import { isJwtFeatureEnabledStateless } from '../base/jwt/functions';
import { IGUMPendingState } from '../base/media/types';
import { IParticipantFeatures } from '../base/participants/types';
import { toState } from '../base/redux/functions';
import { iAmVisitor } from '../visitors/functions';

/**
Expand Down Expand Up @@ -57,3 +59,32 @@ export function getJwtDisabledButtons(

return acc;
}

/**
* Returns the URL to the user documentation.
*
* @param {Function|Object} stateful - The redux store or {@code getState} function.
* @returns {URL} - The URL to the user documentation.
*/
export function getUserDocumentationUrl(stateful: IStateful) {
const state = toState(stateful);
const { userDocumentationUrl } = state['features/dynamic-branding'];
const { deploymentUrls } = state['features/base/config'];

return userDocumentationUrl || deploymentUrls?.userDocumentationURL;
}

/**
* Returns the URL for downloading the mobile app.
*
* @param {Function|Object} stateful - The redux store or {@code getState} function.
* @returns {URL} - The URL for downloading the mobile app.
*/
export function getDownloadAppsUrl(stateful: IStateful) {
const state = toState(stateful);
const { downloadAppsUrl } = state['features/dynamic-branding'];
const { deploymentUrls } = state['features/base/config'];

return downloadAppsUrl || deploymentUrls?.downloadAppsUrl;
}

11 changes: 8 additions & 3 deletions react/features/toolbox/hooks.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,12 @@ import ProfileButton from './components/web/ProfileButton';
import ShareDesktopButton from './components/web/ShareDesktopButton';
import ToggleCameraButton from './components/web/ToggleCameraButton';
import VideoSettingsButton from './components/web/VideoSettingsButton';
import { isButtonEnabled, isDesktopShareButtonDisabled } from './functions.web';
import {
getDownloadAppsUrl,
getUserDocumentationUrl,
isButtonEnabled,
isDesktopShareButtonDisabled
} from './functions.web';
import { ICustomToolbarButton, IToolboxButton, ToolbarButton } from './types';


Expand Down Expand Up @@ -239,7 +244,7 @@ function getShareAudioButton() {
*/
function useDownloadButton() {
const visible = useSelector(
(state: IReduxState) => typeof state['features/base/config'].deploymentUrls?.downloadAppsUrl === 'string');
(state: IReduxState) => typeof getDownloadAppsUrl(state) === 'string');

if (visible) {
return download;
Expand All @@ -254,7 +259,7 @@ function useDownloadButton() {
function useHelpButton() {
const visible = useSelector(
(state: IReduxState) =>
typeof state['features/base/config'].deploymentUrls?.userDocumentationURL === 'string'
typeof getUserDocumentationUrl(state) === 'string'
&& getFeatureFlag(state, HELP_BUTTON_ENABLED, true));

if (visible) {
Expand Down
Loading