Share call link via signal while in call

This commit is contained in:
ayumi-signal 2024-06-12 13:40:06 -07:00 committed by GitHub
parent e6b62001d3
commit 111bb70188
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 56 additions and 2 deletions

View file

@ -3690,6 +3690,10 @@
"messageformat": "Copy call link", "messageformat": "Copy call link",
"description": "Menu item in the in-call info popup for call link calls. The action is to add the call link to the clipboard." "description": "Menu item in the in-call info popup for call link calls. The action is to add the call link to the clipboard."
}, },
"icu:CallingAdhocCallInfo__ShareViaSignal": {
"messageformat": "Share call link via Signal",
"description": "Menu item in the in-call info popup for call link calls. Clicking the item opens the sharing dialog where you can send the call link to your Signal contacts or groups."
},
"icu:CallingAdhocCallInfo__RemoveClient": { "icu:CallingAdhocCallInfo__RemoveClient": {
"messageformat": "Remove this person from the call", "messageformat": "Remove this person from the call",
"description": "Button in the in-call info popup for call link calls showing all participants. The action is to remove the participant from the call." "description": "Button in the in-call info popup for call link calls showing all participants. The action is to remove the participant from the call."

View file

@ -113,6 +113,7 @@ const createProps = (storyProps: Partial<PropsType> = {}): PropsType => ({
setPresenting: action('toggle-presenting'), setPresenting: action('toggle-presenting'),
setRendererCanvas: action('set-renderer-canvas'), setRendererCanvas: action('set-renderer-canvas'),
setOutgoingRing: action('set-outgoing-ring'), setOutgoingRing: action('set-outgoing-ring'),
showShareCallLinkViaSignal: action('show-share-call-link-via-signal'),
startCall: action('start-call'), startCall: action('start-call'),
stopRingtone: action('stop-ringtone'), stopRingtone: action('stop-ringtone'),
switchToPresentationView: action('switch-to-presentation-view'), switchToPresentationView: action('switch-to-presentation-view'),

View file

@ -126,6 +126,10 @@ export type PropsType = {
setOutgoingRing: (_: boolean) => void; setOutgoingRing: (_: boolean) => void;
setPresenting: (_?: PresentedSource) => void; setPresenting: (_?: PresentedSource) => void;
setRendererCanvas: (_: SetRendererCanvasType) => void; setRendererCanvas: (_: SetRendererCanvasType) => void;
showShareCallLinkViaSignal: (
callLink: CallLinkType,
i18n: LocalizerType
) => void;
stopRingtone: () => unknown; stopRingtone: () => unknown;
switchToPresentationView: () => void; switchToPresentationView: () => void;
switchFromPresentationView: () => void; switchFromPresentationView: () => void;
@ -184,6 +188,7 @@ function ActiveCallManager({
setPresenting, setPresenting,
setRendererCanvas, setRendererCanvas,
setOutgoingRing, setOutgoingRing,
showShareCallLinkViaSignal,
startCall, startCall,
switchToPresentationView, switchToPresentationView,
switchFromPresentationView, switchFromPresentationView,
@ -267,6 +272,15 @@ function ActiveCallManager({
} }
}, [callLink]); }, [callLink]);
const handleShareCallLinkViaSignal = useCallback(() => {
if (!callLink) {
log.error('Missing call link');
return;
}
showShareCallLinkViaSignal(callLink, i18n);
}, [callLink, i18n, showShareCallLinkViaSignal]);
let isCallFull: boolean; let isCallFull: boolean;
let showCallLobby: boolean; let showCallLobby: boolean;
let groupMembers: let groupMembers:
@ -379,6 +393,7 @@ function ActiveCallManager({
participants={peekedParticipants} participants={peekedParticipants}
onClose={toggleParticipants} onClose={toggleParticipants}
onCopyCallLink={onCopyCallLink} onCopyCallLink={onCopyCallLink}
onShareCallLinkViaSignal={handleShareCallLinkViaSignal}
removeClient={removeClient} removeClient={removeClient}
/> />
) : ( ) : (
@ -472,6 +487,7 @@ function ActiveCallManager({
participants={groupCallParticipantsForParticipantsList} participants={groupCallParticipantsForParticipantsList}
onClose={toggleParticipants} onClose={toggleParticipants}
onCopyCallLink={onCopyCallLink} onCopyCallLink={onCopyCallLink}
onShareCallLinkViaSignal={handleShareCallLinkViaSignal}
removeClient={removeClient} removeClient={removeClient}
/> />
) : ( ) : (
@ -527,6 +543,7 @@ export function CallManager({
setOutgoingRing, setOutgoingRing,
setPresenting, setPresenting,
setRendererCanvas, setRendererCanvas,
showShareCallLinkViaSignal,
startCall, startCall,
stopRingtone, stopRingtone,
switchFromPresentationView, switchFromPresentationView,
@ -616,6 +633,7 @@ export function CallManager({
setOutgoingRing={setOutgoingRing} setOutgoingRing={setOutgoingRing}
setPresenting={setPresenting} setPresenting={setPresenting}
setRendererCanvas={setRendererCanvas} setRendererCanvas={setRendererCanvas}
showShareCallLinkViaSignal={showShareCallLinkViaSignal}
startCall={startCall} startCall={startCall}
switchFromPresentationView={switchFromPresentationView} switchFromPresentationView={switchFromPresentationView}
switchToPresentationView={switchToPresentationView} switchToPresentationView={switchToPresentationView}

View file

@ -66,6 +66,7 @@ const createProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
participants: overrideProps.participants || [], participants: overrideProps.participants || [],
onClose: action('on-close'), onClose: action('on-close'),
onCopyCallLink: action('on-copy-call-link'), onCopyCallLink: action('on-copy-call-link'),
onShareCallLinkViaSignal: action('on-share-call-link-via-signal'),
removeClient: overrideProps.removeClient || action('remove-client'), removeClient: overrideProps.removeClient || action('remove-client'),
}); });

View file

@ -39,6 +39,7 @@ export type PropsType = {
readonly participants: Array<ParticipantType>; readonly participants: Array<ParticipantType>;
readonly onClose: () => void; readonly onClose: () => void;
readonly onCopyCallLink: () => void; readonly onCopyCallLink: () => void;
readonly onShareCallLinkViaSignal: () => void;
readonly removeClient: ((payload: RemoveClientType) => void) | null; readonly removeClient: ((payload: RemoveClientType) => void) | null;
}; };
@ -142,6 +143,7 @@ export function CallingAdhocCallInfo({
participants, participants,
onClose, onClose,
onCopyCallLink, onCopyCallLink,
onShareCallLinkViaSignal,
removeClient, removeClient,
}: PropsType): JSX.Element | null { }: PropsType): JSX.Element | null {
const [isUnknownContactDialogVisible, setIsUnknownContactDialogVisible] = const [isUnknownContactDialogVisible, setIsUnknownContactDialogVisible] =
@ -150,6 +152,10 @@ export function CallingAdhocCallInfo({
() => setIsUnknownContactDialogVisible(false), () => setIsUnknownContactDialogVisible(false),
[setIsUnknownContactDialogVisible] [setIsUnknownContactDialogVisible]
); );
const onClickShareCallLinkViaSignal = React.useCallback(() => {
onClose();
onShareCallLinkViaSignal();
}, [onClose, onShareCallLinkViaSignal]);
const [knownParticipants, unknownParticipants] = React.useMemo< const [knownParticipants, unknownParticipants] = React.useMemo<
[Array<ParticipantType>, Array<ParticipantType>] [Array<ParticipantType>, Array<ParticipantType>]
@ -323,6 +329,16 @@ export function CallingAdhocCallInfo({
{i18n('icu:CallingAdhocCallInfo__CopyLink')} {i18n('icu:CallingAdhocCallInfo__CopyLink')}
</span> </span>
</button> </button>
<button
className="CallingAdhocCallInfo__MenuItem"
onClick={onClickShareCallLinkViaSignal}
type="button"
>
<span className="CallingAdhocCallInfo__MenuItemIcon CallingAdhocCallInfo__MenuItemIcon--share-via-signal" />
<span className="CallingAdhocCallInfo__MenuItemText">
{i18n('icu:CallingAdhocCallInfo__ShareViaSignal')}
</span>
</button>
</div> </div>
</div> </div>
</ModalHost> </ModalHost>

View file

@ -52,6 +52,7 @@ const useProps = (overrideProps: Partial<PropsType> = {}): PropsType => ({
doForwardMessages: action('doForwardMessages'), doForwardMessages: action('doForwardMessages'),
getPreferredBadge: () => undefined, getPreferredBadge: () => undefined,
i18n, i18n,
isInFullScreenCall: false,
linkPreviewForSource: () => undefined, linkPreviewForSource: () => undefined,
onClose: action('onClose'), onClose: action('onClose'),
onChange: action('onChange'), onChange: action('onChange'),

View file

@ -43,6 +43,7 @@ import {
type MessageForwardDraft, type MessageForwardDraft,
} from '../types/ForwardDraft'; } from '../types/ForwardDraft';
import { missingCaseError } from '../util/missingCaseError'; import { missingCaseError } from '../util/missingCaseError';
import { Theme } from '../util/theme';
export enum ForwardMessagesModalType { export enum ForwardMessagesModalType {
Forward, Forward,
@ -58,6 +59,7 @@ export type DataPropsType = {
drafts: ReadonlyArray<MessageForwardDraft>; drafts: ReadonlyArray<MessageForwardDraft>;
getPreferredBadge: PreferredBadgeSelectorType; getPreferredBadge: PreferredBadgeSelectorType;
i18n: LocalizerType; i18n: LocalizerType;
isInFullScreenCall: boolean;
linkPreviewForSource: ( linkPreviewForSource: (
source: LinkPreviewSourceType source: LinkPreviewSourceType
@ -90,6 +92,7 @@ export function ForwardMessagesModal({
linkPreviewForSource, linkPreviewForSource,
getPreferredBadge, getPreferredBadge,
i18n, i18n,
isInFullScreenCall,
onClose, onClose,
onChange, onChange,
removeLinkPreview, removeLinkPreview,
@ -309,6 +312,8 @@ export function ForwardMessagesModal({
throw missingCaseError(type); throw missingCaseError(type);
} }
const modalTheme = isInFullScreenCall ? Theme.Dark : undefined;
return ( return (
<> <>
{cannotMessage && ( {cannotMessage && (
@ -329,7 +334,8 @@ export function ForwardMessagesModal({
onBackButtonClick={isEditingMessage ? handleBackOrClose : undefined} onBackButtonClick={isEditingMessage ? handleBackOrClose : undefined}
moduleClassName="module-ForwardMessageModal" moduleClassName="module-ForwardMessageModal"
title={title} title={title}
useFocusTrap={false} theme={modalTheme}
useFocusTrap={isInFullScreenCall}
padded={false} padded={false}
modalFooter={footer} modalFooter={footer}
noMouseClose noMouseClose

View file

@ -55,6 +55,7 @@ import { SmartCallingDeviceSelection } from './CallingDeviceSelection';
import { renderEmojiPicker } from './renderEmojiPicker'; import { renderEmojiPicker } from './renderEmojiPicker';
import { renderReactionPicker } from './renderReactionPicker'; import { renderReactionPicker } from './renderReactionPicker';
import { isSharingPhoneNumberWithEverybody as getIsSharingPhoneNumberWithEverybody } from '../../util/phoneNumberSharingMode'; import { isSharingPhoneNumberWithEverybody as getIsSharingPhoneNumberWithEverybody } from '../../util/phoneNumberSharingMode';
import { useGlobalModalActions } from '../ducks/globalModals';
function renderDeviceSelection(): JSX.Element { function renderDeviceSelection(): JSX.Element {
return <SmartCallingDeviceSelection />; return <SmartCallingDeviceSelection />;
@ -454,6 +455,7 @@ export const SmartCallManager = memo(function SmartCallManager() {
toggleSettings, toggleSettings,
} = useCallingActions(); } = useCallingActions();
const { pauseVoiceNotePlayer } = useAudioPlayerActions(); const { pauseVoiceNotePlayer } = useAudioPlayerActions();
const { showShareCallLinkViaSignal } = useGlobalModalActions();
return ( return (
<CallManager <CallManager
@ -499,6 +501,7 @@ export const SmartCallManager = memo(function SmartCallManager() {
setOutgoingRing={setOutgoingRing} setOutgoingRing={setOutgoingRing}
setPresenting={setPresenting} setPresenting={setPresenting}
setRendererCanvas={setRendererCanvas} setRendererCanvas={setRendererCanvas}
showShareCallLinkViaSignal={showShareCallLinkViaSignal}
startCall={startCall} startCall={startCall}
stopRingtone={stopRingtone} stopRingtone={stopRingtone}
switchFromPresentationView={switchFromPresentationView} switchFromPresentationView={switchFromPresentationView}

View file

@ -11,6 +11,7 @@ import * as Errors from '../../types/errors';
import { getAllComposableConversations } from '../selectors/conversations'; import { getAllComposableConversations } from '../selectors/conversations';
import { getIntl, getTheme, getRegionCode } from '../selectors/user'; import { getIntl, getTheme, getRegionCode } from '../selectors/user';
import { getLinkPreview } from '../selectors/linkPreviews'; import { getLinkPreview } from '../selectors/linkPreviews';
import { isInFullScreenCall as getIsInFullScreenCall } from '../selectors/calling';
import { getPreferredBadgeSelector } from '../selectors/badges'; import { getPreferredBadgeSelector } from '../selectors/badges';
import { maybeForwardMessages } from '../../util/maybeForwardMessages'; import { maybeForwardMessages } from '../../util/maybeForwardMessages';
import { import {
@ -57,17 +58,19 @@ function SmartForwardMessagesModalInner({
}: { }: {
forwardMessagesProps: ForwardMessagesPropsType; forwardMessagesProps: ForwardMessagesPropsType;
}): JSX.Element | null { }): JSX.Element | null {
const { type } = forwardMessagesProps;
const candidateConversations = useSelector(getAllComposableConversations); const candidateConversations = useSelector(getAllComposableConversations);
const getPreferredBadge = useSelector(getPreferredBadgeSelector); const getPreferredBadge = useSelector(getPreferredBadgeSelector);
const i18n = useSelector(getIntl); const i18n = useSelector(getIntl);
const linkPreviewForSource = useSelector(getLinkPreview); const linkPreviewForSource = useSelector(getLinkPreview);
const regionCode = useSelector(getRegionCode); const regionCode = useSelector(getRegionCode);
const theme = useSelector(getTheme); const theme = useSelector(getTheme);
const isInFullScreenCall = useSelector(getIsInFullScreenCall);
const { removeLinkPreview } = useLinkPreviewActions(); const { removeLinkPreview } = useLinkPreviewActions();
const { toggleForwardMessagesModal } = useGlobalModalActions(); const { toggleForwardMessagesModal } = useGlobalModalActions();
const { showToast } = useToastActions(); const { showToast } = useToastActions();
const { type } = forwardMessagesProps;
const [drafts, setDrafts] = useState<ReadonlyArray<MessageForwardDraft>>( const [drafts, setDrafts] = useState<ReadonlyArray<MessageForwardDraft>>(
() => { () => {
@ -153,6 +156,7 @@ function SmartForwardMessagesModalInner({
linkPreviewForSource={linkPreviewForSource} linkPreviewForSource={linkPreviewForSource}
getPreferredBadge={getPreferredBadge} getPreferredBadge={getPreferredBadge}
i18n={i18n} i18n={i18n}
isInFullScreenCall={isInFullScreenCall}
onClose={closeModal} onClose={closeModal}
onChange={handleChange} onChange={handleChange}
regionCode={regionCode} regionCode={regionCode}