From bd5134a7cec0c5d7ee7775a1258ac429b1ff8e91 Mon Sep 17 00:00:00 2001 From: ayumi-signal <143036029+ayumi-signal@users.noreply.github.com> Date: Thu, 2 May 2024 13:57:17 -0700 Subject: [PATCH] Show leave button and spinner while requesting to join call link --- _locales/en/messages.json | 4 +++ stylesheets/components/CallingLobby.scss | 10 ++++++ stylesheets/components/SpinnerV2.scss | 33 ++++++++++++++++++ stylesheets/manifest.scss | 1 + ts/components/CallingLobby.stories.tsx | 11 +++++- ts/components/CallingLobby.tsx | 44 ++++++++++++++++++------ ts/components/SpinnerV2.tsx | 40 +++++++++++++++++++++ 7 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 stylesheets/components/SpinnerV2.scss create mode 100644 ts/components/SpinnerV2.tsx diff --git a/_locales/en/messages.json b/_locales/en/messages.json index 897367e7a2e..8e039c46bc9 100644 --- a/_locales/en/messages.json +++ b/_locales/en/messages.json @@ -1613,6 +1613,10 @@ "messageformat": "Anyone who joins this call via the link will see your name, photo, and phone number.", "description": "Toast shown in call lobby before joining a call link call to inform user that profile info will be shared, when the phone number sharing account setting is enabled." }, + "icu:CallingLobby__CallLinkNotice--join-request-pending": { + "messageformat": "Waiting to be let in…", + "description": "Notice shown in call lobby after you requested to join a call link to indicate your request is pending approval." + }, "icu:CallingLobbyJoinButton--join": { "messageformat": "Join", "description": "Button label in the call lobby for joining a call" diff --git a/stylesheets/components/CallingLobby.scss b/stylesheets/components/CallingLobby.scss index 24c8ece364c..55adbdd580c 100644 --- a/stylesheets/components/CallingLobby.scss +++ b/stylesheets/components/CallingLobby.scss @@ -46,9 +46,19 @@ background: $color-black-alpha-60; color: $color-white; border-radius: 10px; + align-items: center; text-align: center; } +.CallingLobby__CallLinkNotice--join-request-pending { + @include font-body-1; + width: auto; +} + +.CallingLobby__CallLinkJoinRequestPendingSpinner { + margin-inline-end: 8px; +} + .CallingLobby__Footer { display: flex; width: 100%; diff --git a/stylesheets/components/SpinnerV2.scss b/stylesheets/components/SpinnerV2.scss new file mode 100644 index 00000000000..9b5e3bfe63a --- /dev/null +++ b/stylesheets/components/SpinnerV2.scss @@ -0,0 +1,33 @@ +// Copyright 2024 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only + +.SpinnerV2 { + animation: SpinnerV2-rotate 2s linear infinite; +} + +.SpinnerV2__Path { + stroke: $color-gray-15; + stroke-linecap: round; + animation: SpinnerV2-dash 1.5s ease-in-out infinite; +} + +@keyframes SpinnerV2-rotate { + 100% { + transform: rotate(360deg); + } +} + +@keyframes SpinnerV2-dash { + 0% { + stroke-dasharray: 2%, 300%; + stroke-dashoffset: 0; + } + 50% { + stroke-dasharray: 180%, 300%; + stroke-dashoffset: -70%; + } + 100% { + stroke-dasharray: 180%, 300%; + stroke-dashoffset: -248%; + } +} diff --git a/stylesheets/manifest.scss b/stylesheets/manifest.scss index 68c3e5ab0b8..f92aab6697f 100644 --- a/stylesheets/manifest.scss +++ b/stylesheets/manifest.scss @@ -147,6 +147,7 @@ @import './components/ShortcutGuide.scss'; @import './components/SignalConnectionsModal.scss'; @import './components/Slider.scss'; +@import './components/SpinnerV2.scss'; @import './components/StagedLinkPreview.scss'; @import './components/StickerManager.scss'; @import './components/Stories.scss'; diff --git a/ts/components/CallingLobby.stories.tsx b/ts/components/CallingLobby.stories.tsx index 1540ff468dc..983ee1c8355 100644 --- a/ts/components/CallingLobby.stories.tsx +++ b/ts/components/CallingLobby.stories.tsx @@ -67,7 +67,7 @@ const createProps = (overrideProps: Partial = {}): PropsType => { i18n, isAdhocAdminApprovalRequired: overrideProps.isAdhocAdminApprovalRequired ?? false, - isAdhocJoinRequestPending: false, + isAdhocJoinRequestPending: overrideProps.isAdhocJoinRequestPending ?? false, isConversationTooBigToRing: false, isCallFull: overrideProps.isCallFull ?? false, isSharingPhoneNumberWithEverybody: @@ -237,3 +237,12 @@ export function CallLinkAdminApproval(): JSX.Element { }); return ; } + +export function CallLinkJoinRequestPending(): JSX.Element { + const props = createProps({ + callMode: CallMode.Adhoc, + isAdhocAdminApprovalRequired: true, + isAdhocJoinRequestPending: true, + }); + return ; +} diff --git a/ts/components/CallingLobby.tsx b/ts/components/CallingLobby.tsx index c2838a62dda..da0abc4e6bf 100644 --- a/ts/components/CallingLobby.tsx +++ b/ts/components/CallingLobby.tsx @@ -28,6 +28,8 @@ import type { ConversationType } from '../state/ducks/conversations'; import { useCallingToasts } from './CallingToast'; import { CallingButtonToastsContainer } from './CallingToastManager'; import { isGroupOrAdhocCallMode } from '../util/isGroupOrAdhocCall'; +import { Button, ButtonVariant } from './Button'; +import { SpinnerV2 } from './SpinnerV2'; export type PropsType = { availableCameras: Array; @@ -211,6 +213,9 @@ export function CallingLobby({ } const canJoin = !isCallFull && !isCallConnecting && isOnline; + const canLeave = + (isAdhocAdminApprovalRequired && isCallConnecting) || + isAdhocJoinRequestPending; let callingLobbyJoinButtonVariant: CallingLobbyJoinButtonVariant; if (isCallFull) { @@ -306,7 +311,16 @@ export function CallingLobby({ {i18n('icu:calling__your-video-is-off')} - {callMode === CallMode.Adhoc && ( + {callMode === CallMode.Adhoc && isAdhocJoinRequestPending ? ( +
+ + {i18n('icu:CallingLobby__CallLinkNotice--join-request-pending')} +
+ ) : (
{isSharingPhoneNumberWithEverybody ? i18n('icu:CallingLobby__CallLinkNotice--phone-sharing') @@ -350,15 +364,25 @@ export function CallingLobby({ />
- { - setIsCallConnecting(true); - onJoinCall(); - }} - variant={callingLobbyJoinButtonVariant} - /> + {canLeave ? ( + + ) : ( + { + setIsCallConnecting(true); + onJoinCall(); + }} + variant={callingLobbyJoinButtonVariant} + /> + )}
diff --git a/ts/components/SpinnerV2.tsx b/ts/components/SpinnerV2.tsx new file mode 100644 index 00000000000..4cf51c952d4 --- /dev/null +++ b/ts/components/SpinnerV2.tsx @@ -0,0 +1,40 @@ +// Copyright 2024 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only + +import React from 'react'; +import classNames from 'classnames'; + +export const SpinnerSvgSizes = ['small', 'normal'] as const; +export type SpinnerSvgSize = typeof SpinnerSvgSizes[number]; + +export type Props = { + className?: string; + size: number; + strokeWidth: number; +}; + +export function SpinnerV2({ + className, + size, + strokeWidth, +}: Props): JSX.Element { + return ( + + + + ); +}