mirror of
https://github.com/vector-im/element-call.git
synced 2026-04-28 09:44:37 +00:00
fix loudspeaker confusion and icons
This commit is contained in:
@@ -23,6 +23,7 @@ import {
|
||||
OverflowHorizontalIcon,
|
||||
OverflowVerticalIcon,
|
||||
VolumeOnSolidIcon,
|
||||
VolumeOffSolidIcon,
|
||||
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import styles from "./Button.module.css";
|
||||
@@ -134,31 +135,25 @@ export const EndCallButton: FC<EndCallButtonProps> = ({
|
||||
|
||||
interface LoudspeakerButtonProps extends ComponentPropsWithoutRef<"button"> {
|
||||
size?: "sm" | "lg";
|
||||
/** The button will be rendered:
|
||||
* true: currently in loudspeaker mode, pressing will switch to earpiece (rendered as enabled)
|
||||
* false: currently in earpiece mode, pressing will switch to loudspeaker (rendered as disabled)
|
||||
*/
|
||||
isEarpieceTarget: boolean;
|
||||
loudspeakerModeEnabled: boolean;
|
||||
}
|
||||
export const LoudspeakerButton: FC<LoudspeakerButtonProps> = ({
|
||||
isEarpieceTarget,
|
||||
loudspeakerModeEnabled,
|
||||
...props
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const label = isEarpieceTarget
|
||||
? t("settings.devices.handset")
|
||||
: t("settings.devices.loudspeaker");
|
||||
// if the target is the earpice, we are currently in loudspeaker mode.
|
||||
const enabled = isEarpieceTarget;
|
||||
const label = loudspeakerModeEnabled
|
||||
? t("settings.devices.loudspeaker")
|
||||
: t("settings.devices.handset");
|
||||
return (
|
||||
<Tooltip label={label}>
|
||||
<CpdButton
|
||||
iconOnly
|
||||
Icon={VolumeOnSolidIcon}
|
||||
Icon={loudspeakerModeEnabled ? VolumeOnSolidIcon : VolumeOffSolidIcon}
|
||||
{...props}
|
||||
kind={enabled ? "primary" : "secondary"}
|
||||
role="switch"
|
||||
aria-checked={enabled}
|
||||
kind={loudspeakerModeEnabled ? "primary" : "secondary"}
|
||||
aria-checked={loudspeakerModeEnabled}
|
||||
/>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
@@ -54,6 +54,8 @@ export const Default: Story = {
|
||||
args: {
|
||||
hideLogo: true,
|
||||
layoutMode: "grid",
|
||||
audioEnabled: true,
|
||||
videoEnabled: true,
|
||||
setLayoutMode: fn(),
|
||||
openSettings: fn(),
|
||||
toggleAudio: fn(),
|
||||
@@ -73,8 +75,8 @@ export const Default: Story = {
|
||||
mapping: {
|
||||
NoOutputCallback: undefined,
|
||||
// This is inverersed (speaker<->earpice) because the switcher object stores the target output, not the current one.
|
||||
speaker: { targetOutput: "speaker", switch: fn() },
|
||||
earpiece: { targetOutput: "earpiece", switch: fn() },
|
||||
speaker: { targetOutput: "earpiece", switch: fn() },
|
||||
earpiece: { targetOutput: "speaker", switch: fn() },
|
||||
},
|
||||
},
|
||||
toggleScreenSharing: fnArgType,
|
||||
@@ -102,7 +104,16 @@ export const AudioVideoEnabled: Story = {
|
||||
videoEnabled: true,
|
||||
},
|
||||
};
|
||||
export const WithAudioOutput: Story = {
|
||||
|
||||
export const WithAudioOutputSpeaker: Story = {
|
||||
...Default,
|
||||
args: {
|
||||
...Default.args,
|
||||
audioOutputSwitcher: { targetOutput: "earpiece", switch: fn() },
|
||||
},
|
||||
};
|
||||
|
||||
export const WithAudioOutputEarpiece: Story = {
|
||||
...Default,
|
||||
args: {
|
||||
...Default.args,
|
||||
|
||||
@@ -35,6 +35,14 @@ export interface FooterProps {
|
||||
ref?: Ref<HTMLDivElement>;
|
||||
/** Children will only be visible if the component is wider than 5*/
|
||||
children?: JSX.Element | JSX.Element[] | false;
|
||||
|
||||
audioEnabled: boolean;
|
||||
/** Also controls if the audioMute button is disabled */
|
||||
toggleAudio: (() => void) | undefined;
|
||||
videoEnabled: boolean;
|
||||
/** Also controls if the videoMute button is disabled */
|
||||
toggleVideo: (() => void) | undefined;
|
||||
|
||||
/* This is needed for WindowMode = "flat" */
|
||||
hideControls?: boolean;
|
||||
/** hide the entire footer*/
|
||||
@@ -49,13 +57,6 @@ export interface FooterProps {
|
||||
/** Also controls if the layout button is visible */
|
||||
setLayoutMode?: (mode: GridMode) => void;
|
||||
|
||||
audioEnabled?: boolean;
|
||||
/** Also controls if the audioMute button is disabled */
|
||||
toggleAudio?: () => void;
|
||||
videoEnabled?: boolean;
|
||||
/** Also controls if the videoMute button is disabled */
|
||||
toggleVideo?: () => void;
|
||||
|
||||
sharingScreen?: boolean;
|
||||
toggleScreenSharing?: () => void;
|
||||
|
||||
@@ -175,7 +176,7 @@ export const CallFooter: FC<FooterProps> = ({
|
||||
<LoudspeakerButton
|
||||
size={buttonSize}
|
||||
onClick={() => audioOutputSwitcher.switch()}
|
||||
isEarpieceTarget={audioOutputSwitcher.targetOutput === "earpiece"}
|
||||
loudspeakerModeEnabled={audioOutputSwitcher.targetOutput === "earpiece"}
|
||||
/>
|
||||
);
|
||||
}, [audioOutputSwitcher, buttonSize]);
|
||||
|
||||
@@ -253,9 +253,10 @@ describe("InCallView", () => {
|
||||
["earpiece-id", { type: "earpiece" }],
|
||||
]),
|
||||
);
|
||||
const selected$ = new BehaviorSubject<
|
||||
{ id: string; virtualEarpiece: boolean } | undefined
|
||||
>({ id: "speaker-id", virtualEarpiece: false });
|
||||
const selected$ = new BehaviorSubject({
|
||||
id: "speaker-id",
|
||||
virtualEarpiece: false,
|
||||
});
|
||||
|
||||
const mediaDevices = mockMediaDevices({
|
||||
audioOutput: {
|
||||
@@ -267,8 +268,7 @@ describe("InCallView", () => {
|
||||
|
||||
const { getByRole } = createInCallView({ mediaDevices });
|
||||
// The button should be visible. When current output is "speaker",
|
||||
// the switcher targets "earpiece", so the tooltip label is "Handset".
|
||||
const audioOutputBtn = getByRole("switch", { name: "Handset" });
|
||||
const audioOutputBtn = getByRole("button", { name: "Loudspeaker" });
|
||||
expect(audioOutputBtn).toBeVisible();
|
||||
|
||||
await user.click(audioOutputBtn);
|
||||
|
||||
@@ -222,6 +222,8 @@ export const LobbyView: FC<Props> = ({
|
||||
{!recentsButtonInFooter && recentsButton}
|
||||
</div>
|
||||
<CallFooter
|
||||
audioEnabled={audioEnabled}
|
||||
videoEnabled={videoEnabled}
|
||||
toggleAudio={toggleAudio ?? undefined}
|
||||
toggleVideo={toggleVideo ?? undefined}
|
||||
openSettings={openSettings}
|
||||
|
||||
Reference in New Issue
Block a user