Use semantic heading in user settings Sidebar & Voip (#10782)

* split SettingsSection out of SettingsTab, replace usage

* correct copyright

* use semantic headings in GeneralRoomSettingsTab

* use SettingsTab and SettingsSubsection in room settings

* fix VoipRoomSettingsTab

* use SettingsSection components in space settings

* settingssubsection text component

* use semantic headings in HelpUserSetttings tab

* use ExternalLink components for external links

* test

* strict

* lint

* semantic heading in labs settings

* semantic headings in keyboard settings tab

* semantic heading in preferencesusersettingstab

* tidying

* use new settings components in eventindexpanel

* findByTestId

* prettier

* semantic headings and style refresh for crypto settings

* e2e panel

* semantic headings and cleanup in Sidebar user settings

* semantic heading in voice user settings

* sonarcloud bug and test
This commit is contained in:
Kerry 2023-05-19 12:03:39 +12:00 committed by GitHub
parent d9a61c093c
commit 55336bf932
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 446 additions and 189 deletions

View file

@ -348,7 +348,6 @@
@import "./views/settings/tabs/user/_MjolnirUserSettingsTab.pcss";
@import "./views/settings/tabs/user/_SecurityUserSettingsTab.pcss";
@import "./views/settings/tabs/user/_SidebarUserSettingsTab.pcss";
@import "./views/settings/tabs/user/_VoiceUserSettingsTab.pcss";
@import "./views/spaces/_SpaceBasicSettings.pcss";
@import "./views/spaces/_SpaceChildrenPicker.pcss";
@import "./views/spaces/_SpaceCreateMenu.pcss";

View file

@ -113,9 +113,11 @@ limitations under the License.
}
.mx_QuickSettingsButton_icon {
// TODO remove when all icons have fill=currentColor
* {
fill: $secondary-content;
}
color: $secondary-content;
width: 16px;
height: 16px;
position: absolute;

View file

@ -14,67 +14,25 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_SidebarUserSettingsTab {
.mx_Checkbox {
margin-top: 12px;
font-size: $font-15px;
line-height: $font-24px;
color: $secondary-content;
}
.mx_SidebarUserSettingsTab_homeAllRoomsCheckbox {
margin-left: 24px;
.mx_SidebarUserSettingsTab_checkboxMicrocopy {
margin-bottom: 12px;
margin-left: 24px;
font-size: $font-15px;
line-height: $font-24px;
color: $secondary-content;
}
.mx_SidebarUserSettingsTab_homeAllRoomsCheckbox {
margin-left: 24px;
& + div {
margin-left: 48px;
}
}
.mx_SidebarUserSettingsTab_homeCheckbox,
.mx_SidebarUserSettingsTab_favouritesCheckbox,
.mx_SidebarUserSettingsTab_peopleCheckbox,
.mx_SidebarUserSettingsTab_orphansCheckbox {
.mx_Checkbox_background + div {
padding-left: 20px;
position: relative;
&::before {
background-color: $secondary-content;
content: "";
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
width: 16px;
height: 16px;
position: absolute;
left: 0;
top: 50%;
transform: translateY(-50%);
}
}
}
.mx_SidebarUserSettingsTab_homeCheckbox .mx_Checkbox_background + div::before {
mask-image: url("$(res)/img/element-icons/home.svg");
}
.mx_SidebarUserSettingsTab_favouritesCheckbox .mx_Checkbox_background + div::before {
mask-image: url("$(res)/img/element-icons/roomlist/favorite.svg");
}
.mx_SidebarUserSettingsTab_peopleCheckbox .mx_Checkbox_background + div::before {
mask-image: url("$(res)/img/element-icons/room/members.svg");
}
.mx_SidebarUserSettingsTab_orphansCheckbox .mx_Checkbox_background + div::before {
mask-image: url("$(res)/img/element-icons/roomlist/hash-circle.svg");
& + div {
margin-left: 48px;
}
}
.mx_SidebarUserSettingsTab_checkbox {
margin-bottom: $spacing-8;
// override checkbox styles˚
label {
align-items: flex-start !important;
}
svg {
height: 16px;
width: 16px;
margin-right: $spacing-8;
margin-bottom: -1px;
}
}

View file

@ -1,23 +0,0 @@
/*
Copyright 2019 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
.mx_VoiceUserSettingsTab .mx_Field {
margin-inline-end: var(--SettingsTab_fullWidthField-margin-inline-end);
}
.mx_VoiceUserSettingsTab_missingMediaPermissions {
margin-bottom: 15px;
}

View file

@ -1,3 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M20.2804 7.90031L13.2804 2.06697C12.5387 1.4489 11.4613 1.4489 10.7196 2.06698L3.71963 7.90031C3.26365 8.28029 3 8.84319 3 9.43675V20.5C3 21.6046 3.89543 22.5 5 22.5H7C8.10457 22.5 9 21.6046 9 20.5V16C9 14.8954 9.89543 14 11 14H13C14.1046 14 15 14.8954 15 16V20.5C15 21.6046 15.8954 22.5 17 22.5H19C20.1046 22.5 21 21.6046 21 20.5V9.43675C21 8.84319 20.7364 8.28029 20.2804 7.90031Z" fill="#737D8C"/>
<path d="M20.2804 7.90031L13.2804 2.06697C12.5387 1.4489 11.4613 1.4489 10.7196 2.06698L3.71963 7.90031C3.26365 8.28029 3 8.84319 3 9.43675V20.5C3 21.6046 3.89543 22.5 5 22.5H7C8.10457 22.5 9 21.6046 9 20.5V16C9 14.8954 9.89543 14 11 14H13C14.1046 14 15 14.8954 15 16V20.5C15 21.6046 15.8954 22.5 17 22.5H19C20.1046 22.5 21 21.6046 21 20.5V9.43675C21 8.84319 20.7364 8.28029 20.2804 7.90031Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 517 B

After

Width:  |  Height:  |  Size: 522 B

View file

@ -2,6 +2,6 @@
<mask id="path-1-inside-1" fill="white">
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.5911 20.2922C15.9951 21.3704 14.0711 22 12 22C9.74879 22 7.67132 21.2561 6 20.0007C3.5711 18.1763 2 15.2716 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 15.4518 20.2511 18.4951 17.5911 20.2922ZM12 12.5C13.6569 12.5 15 11.0449 15 9.25C15 7.45507 13.6569 6 12 6C10.3431 6 9 7.45507 9 9.25C9 11.0449 10.3431 12.5 12 12.5ZM12 20C14.162 20 16.1236 19.1424 17.5634 17.7488C16.673 15.5506 14.5176 14 12 14C9.48242 14 7.32699 15.5506 6.43662 17.7488C7.87635 19.1424 9.83802 20 12 20Z"/>
</mask>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.5911 20.2922C15.9951 21.3704 14.0711 22 12 22C9.74879 22 7.67132 21.2561 6 20.0007C3.5711 18.1763 2 15.2716 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 15.4518 20.2511 18.4951 17.5911 20.2922ZM12 12.5C13.6569 12.5 15 11.0449 15 9.25C15 7.45507 13.6569 6 12 6C10.3431 6 9 7.45507 9 9.25C9 11.0449 10.3431 12.5 12 12.5ZM12 20C14.162 20 16.1236 19.1424 17.5634 17.7488C16.673 15.5506 14.5176 14 12 14C9.48242 14 7.32699 15.5506 6.43662 17.7488C7.87635 19.1424 9.83802 20 12 20Z" fill="black"/>
<path d="M17.5911 20.2922L16.4715 18.6349L17.5911 20.2922ZM6 20.0007L4.79885 21.5999L4.79885 21.5999L6 20.0007ZM17.5634 17.7488L18.9544 19.1859L19.9234 18.2479L19.4171 16.998L17.5634 17.7488ZM6.43662 17.7488L4.5829 16.998L4.07662 18.2479L5.04563 19.1859L6.43662 17.7488ZM12 24C14.4825 24 16.7945 23.244 18.7107 21.9494L16.4715 18.6349C15.1957 19.4968 13.6596 20 12 20V24ZM4.79885 21.5999C6.80462 23.1065 9.30085 24 12 24V20C10.1967 20 8.53802 19.4058 7.20115 18.4016L4.79885 21.5999ZM0 12C0 15.9273 1.88868 19.414 4.79885 21.5999L7.20115 18.4016C5.25353 16.9387 4 14.616 4 12H0ZM12 0C5.37258 0 0 5.37258 0 12H4C4 7.58172 7.58172 4 12 4V0ZM24 12C24 5.37258 18.6274 0 12 0V4C16.4183 4 20 7.58172 20 12H24ZM18.7107 21.9494C21.8977 19.7963 24 16.144 24 12H20C20 14.7596 18.6045 17.1939 16.4715 18.6349L18.7107 21.9494ZM13 9.25C13 10.0941 12.4046 10.5 12 10.5V14.5C14.9091 14.5 17 11.9958 17 9.25H13ZM12 8C12.4046 8 13 8.4059 13 9.25H17C17 6.50425 14.9091 4 12 4V8ZM11 9.25C11 8.4059 11.5954 8 12 8V4C9.09086 4 7 6.50425 7 9.25H11ZM12 10.5C11.5954 10.5 11 10.0941 11 9.25H7C7 11.9958 9.09086 14.5 12 14.5V10.5ZM16.1724 16.3118C15.0906 17.3588 13.6223 18 12 18V22C14.7017 22 17.1567 20.926 18.9544 19.1859L16.1724 16.3118ZM12 16C13.6752 16 15.1146 17.0305 15.7097 18.4996L19.4171 16.998C18.2314 14.0707 15.3599 12 12 12V16ZM8.29033 18.4996C8.88541 17.0305 10.3248 16 12 16V12C8.64008 12 5.76858 14.0707 4.5829 16.998L8.29033 18.4996ZM12 18C10.3777 18 8.90936 17.3588 7.82761 16.3118L5.04563 19.1859C6.84334 20.926 9.2983 22 12 22V18Z" fill="black" mask="url(#path-1-inside-1)"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.5911 20.2922C15.9951 21.3704 14.0711 22 12 22C9.74879 22 7.67132 21.2561 6 20.0007C3.5711 18.1763 2 15.2716 2 12C2 6.47715 6.47715 2 12 2C17.5228 2 22 6.47715 22 12C22 15.4518 20.2511 18.4951 17.5911 20.2922ZM12 12.5C13.6569 12.5 15 11.0449 15 9.25C15 7.45507 13.6569 6 12 6C10.3431 6 9 7.45507 9 9.25C9 11.0449 10.3431 12.5 12 12.5ZM12 20C14.162 20 16.1236 19.1424 17.5634 17.7488C16.673 15.5506 14.5176 14 12 14C9.48242 14 7.32699 15.5506 6.43662 17.7488C7.87635 19.1424 9.83802 20 12 20Z" fill="currentColor"/>
<path d="M17.5911 20.2922L16.4715 18.6349L17.5911 20.2922ZM6 20.0007L4.79885 21.5999L4.79885 21.5999L6 20.0007ZM17.5634 17.7488L18.9544 19.1859L19.9234 18.2479L19.4171 16.998L17.5634 17.7488ZM6.43662 17.7488L4.5829 16.998L4.07662 18.2479L5.04563 19.1859L6.43662 17.7488ZM12 24C14.4825 24 16.7945 23.244 18.7107 21.9494L16.4715 18.6349C15.1957 19.4968 13.6596 20 12 20V24ZM4.79885 21.5999C6.80462 23.1065 9.30085 24 12 24V20C10.1967 20 8.53802 19.4058 7.20115 18.4016L4.79885 21.5999ZM0 12C0 15.9273 1.88868 19.414 4.79885 21.5999L7.20115 18.4016C5.25353 16.9387 4 14.616 4 12H0ZM12 0C5.37258 0 0 5.37258 0 12H4C4 7.58172 7.58172 4 12 4V0ZM24 12C24 5.37258 18.6274 0 12 0V4C16.4183 4 20 7.58172 20 12H24ZM18.7107 21.9494C21.8977 19.7963 24 16.144 24 12H20C20 14.7596 18.6045 17.1939 16.4715 18.6349L18.7107 21.9494ZM13 9.25C13 10.0941 12.4046 10.5 12 10.5V14.5C14.9091 14.5 17 11.9958 17 9.25H13ZM12 8C12.4046 8 13 8.4059 13 9.25H17C17 6.50425 14.9091 4 12 4V8ZM11 9.25C11 8.4059 11.5954 8 12 8V4C9.09086 4 7 6.50425 7 9.25H11ZM12 10.5C11.5954 10.5 11 10.0941 11 9.25H7C7 11.9958 9.09086 14.5 12 14.5V10.5ZM16.1724 16.3118C15.0906 17.3588 13.6223 18 12 18V22C14.7017 22 17.1567 20.926 18.9544 19.1859L16.1724 16.3118ZM12 16C13.6752 16 15.1146 17.0305 15.7097 18.4996L19.4171 16.998C18.2314 14.0707 15.3599 12 12 12V16ZM8.29033 18.4996C8.88541 17.0305 10.3248 16 12 16V12C8.64008 12 5.76858 14.0707 4.5829 16.998L8.29033 18.4996ZM12 18C10.3777 18 8.90936 17.3588 7.82761 16.3118L5.04563 19.1859C6.84334 20.926 9.2983 22 12 22V18Z" fill="currentColor" mask="url(#path-1-inside-1)"/>
</svg>

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -1,3 +1,3 @@
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8.41411 1.43218C8.59217 0.855939 9.40783 0.855941 9.58589 1.43218L11.1715 6.56319H16.3856C16.9721 6.56319 17.224 7.30764 16.7578 7.66373L12.5135 10.9061L14.1185 16.1001C14.2948 16.6705 13.6348 17.1309 13.1604 16.7684L9 13.5902L4.83965 16.7684C4.3652 17.1309 3.70521 16.6705 3.88148 16.1001L5.4865 10.9061L1.24216 7.66373C0.776033 7.30764 1.02785 6.56319 1.61443 6.56319H6.82854L8.41411 1.43218Z" fill="black"/>
<path d="M8.41411 1.43218C8.59217 0.855939 9.40783 0.855941 9.58589 1.43218L11.1715 6.56319H16.3856C16.9721 6.56319 17.224 7.30764 16.7578 7.66373L12.5135 10.9061L14.1185 16.1001C14.2948 16.6705 13.6348 17.1309 13.1604 16.7684L9 13.5902L4.83965 16.7684C4.3652 17.1309 3.70521 16.6705 3.88148 16.1001L5.4865 10.9061L1.24216 7.66373C0.776033 7.30764 1.02785 6.56319 1.61443 6.56319H6.82854L8.41411 1.43218Z" fill="currentColor"/>
</svg>

Before

Width:  |  Height:  |  Size: 524 B

After

Width:  |  Height:  |  Size: 531 B

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 8.4 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

View file

@ -1,5 +1,5 @@
/*
Copyright 2021 - 2022 The Matrix.org Foundation C.I.C.
Copyright 2021 - 2023 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -16,6 +16,10 @@ limitations under the License.
import React, { ChangeEvent } from "react";
import { Icon as HomeIcon } from "../../../../../../res/img/element-icons/home.svg";
import { Icon as FavoriteIcon } from "../../../../../../res/img/element-icons/roomlist/favorite.svg";
import { Icon as MembersIcon } from "../../../../../../res/img/element-icons/room/members.svg";
import { Icon as HashCircleIcon } from "../../../../../../res/img/element-icons/roomlist/hash-circle.svg";
import { _t } from "../../../../../languageHandler";
import SettingsStore from "../../../../../settings/SettingsStore";
import { SettingLevel } from "../../../../../settings/SettingLevel";
@ -23,6 +27,9 @@ import StyledCheckbox from "../../../elements/StyledCheckbox";
import { useSettingValue } from "../../../../../hooks/useSettings";
import { MetaSpace } from "../../../../../stores/spaces";
import PosthogTrackers from "../../../../../PosthogTrackers";
import SettingsTab from "../SettingsTab";
import { SettingsSection } from "../../shared/SettingsSection";
import SettingsSubsection, { SettingsSubsectionText } from "../../shared/SettingsSubsection";
type InteractionName = "WebSettingsSidebarTabSpacesCheckbox" | "WebQuickSettingsPinToSidebarCheckbox";
@ -50,79 +57,91 @@ const SidebarUserSettingsTab: React.FC = () => {
} = useSettingValue<Record<MetaSpace, boolean>>("Spaces.enabledMetaSpaces");
const allRoomsInHome = useSettingValue<boolean>("Spaces.allRoomsInHome");
const onAllRoomsInHomeToggle = async (event: ChangeEvent<HTMLInputElement>): Promise<void> => {
await SettingsStore.setValue("Spaces.allRoomsInHome", null, SettingLevel.ACCOUNT, event.target.checked);
PosthogTrackers.trackInteraction("WebSettingsSidebarTabSpacesCheckbox", event, 1);
};
return (
<div className="mx_SettingsTab mx_SidebarUserSettingsTab">
<div className="mx_SettingsTab_heading">{_t("Sidebar")}</div>
<div className="mx_SettingsTab_section">
<div className="mx_SettingsTab_subheading">{_t("Spaces to show")}</div>
<div className="mx_SettingsTab_subsectionText">
{_t(
<SettingsTab>
<SettingsSection heading={_t("Sidebar")}>
<SettingsSubsection
heading={_t("Spaces to show")}
description={_t(
"Spaces are ways to group rooms and people. " +
"Alongside the spaces you're in, you can use some pre-built ones too.",
)}
</div>
<StyledCheckbox
checked={!!homeEnabled}
onChange={onMetaSpaceChangeFactory(MetaSpace.Home, "WebSettingsSidebarTabSpacesCheckbox")}
className="mx_SidebarUserSettingsTab_homeCheckbox"
disabled={homeEnabled}
>
{_t("Home")}
</StyledCheckbox>
<div className="mx_SidebarUserSettingsTab_checkboxMicrocopy">
{_t("Home is useful for getting an overview of everything.")}
</div>
<StyledCheckbox
checked={!!homeEnabled}
onChange={onMetaSpaceChangeFactory(MetaSpace.Home, "WebSettingsSidebarTabSpacesCheckbox")}
className="mx_SidebarUserSettingsTab_checkbox"
disabled={homeEnabled}
>
<SettingsSubsectionText>
<HomeIcon />
{_t("Home")}
</SettingsSubsectionText>
<SettingsSubsectionText>
{_t("Home is useful for getting an overview of everything.")}
</SettingsSubsectionText>
</StyledCheckbox>
<StyledCheckbox
checked={allRoomsInHome}
disabled={!homeEnabled}
onChange={(e) => {
SettingsStore.setValue("Spaces.allRoomsInHome", null, SettingLevel.ACCOUNT, e.target.checked);
PosthogTrackers.trackInteraction("WebSettingsSidebarTabSpacesCheckbox", e, 1);
}}
className="mx_SidebarUserSettingsTab_homeAllRoomsCheckbox"
>
{_t("Show all rooms")}
</StyledCheckbox>
<div className="mx_SidebarUserSettingsTab_checkboxMicrocopy">
{_t("Show all your rooms in Home, even if they're in a space.")}
</div>
<StyledCheckbox
checked={allRoomsInHome}
disabled={!homeEnabled}
onChange={onAllRoomsInHomeToggle}
className="mx_SidebarUserSettingsTab_checkbox mx_SidebarUserSettingsTab_homeAllRoomsCheckbox"
data-testid="mx_SidebarUserSettingsTab_homeAllRoomsCheckbox"
>
<SettingsSubsectionText>{_t("Show all rooms")}</SettingsSubsectionText>
<SettingsSubsectionText>
{_t("Show all your rooms in Home, even if they're in a space.")}
</SettingsSubsectionText>
</StyledCheckbox>
<StyledCheckbox
checked={!!favouritesEnabled}
onChange={onMetaSpaceChangeFactory(MetaSpace.Favourites, "WebSettingsSidebarTabSpacesCheckbox")}
className="mx_SidebarUserSettingsTab_favouritesCheckbox"
>
{_t("Favourites")}
</StyledCheckbox>
<div className="mx_SidebarUserSettingsTab_checkboxMicrocopy">
{_t("Group all your favourite rooms and people in one place.")}
</div>
<StyledCheckbox
checked={!!favouritesEnabled}
onChange={onMetaSpaceChangeFactory(MetaSpace.Favourites, "WebSettingsSidebarTabSpacesCheckbox")}
className="mx_SidebarUserSettingsTab_checkbox"
>
<SettingsSubsectionText>
<FavoriteIcon />
{_t("Favourites")}
</SettingsSubsectionText>
<SettingsSubsectionText>
{_t("Group all your favourite rooms and people in one place.")}
</SettingsSubsectionText>
</StyledCheckbox>
<StyledCheckbox
checked={!!peopleEnabled}
onChange={onMetaSpaceChangeFactory(MetaSpace.People, "WebSettingsSidebarTabSpacesCheckbox")}
className="mx_SidebarUserSettingsTab_peopleCheckbox"
>
{_t("People")}
</StyledCheckbox>
<div className="mx_SidebarUserSettingsTab_checkboxMicrocopy">
{_t("Group all your people in one place.")}
</div>
<StyledCheckbox
checked={!!peopleEnabled}
onChange={onMetaSpaceChangeFactory(MetaSpace.People, "WebSettingsSidebarTabSpacesCheckbox")}
className="mx_SidebarUserSettingsTab_checkbox"
>
<SettingsSubsectionText>
<MembersIcon />
{_t("People")}
</SettingsSubsectionText>
<SettingsSubsectionText>{_t("Group all your people in one place.")}</SettingsSubsectionText>
</StyledCheckbox>
<StyledCheckbox
checked={!!orphansEnabled}
onChange={onMetaSpaceChangeFactory(MetaSpace.Orphans, "WebSettingsSidebarTabSpacesCheckbox")}
className="mx_SidebarUserSettingsTab_orphansCheckbox"
>
{_t("Rooms outside of a space")}
</StyledCheckbox>
<div className="mx_SidebarUserSettingsTab_checkboxMicrocopy">
{_t("Group all your rooms that aren't part of a space in one place.")}
</div>
</div>
</div>
<StyledCheckbox
checked={!!orphansEnabled}
onChange={onMetaSpaceChangeFactory(MetaSpace.Orphans, "WebSettingsSidebarTabSpacesCheckbox")}
className="mx_SidebarUserSettingsTab_checkbox"
>
<SettingsSubsectionText>
<HashCircleIcon />
{_t("Rooms outside of a space")}
</SettingsSubsectionText>
<SettingsSubsectionText>
{_t("Group all your rooms that aren't part of a space in one place.")}
</SettingsSubsectionText>
</StyledCheckbox>
</SettingsSubsection>
</SettingsSection>
</SettingsTab>
);
};

View file

@ -26,6 +26,9 @@ import { SettingLevel } from "../../../../../settings/SettingLevel";
import SettingsFlag from "../../../elements/SettingsFlag";
import LabelledToggleSwitch from "../../../elements/LabelledToggleSwitch";
import { requestMediaPermissions } from "../../../../../utils/media/requestMediaPermissions";
import SettingsTab from "../SettingsTab";
import { SettingsSection } from "../../shared/SettingsSection";
import SettingsSubsection from "../../shared/SettingsSubsection";
interface IState {
mediaDevices: IMediaDevices | null;
@ -128,7 +131,7 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> {
let webcamDropdown: ReactNode | undefined;
if (!this.state.mediaDevices) {
requestButton = (
<div className="mx_VoiceUserSettingsTab_missingMediaPermissions">
<div>
<p>{_t("Missing media permissions, click the button below to request.")}</p>
<AccessibleButton onClick={this.requestMediaPermissions} kind="primary">
{_t("Request media permissions")}
@ -148,33 +151,30 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> {
}
return (
<div className="mx_SettingsTab mx_VoiceUserSettingsTab">
<div className="mx_SettingsTab_heading">{_t("Voice & Video")}</div>
{requestButton}
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Voice settings")}</span>
{speakerDropdown}
{microphoneDropdown}
<LabelledToggleSwitch
value={this.state.audioAutoGainControl}
onChange={async (v): Promise<void> => {
await MediaDeviceHandler.setAudioAutoGainControl(v);
this.setState({ audioAutoGainControl: MediaDeviceHandler.getAudioAutoGainControl() });
}}
label={_t("Automatically adjust the microphone volume")}
data-testid="voice-auto-gain"
/>
</div>
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Video settings")}</span>
{webcamDropdown}
<SettingsFlag name="VideoView.flipVideoHorizontally" level={SettingLevel.ACCOUNT} />
</div>
<SettingsTab>
<SettingsSection heading={_t("Voice & Video")}>
{requestButton}
<SettingsSubsection heading={_t("Voice settings")} stretchContent>
{speakerDropdown}
{microphoneDropdown}
<LabelledToggleSwitch
value={this.state.audioAutoGainControl}
onChange={async (v): Promise<void> => {
await MediaDeviceHandler.setAudioAutoGainControl(v);
this.setState({ audioAutoGainControl: MediaDeviceHandler.getAudioAutoGainControl() });
}}
label={_t("Automatically adjust the microphone volume")}
data-testid="voice-auto-gain"
/>
</SettingsSubsection>
<SettingsSubsection heading={_t("Video settings")} stretchContent>
{webcamDropdown}
<SettingsFlag name="VideoView.flipVideoHorizontally" level={SettingLevel.ACCOUNT} />
</SettingsSubsection>
</SettingsSection>
<div className="mx_SettingsTab_heading">{_t("Advanced")}</div>
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Voice processing")}</span>
<div className="mx_SettingsTab_section">
<SettingsSection heading={_t("Advanced")}>
<SettingsSubsection heading={_t("Voice processing")}>
<LabelledToggleSwitch
value={this.state.audioNoiseSuppression}
onChange={async (v): Promise<void> => {
@ -193,9 +193,8 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> {
label={_t("Echo cancellation")}
data-testid="voice-echo-cancellation"
/>
</div>
<div className="mx_SettingsTab_section">
<span className="mx_SettingsTab_subheading">{_t("Connection")}</span>
</SettingsSubsection>
<SettingsSubsection heading={_t("Connection")}>
<SettingsFlag
name="webRtcAllowPeerToPeer"
level={SettingLevel.DEVICE}
@ -206,9 +205,9 @@ export default class VoiceUserSettingsTab extends React.Component<{}, IState> {
level={SettingLevel.DEVICE}
onChange={this.changeFallbackICEServerAllowed}
/>
</div>
</div>
</div>
</SettingsSubsection>
</SettingsSection>
</SettingsTab>
);
}
}

View file

@ -0,0 +1,88 @@
/*
Copyright 2023 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from "react";
import { fireEvent, render, screen } from "@testing-library/react";
import SidebarUserSettingsTab from "../../../../../../src/components/views/settings/tabs/user/SidebarUserSettingsTab";
import PosthogTrackers from "../../../../../../src/PosthogTrackers";
import SettingsStore from "../../../../../../src/settings/SettingsStore";
import { MetaSpace } from "../../../../../../src/stores/spaces";
import { SettingLevel } from "../../../../../../src/settings/SettingLevel";
import { flushPromises } from "../../../../../test-utils";
// used by checkbox to relate labels to inputs
// make it stable for snapshot testing
jest.mock("matrix-js-sdk/src/randomstring", () => ({
randomString: jest.fn().mockReturnValue("abcd"),
}));
describe("<SidebarUserSettingsTab />", () => {
beforeEach(() => {
jest.spyOn(PosthogTrackers, "trackInteraction").mockClear();
jest.spyOn(SettingsStore, "getValue").mockRestore();
jest.spyOn(SettingsStore, "setValue").mockReset();
});
it("renders sidebar settings", () => {
const { container } = render(<SidebarUserSettingsTab />);
expect(container).toMatchSnapshot();
});
it("toggles all rooms in home setting", async () => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName) => {
if (settingName === "Spaces.enabledMetaSpaces") {
return {
[MetaSpace.Home]: true,
[MetaSpace.Favourites]: true,
[MetaSpace.People]: true,
[MetaSpace.Orphans]: true,
};
}
return false;
});
render(<SidebarUserSettingsTab />);
fireEvent.click(screen.getByTestId("mx_SidebarUserSettingsTab_homeAllRoomsCheckbox"));
await flushPromises();
expect(SettingsStore.setValue).toHaveBeenCalledWith("Spaces.allRoomsInHome", null, SettingLevel.ACCOUNT, true);
expect(PosthogTrackers.trackInteraction).toHaveBeenCalledWith(
"WebSettingsSidebarTabSpacesCheckbox",
// synthetic event from checkbox
expect.objectContaining({ type: "change" }),
1,
);
});
it("disables all rooms in home setting when home space is disabled", () => {
jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName) => {
if (settingName === "Spaces.enabledMetaSpaces") {
return {
[MetaSpace.Home]: false,
[MetaSpace.Favourites]: true,
[MetaSpace.People]: true,
[MetaSpace.Orphans]: true,
};
}
return false;
});
render(<SidebarUserSettingsTab />);
expect(screen.getByTestId("mx_SidebarUserSettingsTab_homeAllRoomsCheckbox")).toBeDisabled();
});
});

View file

@ -0,0 +1,215 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`<SidebarUserSettingsTab /> renders sidebar settings 1`] = `
<div>
<div
class="mx_SettingsTab"
>
<div
class="mx_SettingsTab_sections"
>
<div
class="mx_SettingsSection"
>
<h2
class="mx_Heading_h2"
>
Sidebar
</h2>
<div
class="mx_SettingsSection_subSections"
>
<div
class="mx_SettingsSubsection"
>
<div
class="mx_SettingsSubsectionHeading"
>
<h3
class="mx_Heading_h3 mx_SettingsSubsectionHeading_heading"
>
Spaces to show
</h3>
</div>
<div
class="mx_SettingsSubsection_description"
>
<div
class="mx_SettingsSubsection_text"
>
Spaces are ways to group rooms and people. Alongside the spaces you're in, you can use some pre-built ones too.
</div>
</div>
<div
class="mx_SettingsSubsection_content"
>
<span
class="mx_Checkbox mx_SidebarUserSettingsTab_checkbox mx_Checkbox_hasKind mx_Checkbox_kind_solid"
>
<input
checked=""
disabled=""
id="checkbox_abcd"
type="checkbox"
/>
<label
for="checkbox_abcd"
>
<div
class="mx_Checkbox_background"
>
<div
class="mx_Checkbox_checkmark"
/>
</div>
<div>
<div
class="mx_SettingsSubsection_text"
>
<div />
Home
</div>
<div
class="mx_SettingsSubsection_text"
>
Home is useful for getting an overview of everything.
</div>
</div>
</label>
</span>
<span
class="mx_Checkbox mx_SidebarUserSettingsTab_checkbox mx_SidebarUserSettingsTab_homeAllRoomsCheckbox mx_Checkbox_hasKind mx_Checkbox_kind_solid"
>
<input
data-testid="mx_SidebarUserSettingsTab_homeAllRoomsCheckbox"
id="checkbox_abcd"
type="checkbox"
/>
<label
for="checkbox_abcd"
>
<div
class="mx_Checkbox_background"
>
<div
class="mx_Checkbox_checkmark"
/>
</div>
<div>
<div
class="mx_SettingsSubsection_text"
>
Show all rooms
</div>
<div
class="mx_SettingsSubsection_text"
>
Show all your rooms in Home, even if they're in a space.
</div>
</div>
</label>
</span>
<span
class="mx_Checkbox mx_SidebarUserSettingsTab_checkbox mx_Checkbox_hasKind mx_Checkbox_kind_solid"
>
<input
id="checkbox_abcd"
type="checkbox"
/>
<label
for="checkbox_abcd"
>
<div
class="mx_Checkbox_background"
>
<div
class="mx_Checkbox_checkmark"
/>
</div>
<div>
<div
class="mx_SettingsSubsection_text"
>
<div />
Favourites
</div>
<div
class="mx_SettingsSubsection_text"
>
Group all your favourite rooms and people in one place.
</div>
</div>
</label>
</span>
<span
class="mx_Checkbox mx_SidebarUserSettingsTab_checkbox mx_Checkbox_hasKind mx_Checkbox_kind_solid"
>
<input
id="checkbox_abcd"
type="checkbox"
/>
<label
for="checkbox_abcd"
>
<div
class="mx_Checkbox_background"
>
<div
class="mx_Checkbox_checkmark"
/>
</div>
<div>
<div
class="mx_SettingsSubsection_text"
>
<div />
People
</div>
<div
class="mx_SettingsSubsection_text"
>
Group all your people in one place.
</div>
</div>
</label>
</span>
<span
class="mx_Checkbox mx_SidebarUserSettingsTab_checkbox mx_Checkbox_hasKind mx_Checkbox_kind_solid"
>
<input
id="checkbox_abcd"
type="checkbox"
/>
<label
for="checkbox_abcd"
>
<div
class="mx_Checkbox_background"
>
<div
class="mx_Checkbox_checkmark"
/>
</div>
<div>
<div
class="mx_SettingsSubsection_text"
>
<div />
Rooms outside of a space
</div>
<div
class="mx_SettingsSubsection_text"
>
Group all your rooms that aren't part of a space in one place.
</div>
</div>
</label>
</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
`;