feat: add the support for CDN_PREFIX (#5266)

* add the support for cdn_prefix

* add cdn-prefix to video and audio too

* refactor where call the store to cdn

* fix e2e test

* add connect redux
This commit is contained in:
Reinaldo Neto 2023-10-17 16:28:02 -03:00 committed by GitHub
parent 199331f8f6
commit 3cf08c29e1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 41 additions and 11 deletions

View File

@ -30,7 +30,8 @@ const Avatar = React.memo(
borderRadius = 4, borderRadius = 4,
type = SubscriptionType.DIRECT, type = SubscriptionType.DIRECT,
avatarExternalProviderUrl, avatarExternalProviderUrl,
roomAvatarExternalProviderUrl roomAvatarExternalProviderUrl,
cdnPrefix
}: IAvatar) => { }: IAvatar) => {
if ((!text && !avatar && !emoji && !rid) || !server) { if ((!text && !avatar && !emoji && !rid) || !server) {
return null; return null;
@ -61,7 +62,8 @@ const Avatar = React.memo(
rid, rid,
blockUnauthenticatedAccess, blockUnauthenticatedAccess,
avatarExternalProviderUrl, avatarExternalProviderUrl,
roomAvatarExternalProviderUrl roomAvatarExternalProviderUrl,
cdnPrefix
}); });
} }

View File

@ -32,9 +32,10 @@ const AvatarContainer = ({
shallowEqual shallowEqual
); );
const { avatarExternalProviderUrl, roomAvatarExternalProviderUrl } = useSelector((state: IApplicationState) => ({ const { avatarExternalProviderUrl, roomAvatarExternalProviderUrl, cdnPrefix } = useSelector((state: IApplicationState) => ({
avatarExternalProviderUrl: state.settings.Accounts_AvatarExternalProviderUrl as string, avatarExternalProviderUrl: state.settings.Accounts_AvatarExternalProviderUrl as string,
roomAvatarExternalProviderUrl: state.settings.Accounts_RoomAvatarExternalProviderUrl as string roomAvatarExternalProviderUrl: state.settings.Accounts_RoomAvatarExternalProviderUrl as string,
cdnPrefix: state.settings.CDN_PREFIX as string
})); }));
const blockUnauthenticatedAccess = useSelector( const blockUnauthenticatedAccess = useSelector(
(state: IApplicationState) => (state: IApplicationState) =>
@ -67,6 +68,7 @@ const AvatarContainer = ({
roomAvatarExternalProviderUrl={roomAvatarExternalProviderUrl} roomAvatarExternalProviderUrl={roomAvatarExternalProviderUrl}
avatarETag={avatarETag} avatarETag={avatarETag}
serverVersion={serverVersion} serverVersion={serverVersion}
cdnPrefix={cdnPrefix}
/> />
); );
}; };

View File

@ -24,4 +24,5 @@ export interface IAvatar {
serverVersion?: string | null; serverVersion?: string | null;
avatarExternalProviderUrl?: string; avatarExternalProviderUrl?: string;
roomAvatarExternalProviderUrl?: string; roomAvatarExternalProviderUrl?: string;
cdnPrefix?: string;
} }

View File

@ -6,6 +6,7 @@ import moment from 'moment';
import { dequal } from 'dequal'; import { dequal } from 'dequal';
import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake'; import { activateKeepAwake, deactivateKeepAwake } from 'expo-keep-awake';
import { Sound } from 'expo-av/build/Audio/Sound'; import { Sound } from 'expo-av/build/Audio/Sound';
import { connect } from 'react-redux';
import Touchable from './Touchable'; import Touchable from './Touchable';
import Markdown from '../markdown'; import Markdown from '../markdown';
@ -17,7 +18,7 @@ import MessageContext from './Context';
import ActivityIndicator from '../ActivityIndicator'; import ActivityIndicator from '../ActivityIndicator';
import { withDimensions } from '../../dimensions'; import { withDimensions } from '../../dimensions';
import { TGetCustomEmoji } from '../../definitions/IEmoji'; import { TGetCustomEmoji } from '../../definitions/IEmoji';
import { IAttachment, IUserMessage } from '../../definitions'; import { IApplicationState, IAttachment, IUserMessage } from '../../definitions';
import { TSupportedThemes, useTheme } from '../../theme'; import { TSupportedThemes, useTheme } from '../../theme';
import { downloadMediaFile, getMediaCache } from '../../lib/methods/handleMediaDownload'; import { downloadMediaFile, getMediaCache } from '../../lib/methods/handleMediaDownload';
import EventEmitter from '../../lib/methods/helpers/events'; import EventEmitter from '../../lib/methods/helpers/events';
@ -41,6 +42,7 @@ interface IMessageAudioProps {
scale?: number; scale?: number;
author?: IUserMessage; author?: IUserMessage;
msg?: string; msg?: string;
cdnPrefix?: string;
} }
interface IMessageAudioState { interface IMessageAudioState {
@ -208,13 +210,12 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
} }
getUrl = () => { getUrl = () => {
const { file } = this.props; const { file, cdnPrefix } = this.props;
// @ts-ignore can't use declare to type this // @ts-ignore can't use declare to type this
const { baseUrl } = this.context; const { baseUrl } = this.context;
let url = file.audio_url; let url = file.audio_url;
if (url && !url.startsWith('http')) { if (url && !url.startsWith('http')) {
url = `${baseUrl}${file.audio_url}`; url = `${cdnPrefix || baseUrl}${file.audio_url}`;
} }
return url; return url;
}; };
@ -393,4 +394,8 @@ class MessageAudio extends React.Component<IMessageAudioProps, IMessageAudioStat
} }
} }
export default withDimensions(MessageAudio); const mapStateToProps = (state: IApplicationState) => ({
cdnPrefix: state.settings.CDN_PREFIX as string
});
export default connect(mapStateToProps)(withDimensions(MessageAudio));

View File

@ -246,5 +246,8 @@ export const defaultSettings = {
Omnichannel_call_provider: { Omnichannel_call_provider: {
type: 'valueAsBoolean' type: 'valueAsBoolean'
}, },
CDN_PREFIX: {
type: 'valueAsString'
},
...deprecatedSettings ...deprecatedSettings
} as const; } as const;

View File

@ -2,6 +2,7 @@ import { URL } from 'react-native-url-polyfill';
import { LOCAL_DOCUMENT_DIRECTORY } from '../handleMediaDownload'; import { LOCAL_DOCUMENT_DIRECTORY } from '../handleMediaDownload';
import { isImageBase64 } from '../isImageBase64'; import { isImageBase64 } from '../isImageBase64';
import { store } from '../../store/auxStore';
function setParamInUrl({ url, token, userId }: { url: string; token: string; userId: string }) { function setParamInUrl({ url, token, userId }: { url: string; token: string; userId: string }) {
const urlObj = new URL(url); const urlObj = new URL(url);
@ -23,5 +24,9 @@ export const formatAttachmentUrl = (attachmentUrl: string | undefined, userId: s
} }
return setParamInUrl({ url: attachmentUrl, token, userId }); return setParamInUrl({ url: attachmentUrl, token, userId });
} }
const cdnPrefix = store?.getState().settings.CDN_PREFIX as string;
if (cdnPrefix) {
server = cdnPrefix.trim().replace(/\/+$/, '');
}
return setParamInUrl({ url: `${server}${attachmentUrl}`, token, userId }); return setParamInUrl({ url: `${server}${attachmentUrl}`, token, userId });
}; };

View File

@ -22,7 +22,8 @@ export const getAvatarURL = ({
blockUnauthenticatedAccess, blockUnauthenticatedAccess,
serverVersion, serverVersion,
avatarExternalProviderUrl, avatarExternalProviderUrl,
roomAvatarExternalProviderUrl roomAvatarExternalProviderUrl,
cdnPrefix
}: IAvatar): string => { }: IAvatar): string => {
let room; let room;
if (type === SubscriptionType.DIRECT) { if (type === SubscriptionType.DIRECT) {
@ -48,6 +49,10 @@ export const getAvatarURL = ({
query += `&etag=${avatarETag}`; query += `&etag=${avatarETag}`;
} }
if (cdnPrefix) {
server = cdnPrefix.trim().replace(/\/+$/, '');
}
if (avatar) { if (avatar) {
if (avatar.startsWith('http')) { if (avatar.startsWith('http')) {
return avatar; return avatar;

View File

@ -478,6 +478,8 @@ describe('Room screen', () => {
.toExist() .toExist()
.withTimeout(2000); .withTimeout(2000);
await expect(element(by.id('action-sheet-handle'))).toBeVisible(); await expect(element(by.id('action-sheet-handle'))).toBeVisible();
// Fix android flaky test. Close the action sheet, then re-open again
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
await element(by.id('action-sheet')).swipe('up', 'fast', 0.5); await element(by.id('action-sheet')).swipe('up', 'fast', 0.5);
await sleep(300); // wait for animation await sleep(300); // wait for animation
await waitFor(element(by[textMatcher]('Delete'))) await waitFor(element(by[textMatcher]('Delete')))

View File

@ -237,6 +237,9 @@ describe('Threads', () => {
.withTimeout(5000); .withTimeout(5000);
await element(by.id(`message-thread-button-${thread}`)).tap(); await element(by.id(`message-thread-button-${thread}`)).tap();
await tryTapping(element(by[textMatcher]('replied')).atIndex(0), 2000, true); await tryTapping(element(by[textMatcher]('replied')).atIndex(0), 2000, true);
// Fix android flaky test. Close the action sheet, then re-open again
await element(by.id('action-sheet-handle')).swipe('up', 'fast', 0.5);
await sleep(1000); // wait for animation
await element(by.id('action-sheet')).swipe('up', 'fast', 0.5); await element(by.id('action-sheet')).swipe('up', 'fast', 0.5);
await sleep(300); // wait for animation await sleep(300); // wait for animation
await element(by[textMatcher]('Delete')).atIndex(0).tap(); await element(by[textMatcher]('Delete')).atIndex(0).tap();

View File

@ -137,9 +137,10 @@ describe('Auto Translate', () => {
// verify default language is checked // verify default language is checked
await waitFor(element(by.id(`auto-translate-view-${languages.default}`))) await waitFor(element(by.id(`auto-translate-view-${languages.default}`)))
.toBeVisible() .toExist()
.whileElement(by.id('auto-translate-view')) .whileElement(by.id('auto-translate-view'))
.scroll(750, 'down'); .scroll(750, 'down');
await element(by.id('auto-translate-view')).swipe('up', 'slow', 0.5);
await waitForVisible(`auto-translate-view-${languages.default}-check`); await waitForVisible(`auto-translate-view-${languages.default}-check`);
// enable translated language // enable translated language
@ -219,6 +220,7 @@ describe('Auto Translate', () => {
}); });
it(`should don't see action to View original when disable auto translate`, async () => { it(`should don't see action to View original when disable auto translate`, async () => {
await searchMessage(oldMessage[languages.default] as string, textMatcher); // will scroll the messages list to the last one
await waitForVisibleTextMatcher(oldMessage[languages.default] as string, textMatcher); await waitForVisibleTextMatcher(oldMessage[languages.default] as string, textMatcher);
await tryTapping(element(by[textMatcher](oldMessage[languages.default] as string)).atIndex(0), 2000, true); await tryTapping(element(by[textMatcher](oldMessage[languages.default] as string)).atIndex(0), 2000, true);