Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify settings tabs #2875

Merged
merged 8 commits into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions locales/en/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -150,26 +150,23 @@
"effect_volume_description": "Volume for sound effects such as: joining or leaving a call, and reactions.",
"effect_volume_label": "Sound effect volume"
},
"developer_settings_label": "Developer Settings",
"developer_settings_label_description": "Expose developer settings in the settings window.",
"developer_tab_title": "Developer",
"feedback_tab_body": "If you are experiencing issues or simply would like to provide some feedback, please send us a short description below.",
"feedback_tab_description_label": "Your feedback",
"feedback_tab_h4": "Submit feedback",
"feedback_tab_send_logs_label": "Include debug logs",
"feedback_tab_thank_you": "Thanks, we received your feedback!",
"feedback_tab_title": "Feedback",
"more_tab_title": "More",
"opt_in_description": "<0></0><1></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": {
"developer_mode_label": "Developer Mode",
hughns marked this conversation as resolved.
Show resolved Hide resolved
"developer_mode_label_description": "Enable developer mode and show developer settings 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 an animation when anyone sends a reaction.",
"reactions_show_label": "Show reactions",
"reactions_title": "Reactions"
"reactions_show_label": "Show 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",
"preferences_tab_show_hand_raised_timer_label": "Show hand raise duration",
"speaker_device_selection_label": "Speaker"
Expand Down
75 changes: 75 additions & 0 deletions src/settings/DeveloperSettingsTab.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
/*
Copyright 2022-2024 New Vector Ltd.

SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/

import { ChangeEvent, FC, useCallback } from "react";
import { useTranslation } from "react-i18next";

import { FieldRow, InputField } from "../input/Input";
import {
useSetting,
duplicateTiles as duplicateTilesSetting,
} from "./settings";
import type { MatrixClient } from "matrix-js-sdk/src/client";

interface Props {
client: MatrixClient;
}

export const DeveloperSettingsTab: FC<Props> = ({ client }) => {
const { t } = useTranslation();
const [duplicateTiles, setDuplicateTiles] = useSetting(duplicateTilesSetting);

return (
<>
<p>
{t("developer_mode.hostname", {
hostname: window.location.hostname || "unknown",
})}
</p>
<p>
{t("version", {
productName: import.meta.env.VITE_PRODUCT_NAME || "Element Call",
version: import.meta.env.VITE_APP_VERSION || "dev",
})}
</p>
<p>
{t("developer_mode.crypto_version", {
version: client.getCrypto()?.getVersion() || "unknown",
})}
</p>
<p>
{t("developer_mode.matrix_id", {
id: client.getUserId() || "unknown",
})}
</p>
<p>
{t("developer_mode.device_id", {
id: client.getDeviceId() || "unknown",
})}
</p>
<FieldRow>
<InputField
id="duplicateTiles"
type="number"
label={t("developer_mode.duplicate_tiles_label")}
value={duplicateTiles.toString()}
min={0}
onChange={useCallback(
(event: ChangeEvent<HTMLInputElement>): void => {
const value = event.target.valueAsNumber;
if (value < 0) {
return;
}
setDuplicateTiles(Number.isNaN(value) ? 0 : value);
},
[setDuplicateTiles],
)}
/>
</FieldRow>
</>
);
};
30 changes: 28 additions & 2 deletions src/settings/FeedbackSettingsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@ SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/

import { FC, useCallback } from "react";
import { ChangeEvent, FC, useCallback } from "react";
import { randomString } from "matrix-js-sdk/src/randomstring";
import { useTranslation } from "react-i18next";
import { Trans, useTranslation } from "react-i18next";
import { Button, Text } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";

import { FieldRow, InputField, ErrorMessage } from "../input/Input";
import { useSubmitRageshake, useRageshakeRequest } from "./submit-rageshake";
import feedbackStyles from "../input/FeedbackInput.module.css";
import { AnalyticsNotice } from "../analytics/AnalyticsNotice";
import { useOptInAnalytics } from "./settings";

interface Props {
roomId?: string;
Expand Down Expand Up @@ -52,8 +54,32 @@ export const FeedbackSettingsTab: FC<Props> = ({ roomId }) => {
[submitRageshake, roomId, sendRageshakeRequest],
);

const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics();
const optInDescription = (
<Text size="sm">
<Trans i18nKey="settings.opt_in_description">
<AnalyticsNotice />
<br />
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.
</Trans>
</Text>
);

return (
<div>
<h4>{t("common.analytics")}</h4>
<FieldRow>
<InputField
id="optInAnalytics"
type="checkbox"
checked={optInAnalytics ?? undefined}
description={optInDescription}
onChange={(event: ChangeEvent<HTMLInputElement>): void => {
setOptInAnalytics?.(event.target.checked);
}}
/>
</FieldRow>
<h4>{t("settings.feedback_tab_h4")}</h4>
<Text>{t("settings.feedback_tab_body")}</Text>
<form onSubmit={onSubmitFeedback}>
hughns marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
21 changes: 19 additions & 2 deletions src/settings/PreferencesSettingsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
showHandRaisedTimer as showHandRaisedTimerSetting,
showReactions as showReactionsSetting,
playReactionsSound as playReactionsSoundSetting,
developerSettingsTab as developerSettingsTabSetting,
useSetting,
} from "./settings";

Expand All @@ -36,9 +37,12 @@ export const PreferencesSettingsTab: FC = () => {
fn(e.target.checked);
};

const [developerSettingsTab, setDeveloperSettingsTab] = useSetting(
developerSettingsTabSetting,
);

return (
<div>
<h4>{t("settings.preferences_tab_h4")}</h4>
<Text>{t("settings.preferences_tab_body")}</Text>
<FieldRow>
<InputField
Expand All @@ -52,7 +56,6 @@ export const PreferencesSettingsTab: FC = () => {
onChange={(e) => onChangeSetting(e, setShowHandRaisedTimer)}
/>
</FieldRow>
<h5>{t("settings.preferences_tab.reactions_title")}</h5>
<FieldRow>
<InputField
id="showReactions"
Expand All @@ -75,6 +78,20 @@ export const PreferencesSettingsTab: FC = () => {
onChange={(e) => onChangeSetting(e, setPlayReactionSound)}
/>
</FieldRow>
<FieldRow>
<InputField
id="developerSettingsTab"
type="checkbox"
checked={developerSettingsTab}
label={t("settings.preferences_tab.developer_mode_label")}
description={t(
"settings.preferences_tab.developer_mode_label_description",
)}
onChange={(event: ChangeEvent<HTMLInputElement>): void =>
setDeveloperSettingsTab(event.target.checked)
}
/>
</FieldRow>
</div>
);
};
126 changes: 10 additions & 116 deletions src/settings/SettingsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,14 @@ SPDX-License-Identifier: AGPL-3.0-only
Please see LICENSE in the repository root for full details.
*/

import { ChangeEvent, FC, useCallback, useState } from "react";
import { Trans, useTranslation } from "react-i18next";
import { FC, useState } from "react";
import { useTranslation } from "react-i18next";
import { MatrixClient } from "matrix-js-sdk/src/matrix";
import { Root as Form, Text } from "@vector-im/compound-web";
import { Root as Form } from "@vector-im/compound-web";

import { Modal } from "../Modal";
import styles from "./SettingsModal.module.css";
import { Tab, TabContainer } from "../tabs/Tabs";
import { FieldRow, InputField } from "../input/Input";
import { AnalyticsNotice } from "../analytics/AnalyticsNotice";
import { ProfileSettingsTab } from "./ProfileSettingsTab";
import { FeedbackSettingsTab } from "./FeedbackSettingsTab";
import {
Expand All @@ -24,15 +22,14 @@ import {
import { widget } from "../widget";
import {
useSetting,
developerSettingsTab as developerSettingsTabSetting,
duplicateTiles as duplicateTilesSetting,
useOptInAnalytics,
soundEffectVolumeSetting,
developerSettingsTab,
} from "./settings";
import { isFirefox } from "../Platform";
import { PreferencesSettingsTab } from "./PreferencesSettingsTab";
import { Slider } from "../Slider";
import { DeviceSelection } from "./DeviceSelection";
import { DeveloperSettingsTab } from "./DeveloperSettingsTab";

type SettingsTab =
| "audio"
Expand Down Expand Up @@ -64,28 +61,13 @@ export const SettingsModal: FC<Props> = ({
}) => {
const { t } = useTranslation();

const [optInAnalytics, setOptInAnalytics] = useOptInAnalytics();
const [developerSettingsTab, setDeveloperSettingsTab] = useSetting(
developerSettingsTabSetting,
);
const [duplicateTiles, setDuplicateTiles] = useSetting(duplicateTilesSetting);

const optInDescription = (
<Text size="sm">
<Trans i18nKey="settings.opt_in_description">
<AnalyticsNotice />
<br />
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.
</Trans>
</Text>
);

const devices = useMediaDevices();
useMediaDeviceNames(devices, open);
const [soundVolume, setSoundVolume] = useSetting(soundEffectVolumeSetting);
const [soundVolumeRaw, setSoundVolumeRaw] = useState(soundVolume);

const [showDeveloperSettingsTab] = useSetting(developerSettingsTab);

const audioTab: Tab<SettingsTab> = {
key: "audio",
name: t("common.audio"),
Expand Down Expand Up @@ -151,104 +133,16 @@ export const SettingsModal: FC<Props> = ({
content: <FeedbackSettingsTab roomId={roomId} />,
};

const moreTab: Tab<SettingsTab> = {
key: "more",
name: t("settings.more_tab_title"),
content: (
<>
<h4>{t("settings.developer_tab_title")}</h4>
<p>
{t("version", {
productName: import.meta.env.VITE_PRODUCT_NAME || "Element Call",
version: import.meta.env.VITE_APP_VERSION || "dev",
})}
</p>
<FieldRow>
<InputField
id="developerSettingsTab"
type="checkbox"
checked={developerSettingsTab}
label={t("settings.developer_settings_label")}
description={t("settings.developer_settings_label_description")}
onChange={(event: ChangeEvent<HTMLInputElement>): void =>
setDeveloperSettingsTab(event.target.checked)
}
/>
</FieldRow>
<h4>{t("common.analytics")}</h4>
<FieldRow>
<InputField
id="optInAnalytics"
type="checkbox"
checked={optInAnalytics ?? undefined}
description={optInDescription}
onChange={(event: ChangeEvent<HTMLInputElement>): void => {
setOptInAnalytics?.(event.target.checked);
}}
/>
</FieldRow>
</>
),
};

const developerTab: Tab<SettingsTab> = {
key: "developer",
name: t("settings.developer_tab_title"),
content: (
<>
<p>
{t("developer_mode.hostname", {
hostname: window.location.hostname || "unknown",
})}
</p>
<p>
{t("version", {
productName: import.meta.env.VITE_PRODUCT_NAME || "Element Call",
version: import.meta.env.VITE_APP_VERSION || "dev",
})}
</p>
<p>
{t("developer_mode.crypto_version", {
version: client.getCrypto()?.getVersion() || "unknown",
})}
</p>
<p>
{t("developer_mode.matrix_id", {
id: client.getUserId() || "unknown",
})}
</p>
<p>
{t("developer_mode.device_id", {
id: client.getDeviceId() || "unknown",
})}
</p>
<FieldRow>
<InputField
id="duplicateTiles"
type="number"
label={t("developer_mode.duplicate_tiles_label")}
value={duplicateTiles.toString()}
min={0}
onChange={useCallback(
(event: ChangeEvent<HTMLInputElement>): void => {
const value = event.target.valueAsNumber;
if (value < 0) {
return;
}
setDuplicateTiles(Number.isNaN(value) ? 0 : value);
},
[setDuplicateTiles],
)}
/>
</FieldRow>
</>
),
content: <DeveloperSettingsTab client={client} />,
};

const tabs = [audioTab, videoTab];
if (widget === null) tabs.push(profileTab);
tabs.push(preferencesTab, feedbackTab, moreTab);
if (developerSettingsTab) tabs.push(developerTab);
tabs.push(preferencesTab, feedbackTab);
if (showDeveloperSettingsTab) tabs.push(developerTab);

return (
<Modal
Expand Down
Loading