diff --git a/public/locales/en-GB/app.json b/public/locales/en-GB/app.json index 6045ac34..52b63548 100644 --- a/public/locales/en-GB/app.json +++ b/public/locales/en-GB/app.json @@ -148,6 +148,13 @@ "feedback_tab_title": "Feedback", "more_tab_title": "More", "opt_in_description": "<0><1>You may withdraw consent by unchecking this box. If you are currently in a call, this setting will take effect at the end of the call.", + "preferences_tab": { + "reactions_play_sound_description": "Play a sound effect when anyone sends a reaction into a call.", + "reactions_play_sound_label": "Play reaction sounds", + "reactions_show_description": "Show reactions", + "reactions_show_label": "Show an animation when anyone sends a reaction.", + "reactions_title": "Reactions" + }, "preferences_tab_body": "Here you can configure extra options for an improved experience", "preferences_tab_h4": "Preferences", "preferences_tab_show_hand_raised_timer_description": "Show a timer when a participant raises their hand", diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx index 7a113d3d..0f846b53 100644 --- a/src/room/InCallView.tsx +++ b/src/room/InCallView.tsx @@ -86,6 +86,7 @@ import handSoundOgg from "../sound/raise_hand.ogg?url"; import handSoundMp3 from "../sound/raise_hand.mp3?url"; import { ReactionsAudioRenderer } from "./ReactionAudioRenderer"; import { useSwitchCamera } from "./useSwitchCamera"; +import { showReactions, useSetting } from "../settings/settings"; const canScreenshare = "getDisplayMedia" in (navigator.mediaDevices ?? {}); @@ -178,6 +179,7 @@ export const InCallView: FC = ({ connState, onShareClick, }) => { + const [shouldShowReactions] = useSetting(showReactions); const { supportsReactions, raisedHands, reactions } = useReactions(); const raisedHandCount = useMemo( () => Object.keys(raisedHands).length, @@ -187,12 +189,12 @@ export const InCallView: FC = ({ const reactionsIcons = useMemo( () => - Object.entries(reactions).map(([sender, { emoji }]) => ({ + shouldShowReactions ? Object.entries(reactions).map(([sender, { emoji }]) => ({ sender, emoji, startX: -Math.ceil(Math.random() * 50) - 25, - })), - [reactions], + })) : [], + [shouldShowReactions, reactions], ); useWakeLock(); @@ -232,7 +234,7 @@ export const InCallView: FC = ({ containerRef1, toggleMicrophone, toggleCamera, - (muted) => muteStates.audio.setEnabled?.(!muted), + (muted) => muteStates.audio.setEnabled?.(!muteprefered), ); const mobile = boundsValid && bounds.width <= 660; diff --git a/src/room/ReactionAudioRenderer.tsx b/src/room/ReactionAudioRenderer.tsx index 31e8d4bf..104c6a1d 100644 --- a/src/room/ReactionAudioRenderer.tsx +++ b/src/room/ReactionAudioRenderer.tsx @@ -8,12 +8,13 @@ Please see LICENSE in the repository root for full details. import { ReactNode } from "react"; import { useReactions } from "../useReactions"; +import { playReactionsSound, useSetting } from "../settings/settings"; export function ReactionsAudioRenderer(): ReactNode { const { reactions } = useReactions(); + const [shouldPlay] = useSetting(playReactionsSound); - // TODO: This may need to ensure we don't change the value if a duplicate reaction comes down. - const expectedReactions = [...new Set([...Object.values(reactions)])]; + const expectedReactions = shouldPlay ? [...new Set([...Object.values(reactions)])] : []; return ( <> {expectedReactions.map( diff --git a/src/settings/PreferencesSettingsTab.tsx b/src/settings/PreferencesSettingsTab.tsx index 783825e8..dd26ba47 100644 --- a/src/settings/PreferencesSettingsTab.tsx +++ b/src/settings/PreferencesSettingsTab.tsx @@ -12,6 +12,8 @@ import { Text } from "@vector-im/compound-web"; import { FieldRow, InputField } from "../input/Input"; import { showHandRaisedTimer as showHandRaisedTimerSetting, + showReactions as showReactionsSetting, + playReactionsSound as playReactionsSoundSetting, useSetting, } from "./settings"; @@ -21,11 +23,20 @@ export const PreferencesSettingsTab: FC = () => { showHandRaisedTimerSetting, ); + const [showReactions, setShowReactions] = useSetting( + showReactionsSetting, + ); + + const [playReactionsSound, setPlayReactionSound] = useSetting( + playReactionsSoundSetting, + ); + + const onChangeSetting = useCallback( - (e: ChangeEvent) => { - setShowHandRaisedTimer(e.target.checked); + (e: ChangeEvent, fn: (value: boolean) => void) => { + fn(e.target.checked); }, - [setShowHandRaisedTimer], + [], ); return ( @@ -41,7 +52,32 @@ export const PreferencesSettingsTab: FC = () => { )} type="checkbox" checked={showHandRaisedTimer} - onChange={onChangeSetting} + onChange={(e) => onChangeSetting(e, setShowHandRaisedTimer)} + /> + +
{t("settings.preferences_tab.reactions_title")}
+ + onChangeSetting(e, setShowReactions)} + /> + + + onChangeSetting(e, setPlayReactionSound)} /> diff --git a/src/settings/settings.ts b/src/settings/settings.ts index 109a882b..abae8ea0 100644 --- a/src/settings/settings.ts +++ b/src/settings/settings.ts @@ -90,4 +90,14 @@ export const showHandRaisedTimer = new Setting( false, ); +export const showReactions = new Setting( + "reactions-show", + true, +); + +export const playReactionsSound = new Setting( + "reactions-play-sound", + true, +); + export const alwaysShowSelf = new Setting("always-show-self", true);