diff --git a/public/locales/en-GB/app.json b/public/locales/en-GB/app.json
index 809f5e4..fe52c85 100644
--- a/public/locales/en-GB/app.json
+++ b/public/locales/en-GB/app.json
@@ -16,13 +16,12 @@
"<0>Why not finish by setting up a password to keep your account?0><1>You'll be able to keep your name and set an avatar for use on future calls1>": "<0>Why not finish by setting up a password to keep your account?0><1>You'll be able to keep your name and set an avatar for use on future calls1>",
"Accept camera/microphone permissions to join the call.": "Accept camera/microphone permissions to join the call.",
"Accept microphone permissions to join the call.": "Accept microphone permissions to join the call.",
- "Advanced": "Advanced",
- "Allow analytics": "Allow analytics",
"Another user on this call is having an issue. In order to better diagnose these issues we'd like to collect a debug log.": "Another user on this call is having an issue. In order to better diagnose these issues we'd like to collect a debug log.",
"Audio": "Audio",
"Avatar": "Avatar",
"By clicking \"Go\", you agree to our <2>Terms and conditions2>": "By clicking \"Go\", you agree to our <2>Terms and conditions2>",
"By clicking \"Join call now\", you agree to our <2>Terms and conditions2>": "By clicking \"Join call now\", you agree to our <2>Terms and conditions2>",
+ "By ticking this box you consent to the collection of anonymous data, which we use to improve your experience. You can find more information about which data we track in our ": "By ticking this box you consent to the collection of anonymous data, which we use to improve your experience. You can find more information about which data we track in our ",
"Call link copied": "Call link copied",
"Call type menu": "Call type menu",
"Camera": "Camera",
@@ -41,10 +40,12 @@
"Description (optional)": "Description (optional)",
"Details": "Details",
"Developer": "Developer",
+ "Developer Settings": "Developer Settings",
"Display name": "Display name",
"Download debug logs": "Download debug logs",
"Element Call Home": "Element Call Home",
"Exit full screen": "Exit full screen",
+ "Expose developer settings in the settings window.": "Expose developer settings in the settings window.",
"Fetching group call timed out.": "Fetching group call timed out.",
"Freedom": "Freedom",
"Full screen": "Full screen",
@@ -84,6 +85,7 @@
"Press and hold spacebar to talk over {{name}}": "Press and hold spacebar to talk over {{name}}",
"Press and hold to talk": "Press and hold to talk",
"Press and hold to talk over {{name}}": "Press and hold to talk over {{name}}",
+ "Privacy Policy": "Privacy Policy",
"Profile": "Profile",
"Recaptcha dismissed": "Recaptcha dismissed",
"Recaptcha not loaded": "Recaptcha not loaded",
@@ -120,7 +122,6 @@
"This feature is only supported on Firefox.": "This feature is only supported on Firefox.",
"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 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/src/ClientContext.tsx b/src/ClientContext.tsx
index fa83f5d..46dfe5a 100644
--- a/src/ClientContext.tsx
+++ b/src/ClientContext.tsx
@@ -36,7 +36,10 @@ import {
fallbackICEServerAllowed,
} from "./matrix-utils";
import { widget } from "./widget";
-import { PosthogAnalytics, RegistrationType } from "./PosthogAnalytics";
+import {
+ PosthogAnalytics,
+ RegistrationType,
+} from "./analytics/PosthogAnalytics";
import { translatedError } from "./TranslatedError";
import { useEventTarget } from "./useEvents";
import { Config } from "./config/Config";
diff --git a/src/analytics/AnalyticsOptInDescription.tsx b/src/analytics/AnalyticsOptInDescription.tsx
new file mode 100644
index 0000000..46727f5
--- /dev/null
+++ b/src/analytics/AnalyticsOptInDescription.tsx
@@ -0,0 +1,20 @@
+import { t } from "i18next";
+import React from "react";
+
+import { Link } from "../typography/Typography";
+
+export const optInDescription: () => JSX.Element = () => {
+ return (
+ <>
+ <>
+ {t(
+ "By ticking this box you consent to the collection of anonymous data, which we use to improve your experience. You can find more information about which data we track in our "
+ )}
+ >
+
+ <>{t("Privacy Policy")}>
+
+ .
+ >
+ );
+};
diff --git a/src/PosthogAnalytics.ts b/src/analytics/PosthogAnalytics.ts
similarity index 98%
rename from src/PosthogAnalytics.ts
rename to src/analytics/PosthogAnalytics.ts
index 4e91a6d..e2e8fda 100644
--- a/src/PosthogAnalytics.ts
+++ b/src/analytics/PosthogAnalytics.ts
@@ -19,8 +19,8 @@ import { logger } from "matrix-js-sdk/src/logger";
import { MatrixClient } from "matrix-js-sdk";
import { Buffer } from "buffer";
-import { widget } from "./widget";
-import { getSetting, setSetting, settingsBus } from "./settings/useSetting";
+import { widget } from "../widget";
+import { getSetting, setSetting, settingsBus } from "../settings/useSetting";
import {
CallEndedTracker,
CallStartedTracker,
@@ -30,8 +30,8 @@ import {
MuteMicrophoneTracker,
UndecryptableToDeviceEventTracker,
} from "./PosthogEvents";
-import { Config } from "./config/Config";
-import { getUrlParams } from "./UrlParams";
+import { Config } from "../config/Config";
+import { getUrlParams } from "../UrlParams";
/* Posthog analytics tracking.
*
diff --git a/src/PosthogEvents.ts b/src/analytics/PosthogEvents.ts
similarity index 100%
rename from src/PosthogEvents.ts
rename to src/analytics/PosthogEvents.ts
diff --git a/src/auth/LoginPage.tsx b/src/auth/LoginPage.tsx
index 88296db..20f6e00 100644
--- a/src/auth/LoginPage.tsx
+++ b/src/auth/LoginPage.tsx
@@ -25,7 +25,7 @@ import { Button } from "../button";
import styles from "./LoginPage.module.css";
import { useInteractiveLogin } from "./useInteractiveLogin";
import { usePageTitle } from "../usePageTitle";
-import { PosthogAnalytics } from "../PosthogAnalytics";
+import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
import { Config } from "../config/Config";
export const LoginPage: FC = () => {
diff --git a/src/auth/RegisterPage.tsx b/src/auth/RegisterPage.tsx
index f5025b8..0464266 100644
--- a/src/auth/RegisterPage.tsx
+++ b/src/auth/RegisterPage.tsx
@@ -38,7 +38,7 @@ import { LoadingView } from "../FullScreenView";
import { useRecaptcha } from "./useRecaptcha";
import { Caption, Link } from "../typography/Typography";
import { usePageTitle } from "../usePageTitle";
-import { PosthogAnalytics } from "../PosthogAnalytics";
+import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
import { Config } from "../config/Config";
export const RegisterPage: FC = () => {
diff --git a/src/home/RegisteredView.tsx b/src/home/RegisteredView.tsx
index b08f22a..a6278c2 100644
--- a/src/home/RegisteredView.tsx
+++ b/src/home/RegisteredView.tsx
@@ -42,6 +42,8 @@ import { JoinExistingCallModal } from "./JoinExistingCallModal";
import { Title } from "../typography/Typography";
import { Form } from "../form/Form";
import { CallType, CallTypeDropdown } from "./CallTypeDropdown";
+import { useOptInAnalytics } from "../settings/useSetting";
+import { optInDescription } from "../analytics/AnalyticsOptInDescription";
interface Props {
client: MatrixClient;
@@ -52,6 +54,7 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) {
const [callType, setCallType] = useState(CallType.Video);
const [loading, setLoading] = useState(false);
const [error, setError] = useState();
+ const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics();
const history = useHistory();
const { t } = useTranslation();
const { modalState, modalProps } = useModalTriggerState();
@@ -141,6 +144,15 @@ export function RegisteredView({ client, isPasswordlessUser }: Props) {
{loading ? t("Loading…") : t("Go")}
+ ) =>
+ setOptInAnalytics(event.target.checked)
+ }
+ />
{error && (
diff --git a/src/home/UnauthenticatedView.tsx b/src/home/UnauthenticatedView.tsx
index 826468b..6339e42 100644
--- a/src/home/UnauthenticatedView.tsx
+++ b/src/home/UnauthenticatedView.tsx
@@ -39,12 +39,15 @@ import { CallType, CallTypeDropdown } from "./CallTypeDropdown";
import styles from "./UnauthenticatedView.module.css";
import commonStyles from "./common.module.css";
import { generateRandomName } from "../auth/generateRandomName";
+import { useOptInAnalytics } from "../settings/useSetting";
+import { optInDescription } from "../analytics/AnalyticsOptInDescription";
export const UnauthenticatedView: FC = () => {
const { setClient } = useClient();
const [callType, setCallType] = useState(CallType.Video);
const [loading, setLoading] = useState(false);
const [error, setError] = useState();
+ const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics();
const [privacyPolicyUrl, recaptchaKey, register] =
useInteractiveRegistration();
const { execute, reset, recaptchaId } = useRecaptcha(recaptchaKey);
@@ -152,6 +155,15 @@ export const UnauthenticatedView: FC = () => {
autoComplete="off"
/>
+ ) =>
+ setOptInAnalytics(event.target.checked)
+ }
+ />
By clicking "Go", you agree to our{" "}
diff --git a/src/input/Input.module.css b/src/input/Input.module.css
index 60b6993..2420cc4 100644
--- a/src/input/Input.module.css
+++ b/src/input/Input.module.css
@@ -209,3 +209,7 @@ limitations under the License.
margin-left: 26px;
width: 100%; /* Ensure that it breaks onto the next row */
}
+
+.description.noLabel {
+ margin-top: -20px; /* Ensures that there is no weired spacing if the checkbox doesn't have a label */
+}
diff --git a/src/input/Input.tsx b/src/input/Input.tsx
index bfc17d7..afecd6a 100644
--- a/src/input/Input.tsx
+++ b/src/input/Input.tsx
@@ -55,14 +55,14 @@ export function Field({ children, className }: FieldProps): JSX.Element {
}
interface InputFieldProps {
- label: string;
+ label?: string;
type: string;
prefix?: string;
suffix?: string;
id?: string;
checked?: boolean;
className?: string;
- description?: string;
+ description?: string | ReactNode;
disabled?: boolean;
required?: boolean;
// this is a hack. Those variables should be part of `HTMLAttributes | HTMLAttributes`
@@ -140,7 +140,14 @@ export const InputField = forwardRef<
{suffix && {suffix}}
{description && (
-
+
{description}
)}
diff --git a/src/room/GroupCallInspector.tsx b/src/room/GroupCallInspector.tsx
index 73b2a00..648a0a1 100644
--- a/src/room/GroupCallInspector.tsx
+++ b/src/room/GroupCallInspector.tsx
@@ -35,7 +35,7 @@ import { CallEvent } from "matrix-js-sdk/src/webrtc/call";
import styles from "./GroupCallInspector.module.css";
import { SelectInput } from "../input/SelectInput";
-import { PosthogAnalytics } from "../PosthogAnalytics";
+import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
interface InspectorContextState {
eventsByUserId?: { [userId: string]: SequenceDiagramMatrixEvent[] };
diff --git a/src/room/GroupCallView.tsx b/src/room/GroupCallView.tsx
index 8867ed4..7af31d6 100644
--- a/src/room/GroupCallView.tsx
+++ b/src/room/GroupCallView.tsx
@@ -32,7 +32,7 @@ import { CallEndedView } from "./CallEndedView";
import { useRoomAvatar } from "./useRoomAvatar";
import { useSentryGroupCallHandler } from "./useSentryGroupCallHandler";
import { useLocationNavigation } from "../useLocationNavigation";
-import { PosthogAnalytics } from "../PosthogAnalytics";
+import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
import { useMediaHandler } from "../settings/useMediaHandler";
import { findDeviceByName, getDevices } from "../media-utils";
diff --git a/src/room/InCallView.tsx b/src/room/InCallView.tsx
index 17a0fde..48b1cbf 100644
--- a/src/room/InCallView.tsx
+++ b/src/room/InCallView.tsx
@@ -63,7 +63,7 @@ import {
import { useModalTriggerState } from "../Modal";
import { useAudioContext } from "../video-grid/useMediaStream";
import { useFullscreen } from "../video-grid/useFullscreen";
-import { PosthogAnalytics } from "../PosthogAnalytics";
+import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
import { widget, ElementWidgetActions } from "../widget";
import { useJoinRule } from "./useJoinRule";
import { useUrlParams } from "../UrlParams";
diff --git a/src/room/useGroupCall.ts b/src/room/useGroupCall.ts
index 9d50987..37484b4 100644
--- a/src/room/useGroupCall.ts
+++ b/src/room/useGroupCall.ts
@@ -29,7 +29,7 @@ import { useTranslation } from "react-i18next";
import { IWidgetApiRequest } from "matrix-widget-api";
import { usePageUnload } from "./usePageUnload";
-import { PosthogAnalytics } from "../PosthogAnalytics";
+import { PosthogAnalytics } from "../analytics/PosthogAnalytics";
import { TranslatedError, translatedError } from "../TranslatedError";
import { ElementWidgetActions, ScreenshareStartData, widget } from "../widget";
diff --git a/src/settings/SettingsModal.module.css b/src/settings/SettingsModal.module.css
index 7eb3915..9b4951b 100644
--- a/src/settings/SettingsModal.module.css
+++ b/src/settings/SettingsModal.module.css
@@ -26,3 +26,12 @@ limitations under the License.
.fieldRowText {
margin-bottom: 0;
}
+
+/*
+This style guarantees a fixed width of the tab bar in the settings window.
+The "Developer" item in the tab bar can be toggled.
+Without a defined width activating the developer tab makes the tab container jump to the right.
+*/
+.tabLabel {
+ width: 80px;
+}
diff --git a/src/settings/SettingsModal.tsx b/src/settings/SettingsModal.tsx
index 244d1d1..90a1cb5 100644
--- a/src/settings/SettingsModal.tsx
+++ b/src/settings/SettingsModal.tsx
@@ -34,11 +34,13 @@ import {
useOptInAnalytics,
canEnableSpatialAudio,
useNewGrid,
+ useDeveloperSettingsTab,
} from "./useSetting";
import { FieldRow, InputField } from "../input/Input";
import { Button } from "../button";
import { useDownloadDebugLog } from "./submit-rageshake";
import { Body } from "../typography/Typography";
+import { optInDescription } from "../analytics/AnalyticsOptInDescription";
interface Props {
isOpen: boolean;
@@ -62,6 +64,8 @@ export const SettingsModal = (props: Props) => {
const [spatialAudio, setSpatialAudio] = useSpatialAudio();
const [showInspector, setShowInspector] = useShowInspector();
const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics();
+ const [developerSettingsTab, setDeveloperSettingsTab] =
+ useDeveloperSettingsTab();
const [keyboardShortcuts, setKeyboardShortcuts] = useKeyboardShortcuts();
const [newGrid, setNewGrid] = useNewGrid();
@@ -80,7 +84,7 @@ export const SettingsModal = (props: Props) => {
title={
<>
- {t("Audio")}
+ {t("Audio")}
>
}
>
@@ -158,24 +162,11 @@ export const SettingsModal = (props: Props) => {
title={
<>
- {t("Advanced")}
+ {t("More")}
>
}
>
-
- ) =>
- setOptInAnalytics(event.target.checked)
- }
- />
-
+