diff --git a/public/locales/en-GB/app.json b/public/locales/en-GB/app.json
index ef330e6..7d4ae7b 100644
--- a/public/locales/en-GB/app.json
+++ b/public/locales/en-GB/app.json
@@ -117,7 +117,7 @@
"This call already exists, would you like to join?": "This call already exists, would you like to join?",
"This site is protected by ReCAPTCHA and the Google <2>Privacy Policy2> and <6>Terms of Service6> apply.<9>9>By clicking \"Register\", you agree to our <12>Terms and conditions12>": "This site is protected by ReCAPTCHA and the Google <2>Privacy Policy2> and <6>Terms of Service6> apply.<9>9>By clicking \"Register\", you agree to our <12>Terms and conditions12>",
"This will make a speaker's audio seem as if it is coming from where their tile is positioned on screen. (Experimental feature: this may impact the stability of audio.)": "This will make a speaker's audio seem as if it is coming from where their tile is positioned on screen. (Experimental feature: this may impact the stability of audio.)",
- "This will send anonymized data (such as the duration of a call and the number of participants) to the element call team to help us optimise the application based on how it is used.": "This will send anonymized data (such as the duration of a call and the number of participants) to the element call team to help us optimise the application based on how it is used.",
+ "This will send anonymised data (such as the duration of a call and the number of participants) to the Element Call team to help us optimise the application based on how it is used.": "This will send anonymised data (such as the duration of a call and the number of participants) to the Element Call team to help us optimise the application based on how it is used.",
"Turn off camera": "Turn off camera",
"Turn on camera": "Turn on camera",
"Unmute microphone": "Unmute microphone",
diff --git a/scripts/dockerbuild.sh b/scripts/dockerbuild.sh
index 7dce8f6..cda60c2 100755
--- a/scripts/dockerbuild.sh
+++ b/scripts/dockerbuild.sh
@@ -7,7 +7,6 @@ export VITE_PRODUCT_NAME="Element Call"
git clone https://github.com/matrix-org/matrix-js-sdk.git
cd matrix-js-sdk
-git checkout robertlong/group-call
yarn install
yarn run build
yarn link
diff --git a/src/input/Input.tsx b/src/input/Input.tsx
index cd7603f..acec7d3 100644
--- a/src/input/Input.tsx
+++ b/src/input/Input.tsx
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
-import React, { ChangeEvent, FC, forwardRef, ReactNode } from "react";
+import React, { ChangeEvent, FC, forwardRef, ReactNode, useId } from "react";
import classNames from "classnames";
import styles from "./Input.module.css";
@@ -96,6 +96,8 @@ export const InputField = forwardRef<
},
ref
) => {
+ const descriptionId = useId();
+
return (
}
disabled={disabled}
+ aria-describedby={descriptionId}
{...rest}
/>
) : (
@@ -122,6 +125,7 @@ export const InputField = forwardRef<
type={type}
checked={checked}
disabled={disabled}
+ aria-describedby={descriptionId}
{...rest}
/>
)}
@@ -135,7 +139,11 @@ export const InputField = forwardRef<
{label}
{suffix && {suffix}}
- {description && {description}
}
+ {description && (
+
+ {description}
+
+ )}
);
}
diff --git a/src/settings/SettingsModal.tsx b/src/settings/SettingsModal.tsx
index cb7acb2..f895538 100644
--- a/src/settings/SettingsModal.tsx
+++ b/src/settings/SettingsModal.tsx
@@ -159,7 +159,7 @@ export const SettingsModal = (props: Props) => {
type="checkbox"
checked={optInAnalytics}
description={t(
- "This will send anonymized data (such as the duration of a call and the number of participants) to the element call team to help us optimise the application based on how it is used."
+ "This will send anonymised data (such as the duration of a call and the number of participants) to the Element Call team to help us optimise the application based on how it is used."
)}
onChange={(event: React.ChangeEvent) =>
setOptInAnalytics(event.target.checked)
diff --git a/src/video-grid/VideoTileContainer.tsx b/src/video-grid/VideoTileContainer.tsx
index cb93dbd..0478bb4 100644
--- a/src/video-grid/VideoTileContainer.tsx
+++ b/src/video-grid/VideoTileContainer.tsx
@@ -71,8 +71,8 @@ export function VideoTileContainer({
stream ?? null,
audioContext,
audioDestination,
- isLocal,
- localVolume
+ localVolume,
+ isLocal || maximised
);
const {
modalState: videoTileSettingsModalState,
diff --git a/src/video-grid/useMediaStream.ts b/src/video-grid/useMediaStream.ts
index 61c6524..d1879bd 100644
--- a/src/video-grid/useMediaStream.ts
+++ b/src/video-grid/useMediaStream.ts
@@ -20,6 +20,7 @@ import {
acquireContext,
releaseContext,
} from "matrix-js-sdk/src/webrtc/audioContext";
+import { logger } from "matrix-js-sdk/src/logger";
import { useSpatialAudio } from "../settings/useSetting";
import { useEventTarget } from "../useEvents";
@@ -213,10 +214,10 @@ export const useSpatialMediaStream = (
stream: MediaStream | null,
audioContext: AudioContext,
audioDestination: AudioNode,
- mute = false,
- localVolume?: number
+ localVolume: number,
+ mute = false
): [RefObject, RefObject] => {
- const tileRef = useRef();
+ const tileRef = useRef(null);
const [spatialAudio] = useSpatialAudio();
// We always handle audio separately form the video element
const mediaRef = useMediaStream(stream, null, true);
@@ -227,53 +228,63 @@ export const useSpatialMediaStream = (
const sourceRef = useRef();
useEffect(() => {
- if (spatialAudio && tileRef.current && !mute && audioTrackCount > 0) {
- if (!pannerNodeRef.current) {
- pannerNodeRef.current = new PannerNode(audioContext, {
- panningModel: "HRTF",
- refDistance: 3,
- });
+ if (spatialAudio) {
+ if (tileRef.current && !mute && audioTrackCount > 0) {
+ logger.debug(`Rendering spatial audio for ${stream!.id}`);
+
+ if (!pannerNodeRef.current) {
+ pannerNodeRef.current = new PannerNode(audioContext, {
+ panningModel: "HRTF",
+ refDistance: 3,
+ });
+ }
+ if (!gainNodeRef.current) {
+ gainNodeRef.current = new GainNode(audioContext, {
+ gain: localVolume,
+ });
+ }
+ if (!sourceRef.current || sourceRef.current.mediaStream !== stream!) {
+ sourceRef.current = audioContext.createMediaStreamSource(stream!);
+ }
+
+ const tile = tileRef.current;
+ const source = sourceRef.current;
+ const gainNode = gainNodeRef.current;
+ const pannerNode = pannerNodeRef.current;
+
+ const updatePosition = () => {
+ const bounds = tile.getBoundingClientRect();
+ const windowSize = Math.max(window.innerWidth, window.innerHeight);
+ // Position the source relative to its placement in the window
+ pannerNodeRef.current!.positionX.value =
+ (bounds.x + bounds.width / 2) / windowSize - 0.5;
+ pannerNodeRef.current!.positionY.value =
+ (bounds.y + bounds.height / 2) / windowSize - 0.5;
+ // Put the source in front of the listener
+ pannerNodeRef.current!.positionZ.value = -2;
+ };
+
+ gainNode.gain.value = localVolume;
+ updatePosition();
+ source.connect(gainNode).connect(pannerNode).connect(audioDestination);
+ // HACK: We abuse the CSS transitionrun event to detect when the tile
+ // moves, because useMeasure, IntersectionObserver, etc. all have no
+ // ability to track changes in the CSS transform property
+ tile.addEventListener("transitionrun", updatePosition);
+
+ return () => {
+ tile.removeEventListener("transitionrun", updatePosition);
+ source.disconnect();
+ gainNode.disconnect();
+ pannerNode.disconnect();
+ };
+ } else if (stream) {
+ logger.debug(
+ `Not rendering spatial audio for ${stream.id} (tile ref ${Boolean(
+ tileRef.current
+ )}, mute ${mute}, track count ${audioTrackCount})`
+ );
}
- if (!gainNodeRef.current) {
- gainNodeRef.current = new GainNode(audioContext, {
- gain: localVolume,
- });
- }
- if (!sourceRef.current) {
- sourceRef.current = audioContext.createMediaStreamSource(stream!);
- }
-
- const tile = tileRef.current;
- const source = sourceRef.current;
- const gainNode = gainNodeRef.current;
- const pannerNode = pannerNodeRef.current;
-
- const updatePosition = () => {
- const bounds = tile.getBoundingClientRect();
- const windowSize = Math.max(window.innerWidth, window.innerHeight);
- // Position the source relative to its placement in the window
- pannerNodeRef.current!.positionX.value =
- (bounds.x + bounds.width / 2) / windowSize - 0.5;
- pannerNodeRef.current!.positionY.value =
- (bounds.y + bounds.height / 2) / windowSize - 0.5;
- // Put the source in front of the listener
- pannerNodeRef.current!.positionZ.value = -2;
- };
-
- gainNode.gain.value = localVolume;
- updatePosition();
- source.connect(gainNode).connect(pannerNode).connect(audioDestination);
- // HACK: We abuse the CSS transitionrun event to detect when the tile
- // moves, because useMeasure, IntersectionObserver, etc. all have no
- // ability to track changes in the CSS transform property
- tile.addEventListener("transitionrun", updatePosition);
-
- return () => {
- tile.removeEventListener("transitionrun", updatePosition);
- source.disconnect();
- gainNode.disconnect();
- pannerNode.disconnect();
- };
}
}, [
stream,