diff --git a/app/products/calls/components/calls_custom_message/calls_custom_message.tsx b/app/products/calls/components/calls_custom_message/calls_custom_message.tsx
index 9cdca0d2c..13e34fded 100644
--- a/app/products/calls/components/calls_custom_message/calls_custom_message.tsx
+++ b/app/products/calls/components/calls_custom_message/calls_custom_message.tsx
@@ -9,6 +9,7 @@ import {Text, TouchableOpacity, View} from 'react-native';
import {leaveCallConfirmation} from '@calls/actions/calls';
import {leaveAndJoinWithAlert, showLimitRestrictedAlert} from '@calls/alerts';
import {setJoiningChannelId} from '@calls/state';
+import {getCallPropsFromPost} from '@calls/utils';
import CompassIcon from '@components/compass_icon';
import FormattedRelativeTime from '@components/formatted_relative_time';
import FormattedText from '@components/formatted_text';
@@ -164,13 +165,15 @@ export const CallsCustomMessage = ({
leaveCallConfirmation(intl, otherParticipants, isAdmin, isHost, serverUrl, post.channelId);
}, [intl, otherParticipants, isAdmin, isHost, serverUrl, post.channelId]);
- const title = post.props.title ? (
+ const callProps = getCallPropsFromPost(post);
+
+ const title = callProps.title ? (
- {post.props.title}
+ {callProps.title}
) : null;
- if (post.props.end_at) {
+ if (callProps.start_at > 0 && callProps.end_at > 0) {
return (
<>
{title}
@@ -195,7 +198,7 @@ export const CallsCustomMessage = ({
{' '}
@@ -204,7 +207,7 @@ export const CallsCustomMessage = ({
id={'mobile.calls_lasted'}
style={style.timeText}
defaultMessage={'Lasted {duration}'}
- values={{duration: moment.duration(post.props.end_at - post.props.start_at).humanize(false)}}
+ values={{duration: moment.duration(callProps.end_at - callProps.start_at).humanize(false)}}
/>
@@ -273,7 +276,7 @@ export const CallsCustomMessage = ({
style={style.text}
/>
diff --git a/app/products/calls/utils.test.ts b/app/products/calls/utils.test.ts
index b70afb726..cf59dc1c3 100644
--- a/app/products/calls/utils.test.ts
+++ b/app/products/calls/utils.test.ts
@@ -6,7 +6,7 @@ import assert from 'assert';
import {type CallsConfigState, DefaultCallsConfig} from '@calls/types/calls';
import {License} from '@constants';
-import {getICEServersConfigs} from './utils';
+import {getICEServersConfigs, getCallPropsFromPost} from './utils';
describe('getICEServersConfigs', () => {
it('backwards compatible case, no ICEServersConfigs present', () => {
@@ -97,3 +97,109 @@ describe('getICEServersConfigs', () => {
]);
});
});
+
+describe('getCallPropsFromPost', () => {
+ test('undefined props', () => {
+ const post = {} as Post;
+
+ const props = getCallPropsFromPost(post);
+
+ expect(props.title).toBe('');
+ expect(props.start_at).toBe(0);
+ expect(props.end_at).toBe(0);
+ expect(props.recordings).toStrictEqual({});
+ expect(props.recording_files.length).toBe(0);
+ expect(props.transcriptions).toStrictEqual({});
+ expect(props.participants.length).toBe(0);
+ });
+
+ test('missing props', () => {
+ const post = {
+ props: {},
+ } as Post;
+
+ const props = getCallPropsFromPost(post);
+
+ expect(props.title).toBe('');
+ expect(props.start_at).toBe(0);
+ expect(props.end_at).toBe(0);
+ expect(props.recordings).toStrictEqual({});
+ expect(props.recording_files.length).toBe(0);
+ expect(props.transcriptions).toStrictEqual({});
+ expect(props.participants.length).toBe(0);
+ });
+
+ test('invalid props', () => {
+ const callProps = {
+ title: {},
+ start_at: 'invalid',
+ end_at: [],
+ recordings: null,
+ transcriptions: 45,
+ participants: 'invalid',
+ recording_files: 45,
+ };
+
+ const post = {
+ props: callProps as unknown,
+ } as Post;
+
+ const props = getCallPropsFromPost(post);
+
+ expect(props.title).toBe('');
+ expect(props.start_at).toBe(0);
+ expect(props.end_at).toBe(0);
+ expect(props.recordings).toStrictEqual({});
+ expect(props.recording_files.length).toBe(0);
+ expect(props.transcriptions).toStrictEqual({});
+ expect(props.participants.length).toBe(0);
+ });
+
+ test('full props', () => {
+ const callProps = {
+ title: 'call title',
+ start_at: 1000,
+ end_at: 1045,
+ recordings: {
+ recA: {
+ file_id: 'recAFileID',
+ post_id: 'recAPostID',
+ tr_id: 'trA',
+ },
+ recB: {
+ file_id: 'recBFileID',
+ post_id: 'recBPostID',
+ tr_id: 'trB',
+ },
+ },
+ recording_files: ['recAFileID', 'recBFileID'],
+ transcriptions: {
+ trA: {
+ file_id: 'trAFileID',
+ post_id: 'trAPostID',
+ rec_id: 'recA',
+ },
+ trB: {
+ file_id: 'trBFileID',
+ post_id: 'trBPostID',
+ rec_id: 'recB',
+ },
+ },
+ participants: ['userA', 'userB'],
+ };
+
+ const post = {
+ props: callProps as unknown,
+ } as Post;
+
+ const props = getCallPropsFromPost(post);
+
+ expect(props.title).toBe(post.props.title);
+ expect(props.start_at).toBe(post.props.start_at);
+ expect(props.end_at).toBe(post.props.end_at);
+ expect(props.recordings).toBe(post.props.recordings);
+ expect(props.recording_files).toBe(post.props.recording_files);
+ expect(props.transcriptions).toBe(post.props.transcriptions);
+ expect(props.participants).toBe(post.props.participants);
+ });
+});
diff --git a/app/products/calls/utils.ts b/app/products/calls/utils.ts
index 086df8ec3..13969feb0 100644
--- a/app/products/calls/utils.ts
+++ b/app/products/calls/utils.ts
@@ -17,7 +17,7 @@ import type {
CallsTheme,
CallsVersion,
} from '@calls/types/calls';
-import type {CallsConfig, Caption} from '@mattermost/calls/lib/types';
+import type {CallsConfig, Caption, CallPostProps} from '@mattermost/calls/lib/types';
import type PostModel from '@typings/database/models/servers/post';
import type UserModel from '@typings/database/models/servers/user';
import type {IntlShape} from 'react-intl';
@@ -246,3 +246,21 @@ export const getTranscriptionUri = (serverUrl: string, postProps?: Record