mirror of
https://github.com/vector-im/element-call.git
synced 2026-05-19 10:54:36 +00:00
translation fixes
This commit is contained in:
@@ -204,6 +204,7 @@
|
||||
"change_device_button": "Change audio device",
|
||||
"default": "Default",
|
||||
"default_named": "Default <2>({{name}})</2>",
|
||||
"default_numbered": "Default {{n}}",
|
||||
"handset": "Handset",
|
||||
"loudspeaker": "Loudspeaker",
|
||||
"microphone": "Microphone",
|
||||
|
||||
@@ -98,7 +98,6 @@ export const Default: Story = {
|
||||
selectedVideo: undefined,
|
||||
selectAudioButtonOption: undefined,
|
||||
selectVideoButtonOption: undefined,
|
||||
videoToggles: [],
|
||||
},
|
||||
parameters: {
|
||||
layout: "fullscreen",
|
||||
@@ -135,12 +134,12 @@ export const WithAudioAndVideoOptions: Story = {
|
||||
audioEnabled: false,
|
||||
videoEnabled: true,
|
||||
audioOptions: [
|
||||
{ label: "Microphone 1", id: "1" },
|
||||
{ label: "Microphone 2", id: "2" },
|
||||
{ label: { type: "name", name: "Microphone 1" }, id: "1" },
|
||||
{ label: { type: "name", name: "Microphone 2" }, id: "2" },
|
||||
],
|
||||
videoOptions: [
|
||||
{ label: "Camera 1", id: "1" },
|
||||
{ label: "Camera 2", id: "2" },
|
||||
{ label: { type: "name", name: "Camera 1" }, id: "1" },
|
||||
{ label: { type: "name", name: "Camera 2" }, id: "2" },
|
||||
],
|
||||
selectedAudio: "2",
|
||||
selectedVideo: "1",
|
||||
|
||||
@@ -123,11 +123,29 @@ describe("createCallFooterViewModel", () => {
|
||||
);
|
||||
|
||||
expect(vm.audioOptions$?.value).toEqual([
|
||||
{ id: "mic1", label: "Audio Device 1" },
|
||||
{ id: "mic2", label: "Microphone 2" },
|
||||
{
|
||||
id: "mic1",
|
||||
label: {
|
||||
number: 1,
|
||||
type: "number",
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "mic2",
|
||||
label: {
|
||||
name: "Microphone 2",
|
||||
type: "name",
|
||||
},
|
||||
},
|
||||
]);
|
||||
expect(vm.videoOptions$?.value).toEqual([
|
||||
{ id: "cam1", label: "Camera 1" },
|
||||
{
|
||||
id: "cam1",
|
||||
label: {
|
||||
name: "Camera 1",
|
||||
type: "name",
|
||||
},
|
||||
},
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -11,7 +11,6 @@ import { supportsBackgroundProcessors } from "@livekit/track-processors";
|
||||
import { type CallViewModel } from "../state/CallViewModel/CallViewModel";
|
||||
import { type MenuOptions } from "./MediaMuteAndSwitchButton";
|
||||
import { type MediaDevices } from "../state/MediaDevices";
|
||||
import { mediaDeviceLabelToString } from "../settings/DeviceSelection";
|
||||
import {
|
||||
backgroundBlur as backgroundBlurSettings,
|
||||
debugTileLayout as debugTileLayoutSetting,
|
||||
@@ -77,10 +76,7 @@ function buildDeviceBehaviors(
|
||||
map((available) =>
|
||||
[...available.entries()].map(([id, label]) => ({
|
||||
id,
|
||||
label: mediaDeviceLabelToString(
|
||||
label,
|
||||
(n) => "Audio Device " + n,
|
||||
),
|
||||
label,
|
||||
})),
|
||||
),
|
||||
),
|
||||
@@ -100,10 +96,7 @@ function buildDeviceBehaviors(
|
||||
map((available) =>
|
||||
[...available.entries()].map(([id, label]) => ({
|
||||
id,
|
||||
label: mediaDeviceLabelToString(
|
||||
label,
|
||||
(n) => "Camera " + n,
|
||||
),
|
||||
label,
|
||||
})),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -23,8 +23,8 @@ export const Default: Story = {
|
||||
iconsAndLabels: "audio",
|
||||
enabled: true,
|
||||
options: [
|
||||
{ label: "option 1", id: "1" },
|
||||
{ label: "option 2", id: "2" },
|
||||
{ label: { type: "name", name: "Option 1" }, id: "1" },
|
||||
{ label: { type: "name", name: "Option 2" }, id: "2" },
|
||||
],
|
||||
selectedOption: "1",
|
||||
onMuteClick: fn(),
|
||||
@@ -39,16 +39,11 @@ export const AudioMute: Story = {
|
||||
iconsAndLabels: "audio",
|
||||
enabled: false,
|
||||
options: [
|
||||
{ label: "Microphone 1", id: "1" },
|
||||
{ label: "Microphone 2", id: "2" },
|
||||
],
|
||||
toggles: [
|
||||
{
|
||||
label: "example toggle",
|
||||
id: "t0",
|
||||
enabled: true,
|
||||
},
|
||||
{ label: { type: "name", name: "Microphone 1" }, id: "1" },
|
||||
{ label: { type: "name", name: "Microphone 2" }, id: "2" },
|
||||
],
|
||||
videoBlurEnabled: true,
|
||||
backgroundBlurToggleClick: fn(),
|
||||
selectedOption: "2",
|
||||
},
|
||||
play: async ({ args, canvasElement }) => {
|
||||
@@ -67,10 +62,10 @@ export const AudioUnmute: Story = {
|
||||
iconsAndLabels: "audio",
|
||||
enabled: true,
|
||||
options: [
|
||||
{ label: "Microphone 1", id: "1" },
|
||||
{ label: "Microphone 2", id: "2" },
|
||||
{ label: { type: "name", name: "Microphone 1" }, id: "1" },
|
||||
{ label: { type: "name", name: "Microphone 2" }, id: "2" },
|
||||
],
|
||||
toggles: [],
|
||||
|
||||
selectedOption: "2",
|
||||
},
|
||||
};
|
||||
@@ -81,10 +76,10 @@ export const VideoMute: Story = {
|
||||
iconsAndLabels: "video",
|
||||
enabled: false,
|
||||
options: [
|
||||
{ label: "Camera 1", id: "1" },
|
||||
{ label: "Camera 2", id: "2" },
|
||||
{ label: { type: "name", name: "Camera 1" }, id: "1" },
|
||||
{ label: { type: "name", name: "Camera 2" }, id: "2" },
|
||||
],
|
||||
toggles: [],
|
||||
|
||||
selectedOption: "1",
|
||||
},
|
||||
};
|
||||
@@ -95,16 +90,11 @@ export const VideoUnmute: Story = {
|
||||
iconsAndLabels: "video",
|
||||
enabled: true,
|
||||
options: [
|
||||
{ label: "Camera 1", id: "1" },
|
||||
{ label: "Camera 2", id: "2" },
|
||||
],
|
||||
toggles: [
|
||||
{
|
||||
label: "Background blur",
|
||||
id: "background_blurring",
|
||||
enabled: false,
|
||||
},
|
||||
{ label: { type: "name", name: "Camera 1" }, id: "1" },
|
||||
{ label: { type: "name", name: "Camera 2" }, id: "2" },
|
||||
],
|
||||
videoBlurEnabled: true,
|
||||
backgroundBlurToggleClick: fn(),
|
||||
selectedOption: "2",
|
||||
},
|
||||
};
|
||||
|
||||
@@ -86,8 +86,8 @@ describe("MediaMuteAndSwitchButton", () => {
|
||||
iconsAndLabels="audio"
|
||||
enabled={true}
|
||||
options={[
|
||||
{ label: "Microphone 1", id: "mic1" },
|
||||
{ label: "Microphone 2", id: "mic2" },
|
||||
{ label: { type: "name", name: "Microphone 1" }, id: "mic1" },
|
||||
{ label: { type: "name", name: "Microphone 2" }, id: "mic2" },
|
||||
]}
|
||||
selectedOption="mic1"
|
||||
onSelect={onSelect}
|
||||
@@ -110,8 +110,8 @@ describe("MediaMuteAndSwitchButton", () => {
|
||||
iconsAndLabels="audio"
|
||||
enabled={true}
|
||||
options={[
|
||||
{ label: "Microphone 1", id: "mic1" },
|
||||
{ label: "Microphone 2", id: "mic2" },
|
||||
{ label: { type: "name", name: "Microphone 1" }, id: "mic1" },
|
||||
{ label: { type: "name", name: "Microphone 2" }, id: "mic2" },
|
||||
]}
|
||||
selectedOption="mic1"
|
||||
onSelect={onSelect}
|
||||
@@ -139,8 +139,8 @@ describe("MediaMuteAndSwitchButton", () => {
|
||||
iconsAndLabels="audio"
|
||||
enabled={true}
|
||||
options={[
|
||||
{ label: "Microphone 1", id: "mic1" },
|
||||
{ label: "Microphone 2", id: "mic2" },
|
||||
{ label: { type: "name", name: "Microphone 1" }, id: "mic1" },
|
||||
{ label: { type: "name", name: "Microphone 2" }, id: "mic2" },
|
||||
]}
|
||||
selectedOption={selectedOption}
|
||||
onSelect={(id) => {
|
||||
@@ -222,8 +222,8 @@ describe("MediaMuteAndSwitchButton", () => {
|
||||
iconsAndLabels="audio"
|
||||
enabled={true}
|
||||
options={[
|
||||
{ label: "Microphone 1", id: "mic1" },
|
||||
{ label: "Microphone 2", id: "mic2" },
|
||||
{ label: { type: "name", name: "Microphone 1" }, id: "mic1" },
|
||||
{ label: { type: "name", name: "Microphone 2" }, id: "mic2" },
|
||||
]}
|
||||
selectedOption="mic2"
|
||||
/>
|
||||
|
||||
@@ -12,7 +12,6 @@ import {
|
||||
MenuItem,
|
||||
ToggleMenuItem,
|
||||
} from "@vector-im/compound-web";
|
||||
import { t } from "i18next";
|
||||
import {
|
||||
CheckIcon,
|
||||
ChevronUpIcon,
|
||||
@@ -22,12 +21,14 @@ import {
|
||||
VideoCallIcon,
|
||||
} from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
import classNames from "classnames";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import styles from "./MediaMuteAndSwitchButton.module.css";
|
||||
import { MicButton, VideoButton } from "../button";
|
||||
import { type DeviceLabel } from "../state/MediaDevices";
|
||||
|
||||
export interface MenuOptions {
|
||||
label: string;
|
||||
label: DeviceLabel;
|
||||
id: string;
|
||||
}
|
||||
|
||||
@@ -67,7 +68,7 @@ export const MediaMuteAndSwitchButton: FC<MediaMuteAndSwitchButtonProps> = ({
|
||||
}) => {
|
||||
const [plannedSelection, setPlannedSelection] = useState<string | null>(null);
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
|
||||
const { t } = useTranslation();
|
||||
let button;
|
||||
let toggles =
|
||||
backgroundBlurToggleClick === undefined
|
||||
@@ -152,35 +153,45 @@ export const MediaMuteAndSwitchButton: FC<MediaMuteAndSwitchButtonProps> = ({
|
||||
/>
|
||||
}
|
||||
>
|
||||
{options?.map((option) => (
|
||||
<MenuItem
|
||||
hideChevron
|
||||
label={option.label}
|
||||
Icon={
|
||||
IconOptions && (
|
||||
<IconOptions
|
||||
width={24}
|
||||
height={24}
|
||||
className={styles.itemIcon}
|
||||
/>
|
||||
)
|
||||
{options?.map(({ label, id }) => {
|
||||
const labelText = ((): string => {
|
||||
switch (label.type) {
|
||||
case "name":
|
||||
return label.name;
|
||||
case "number":
|
||||
return t("settings.devices.default_numbered", {
|
||||
n: label.number,
|
||||
});
|
||||
}
|
||||
onSelect={(e) => {
|
||||
e.preventDefault();
|
||||
if (option.id === selectedOption) return;
|
||||
setPlannedSelection(option.id);
|
||||
onSelect?.(option.id);
|
||||
}}
|
||||
key={option.id}
|
||||
>
|
||||
{selectedOption === option.id && (
|
||||
<CheckIcon width={24} height={24} />
|
||||
)}
|
||||
{selectedOption !== option.id && plannedSelection === option.id && (
|
||||
<SpinnerIcon width={24} height={24} className={styles.rotate} />
|
||||
)}
|
||||
</MenuItem>
|
||||
))}
|
||||
})();
|
||||
return (
|
||||
<MenuItem
|
||||
hideChevron
|
||||
label={labelText}
|
||||
Icon={
|
||||
IconOptions && (
|
||||
<IconOptions
|
||||
width={24}
|
||||
height={24}
|
||||
className={styles.itemIcon}
|
||||
/>
|
||||
)
|
||||
}
|
||||
onSelect={(e) => {
|
||||
e.preventDefault();
|
||||
if (id === selectedOption) return;
|
||||
setPlannedSelection(id);
|
||||
onSelect?.(id);
|
||||
}}
|
||||
key={id}
|
||||
>
|
||||
{selectedOption === id && <CheckIcon width={24} height={24} />}
|
||||
{selectedOption !== id && plannedSelection === id && (
|
||||
<SpinnerIcon width={24} height={24} className={styles.rotate} />
|
||||
)}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
{(toggles?.length ?? 0) > 0 && <hr />}
|
||||
{toggles?.map((toggle) => (
|
||||
<ToggleMenuItem
|
||||
|
||||
@@ -94,7 +94,7 @@ const logger = rootLogger.getChild("[InCallView]");
|
||||
|
||||
export interface ActiveCallProps extends Omit<
|
||||
InCallViewProps,
|
||||
"vm" | "livekitRoom" | "connState"
|
||||
"vm" | "livekitRoom" | "connState" | "footerVm"
|
||||
> {
|
||||
e2eeSystem: EncryptionSystem;
|
||||
// TODO refactor those reasons into an enum
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
Separator,
|
||||
} from "@vector-im/compound-web";
|
||||
import { useObservableEagerState } from "observable-hooks";
|
||||
import { t } from "i18next";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import {
|
||||
type AudioOutputDeviceLabel,
|
||||
@@ -30,42 +30,11 @@ interface Props {
|
||||
numberedLabel: (number: number) => string;
|
||||
}
|
||||
|
||||
export function mediaDeviceLabelToString(
|
||||
label: DeviceLabel | AudioOutputDeviceLabel,
|
||||
numberedLabel: (number: number) => string,
|
||||
): string {
|
||||
let labelText = "";
|
||||
switch (label.type) {
|
||||
case "name":
|
||||
labelText = label.name;
|
||||
break;
|
||||
case "number":
|
||||
labelText = numberedLabel(label.number);
|
||||
break;
|
||||
case "default":
|
||||
labelText =
|
||||
label.name === null
|
||||
? t("settings.devices.default")
|
||||
: t("settings.devices.default_named", { name: label.name });
|
||||
break;
|
||||
case "speaker":
|
||||
labelText = t("settings.devices.loudspeaker");
|
||||
break;
|
||||
case "earpiece":
|
||||
labelText = t("settings.devices.handset");
|
||||
break;
|
||||
}
|
||||
return labelText;
|
||||
}
|
||||
|
||||
export const DeviceSelection: FC<Props> = ({
|
||||
device,
|
||||
title,
|
||||
numberedLabel,
|
||||
}) => {
|
||||
export const DeviceSelection: FC<Props> = ({ device, title }) => {
|
||||
const groupId = useId();
|
||||
const available = useObservableEagerState(device.available$);
|
||||
const selectedId = useObservableEagerState(device.selected$)?.id;
|
||||
const { t } = useTranslation();
|
||||
const onChange = useCallback(
|
||||
(e: ChangeEvent<HTMLInputElement>) => {
|
||||
device.select(e.target.value);
|
||||
@@ -90,7 +59,24 @@ export const DeviceSelection: FC<Props> = ({
|
||||
<Separator className={styles.separator} />
|
||||
<div className={styles.options}>
|
||||
{[...available].map(([id, label]) => {
|
||||
const labelText = mediaDeviceLabelToString(label, numberedLabel);
|
||||
const labelText = ((): string => {
|
||||
switch (label.type) {
|
||||
case "name":
|
||||
return label.name;
|
||||
case "number":
|
||||
return t("settings.devices.default_numbered", {
|
||||
n: label.number,
|
||||
});
|
||||
case "default":
|
||||
return label.name === null
|
||||
? t("settings.devices.default")
|
||||
: t("settings.devices.default_named", label.name);
|
||||
case "speaker":
|
||||
return t("settings.devices.loudspeaker");
|
||||
case "earpiece":
|
||||
return t("settings.devices.handset");
|
||||
}
|
||||
})();
|
||||
return (
|
||||
<InlineField
|
||||
key={id}
|
||||
|
||||
Reference in New Issue
Block a user