fix(iOS-mailto): Send no new line invite on default email

- addresses this issue: https://developer.apple.com/forums/thread/681023
This commit is contained in:
hmuresan 2021-07-15 16:12:06 +03:00 committed by Horatiu Muresan
parent 73328810e4
commit 6f9944a2d0
4 changed files with 72 additions and 4 deletions

View File

@ -418,6 +418,10 @@
"invitePhone": "To join by phone instead, tap this: {{number}},,{{conferenceID}}#\n", "invitePhone": "To join by phone instead, tap this: {{number}},,{{conferenceID}}#\n",
"invitePhoneAlternatives": "Looking for a different dial-in number?\nSee meeting dial-in numbers: {{url}}\n\n\nIf also dialing-in through a room phone, join without connecting to audio: {{silentUrl}}", "invitePhoneAlternatives": "Looking for a different dial-in number?\nSee meeting dial-in numbers: {{url}}\n\n\nIf also dialing-in through a room phone, join without connecting to audio: {{silentUrl}}",
"inviteSipEndpoint": "To join using the SIP address, enter this: {{sipUri}}", "inviteSipEndpoint": "To join using the SIP address, enter this: {{sipUri}}",
"inviteTextiOSPersonal": "{{name}} is inviting you to a meeting.",
"inviteTextiOSJoinSilent": "If you are dialing-in through a room phone, use this link to join without connecting to audio: {{silentUrl}}.",
"inviteTextiOSInviteUrl": "Click the following link to join: {{inviteUrl}}.",
"inviteTextiOSPhone": "To join via phone, use this number: {{number}},,{{conferenceID}}#. If you are looking for a different number, this is the full list: {{didUrl}}.",
"inviteURLFirstPartGeneral": "You are invited to join a meeting.", "inviteURLFirstPartGeneral": "You are invited to join a meeting.",
"inviteURLFirstPartPersonal": "{{name}} is inviting you to a meeting.\n", "inviteURLFirstPartPersonal": "{{name}} is inviting you to a meeting.\n",
"inviteURLSecondPart": "\nJoin the meeting:\n{{url}}\n", "inviteURLSecondPart": "\nJoin the meeting:\n{{url}}\n",

View File

@ -16,6 +16,7 @@ import { updateDialInNumbers } from '../../../actions';
import { import {
_getDefaultPhoneNumber, _getDefaultPhoneNumber,
getInviteText, getInviteText,
getInviteTextiOS,
isAddPeopleEnabled, isAddPeopleEnabled,
isDialOutEnabled, isDialOutEnabled,
sharingFeatures, sharingFeatures,
@ -62,6 +63,12 @@ type Props = {
*/ */
_invitationText: string, _invitationText: string,
/**
* The custom no new-lines meeting invitation text for iOS default email.
* Needed because of this mailto: iOS issue: https://developer.apple.com/forums/thread/681023
*/
_invitationTextiOS: string,
/** /**
* An alternate app name to be displayed in the email subject. * An alternate app name to be displayed in the email subject.
*/ */
@ -110,6 +117,7 @@ function AddPeopleDialog({
_urlSharingVisible, _urlSharingVisible,
_emailSharingVisible, _emailSharingVisible,
_invitationText, _invitationText,
_invitationTextiOS,
_inviteAppName, _inviteAppName,
_inviteContactsVisible, _inviteContactsVisible,
_inviteUrl, _inviteUrl,
@ -160,7 +168,8 @@ function AddPeopleDialog({
_emailSharingVisible _emailSharingVisible
? <InviteByEmailSection ? <InviteByEmailSection
inviteSubject = { inviteSubject } inviteSubject = { inviteSubject }
inviteText = { _invitationText } /> inviteText = { _invitationText }
inviteTextiOS = { _invitationTextiOS } />
: null : null
} }
{ _embedMeetingVisible && <EmbedMeetingTrigger /> } { _embedMeetingVisible && <EmbedMeetingTrigger /> }
@ -207,6 +216,9 @@ function mapStateToProps(state, ownProps) {
_invitationText: getInviteText({ state, _invitationText: getInviteText({ state,
phoneNumber, phoneNumber,
t: ownProps.t }), t: ownProps.t }),
_invitationTextiOS: getInviteTextiOS({ state,
phoneNumber,
t: ownProps.t }),
_inviteAppName: inviteAppName, _inviteAppName: inviteAppName,
_inviteContactsVisible: interfaceConfig.ENABLE_DIAL_OUT && !hideInviteContacts, _inviteContactsVisible: interfaceConfig.ENABLE_DIAL_OUT && !hideInviteContacts,
_inviteUrl: getInviteURL(state), _inviteUrl: getInviteURL(state),

View File

@ -2,6 +2,7 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { isIosMobileBrowser } from '../../../../base/environment/utils';
import { translate } from '../../../../base/i18n'; import { translate } from '../../../../base/i18n';
import { import {
Icon, Icon,
@ -27,6 +28,11 @@ type Props = {
*/ */
inviteText: string, inviteText: string,
/**
* The encoded no new-lines iOS invitation text to be sent on default mail.
*/
inviteTextiOS: string,
/** /**
* Invoked to obtain translated strings. * Invoked to obtain translated strings.
*/ */
@ -38,10 +44,13 @@ type Props = {
* *
* @returns {React$Element<any>} * @returns {React$Element<any>}
*/ */
function InviteByEmailSection({ inviteSubject, inviteText, t }: Props) { function InviteByEmailSection({ inviteSubject, inviteText, inviteTextiOS, t }: Props) {
const [ isActive, setIsActive ] = useState(false); const [ isActive, setIsActive ] = useState(false);
const encodedInviteSubject = encodeURIComponent(inviteSubject); const encodedInviteSubject = encodeURIComponent(inviteSubject);
const encodedInviteText = encodeURIComponent(inviteText); const encodedInviteText = encodeURIComponent(inviteText);
const encodedInviteTextiOS = encodeURIComponent(inviteTextiOS);
const encodedDefaultEmailText = isIosMobileBrowser() ? encodedInviteTextiOS : encodedInviteText;
/** /**
* Copies the conference invitation to the clipboard. * Copies the conference invitation to the clipboard.
@ -100,7 +109,7 @@ function InviteByEmailSection({ inviteSubject, inviteText, t }: Props) {
{ {
icon: IconEmail, icon: IconEmail,
tooltipKey: 'addPeople.defaultEmail', tooltipKey: 'addPeople.defaultEmail',
url: `mailto:?subject=${encodedInviteSubject}&body=${encodedInviteText}` url: `mailto:?subject=${encodedInviteSubject}&body=${encodedDefaultEmailText}`
}, },
{ {
icon: IconGoogle, icon: IconGoogle,

View File

@ -3,6 +3,7 @@
import { getActiveSession } from '../../features/recording/functions'; import { getActiveSession } from '../../features/recording/functions';
import { getRoomName } from '../base/conference'; import { getRoomName } from '../base/conference';
import { getInviteURL } from '../base/connection'; import { getInviteURL } from '../base/connection';
import { isIosMobileBrowser } from '../base/environment/utils';
import { i18next } from '../base/i18n'; import { i18next } from '../base/i18n';
import { JitsiRecordingConstants } from '../base/lib-jitsi-meet'; import { JitsiRecordingConstants } from '../base/lib-jitsi-meet';
import { getLocalParticipant, isLocalParticipantModerator } from '../base/participants'; import { getLocalParticipant, isLocalParticipantModerator } from '../base/participants';
@ -251,6 +252,49 @@ export function getInviteResultsForQuery(
}); });
} }
/**
* Creates a custom no new lines message for iOS default mail describing how to dial in to the conference.
*
* @returns {string}
*/
export function getInviteTextiOS({
state,
phoneNumber,
t
}: Object) {
if (!isIosMobileBrowser()) {
return '';
}
const dialIn = state['features/invite'];
const inviteUrl = getInviteURL(state);
const localParticipant = getLocalParticipant(state);
const localParticipantName = localParticipant?.name;
const inviteURL = _decodeRoomURI(inviteUrl);
let invite = localParticipantName
? t('info.inviteTextiOSPersonal', { name: localParticipantName })
: t('info.inviteURLFirstPartGeneral');
invite += ' ';
invite += t('info.inviteTextiOSInviteUrl', { inviteUrl });
invite += ' ';
if (shouldDisplayDialIn(dialIn)) {
invite += t('info.inviteTextiOSPhone', {
number: phoneNumber,
conferenceID: dialIn.conferenceID,
didUrl: getDialInfoPageURL(state)
});
}
invite += ' ';
invite += t('info.inviteTextiOSJoinSilent', { silentUrl: `${inviteURL}#config.startSilent=true` });
return invite;
}
/** /**
* Creates a message describing how to dial in to the conference. * Creates a message describing how to dial in to the conference.
* *
@ -271,7 +315,6 @@ export function getInviteText({
const localParticipantName = localParticipant?.name; const localParticipantName = localParticipant?.name;
const inviteURL = _decodeRoomURI(inviteUrl); const inviteURL = _decodeRoomURI(inviteUrl);
let invite = localParticipantName let invite = localParticipantName
? t('info.inviteURLFirstPartPersonal', { name: localParticipantName }) ? t('info.inviteURLFirstPartPersonal', { name: localParticipantName })
: t('info.inviteURLFirstPartGeneral'); : t('info.inviteURLFirstPartGeneral');