split SettingsSection out of SettingsTab, replace usage (#10735)
* split SettingsSection out of SettingsTab, replace usage * correct copyright * fix VoipRoomSettingsTabpull/28788/head^2
parent
35376996b0
commit
58c942be45
|
@ -339,6 +339,7 @@
|
|||
@import "./views/settings/_SpellCheckLanguages.pcss";
|
||||
@import "./views/settings/_ThemeChoicePanel.pcss";
|
||||
@import "./views/settings/_UpdateCheckButton.pcss";
|
||||
@import "./views/settings/tabs/_SettingsSection.pcss";
|
||||
@import "./views/settings/tabs/_SettingsTab.pcss";
|
||||
@import "./views/settings/tabs/room/_GeneralRoomSettingsTab.pcss";
|
||||
@import "./views/settings/tabs/room/_NotificationSettingsTab.pcss";
|
||||
|
|
|
@ -20,9 +20,11 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_SettingsFieldset_legend {
|
||||
font-size: $font-16px;
|
||||
display: block;
|
||||
// matches h3
|
||||
font-size: $font-18px;
|
||||
font-weight: var(--font-semi-bold);
|
||||
line-height: $font-22px;
|
||||
display: block;
|
||||
color: $primary-content;
|
||||
margin-bottom: 10px;
|
||||
margin-top: 12px;
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
Copyright 2023 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_SettingsSection {
|
||||
--SettingsTab_section-margin-bottom-preferences-labs: 30px;
|
||||
--SettingsTab_heading_nth_child-margin-top: 30px; /* TODO: Use a spacing variable */
|
||||
--SettingsTab_fullWidthField-margin-inline-end: 100px;
|
||||
--SettingsTab_tooltip-max-width: 120px; /* So it fits in the space provided by the page */
|
||||
|
||||
color: $primary-content;
|
||||
|
||||
a {
|
||||
color: $links;
|
||||
}
|
||||
}
|
||||
|
||||
.mx_SettingsSection_subSections {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr;
|
||||
grid-gap: $spacing-32;
|
||||
|
||||
padding: $spacing-16 0;
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
Copyright 2022 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, { HTMLAttributes } from "react";
|
||||
|
||||
import Heading from "../../typography/Heading";
|
||||
|
||||
export interface SettingsSectionProps extends HTMLAttributes<HTMLDivElement> {
|
||||
heading: string | React.ReactNode;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* A section of settings content
|
||||
* A SettingsTab may contain one or more SettingsSections
|
||||
* Eg:
|
||||
* ```
|
||||
* <SettingsTab>
|
||||
* <SettingsSection heading="General">
|
||||
* <SettingsSubsection heading="Profile">
|
||||
* // profile settings form
|
||||
* <SettingsSubsection>
|
||||
* <SettingsSubsection heading="Account">
|
||||
* // account settings
|
||||
* <SettingsSubsection>
|
||||
* </SettingsSection>
|
||||
* </SettingsTab>
|
||||
* ```
|
||||
*/
|
||||
export const SettingsSection: React.FC<SettingsSectionProps> = ({ heading, children, ...rest }) => (
|
||||
<div {...rest} className="mx_SettingsSection">
|
||||
{typeof heading === "string" ? <Heading size="h2">{heading}</Heading> : <>{heading}</>}
|
||||
<div className="mx_SettingsSection_subSections">{children}</div>
|
||||
</div>
|
||||
);
|
|
@ -15,16 +15,30 @@ limitations under the License.
|
|||
*/
|
||||
import React from "react";
|
||||
|
||||
import Heading from "../../typography/Heading";
|
||||
|
||||
export interface SettingsTabProps {
|
||||
heading: string;
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const SettingsTab: React.FC<SettingsTabProps> = ({ heading, children }) => (
|
||||
/**
|
||||
* Container for a tab of settings panel content
|
||||
* Should contain one or more SettingsSection
|
||||
* Settings width, padding and spacing between sections
|
||||
* Eg:
|
||||
* ```
|
||||
* <SettingsTab>
|
||||
* <SettingsSection heading="General">
|
||||
* <SettingsSubsection heading="Profile">
|
||||
* // profile settings form
|
||||
* <SettingsSubsection>
|
||||
* <SettingsSubsection heading="Account">
|
||||
* // account settings
|
||||
* <SettingsSubsection>
|
||||
* </SettingsSection>
|
||||
* </SettingsTab>
|
||||
* ```
|
||||
*/
|
||||
const SettingsTab: React.FC<SettingsTabProps> = ({ children }) => (
|
||||
<div className="mx_SettingsTab">
|
||||
<Heading size="h2">{heading}</Heading>
|
||||
<div className="mx_SettingsTab_sections">{children}</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -28,6 +28,7 @@ import SettingsTab from "../SettingsTab";
|
|||
import { ElementCall } from "../../../../../models/Call";
|
||||
import { useRoomState } from "../../../../../hooks/useRoomState";
|
||||
import SdkConfig, { DEFAULTS } from "../../../../../SdkConfig";
|
||||
import { SettingsSection } from "../../shared/SettingsSection";
|
||||
|
||||
interface ElementCallSwitchProps {
|
||||
room: Room;
|
||||
|
@ -100,10 +101,12 @@ interface Props {
|
|||
|
||||
export const VoipRoomSettingsTab: React.FC<Props> = ({ room }) => {
|
||||
return (
|
||||
<SettingsTab heading={_t("Voice & Video")}>
|
||||
<SettingsSubsection heading={_t("Call type")}>
|
||||
<ElementCallSwitch room={room} />
|
||||
</SettingsSubsection>
|
||||
<SettingsTab>
|
||||
<SettingsSection heading={_t("Voice & Video")}>
|
||||
<SettingsSubsection heading={_t("Call type")}>
|
||||
<ElementCallSwitch room={room} />
|
||||
</SettingsSubsection>
|
||||
</SettingsSection>
|
||||
</SettingsTab>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -38,6 +38,7 @@ import { useAsyncMemo } from "../../../../../hooks/useAsyncMemo";
|
|||
import QuestionDialog from "../../../dialogs/QuestionDialog";
|
||||
import { FilterVariation } from "../../devices/filter";
|
||||
import { OtherSessionsSectionHeading } from "../../devices/OtherSessionsSectionHeading";
|
||||
import { SettingsSection } from "../../shared/SettingsSection";
|
||||
|
||||
const confirmSignOut = async (sessionsToSignOutCount: number): Promise<boolean> => {
|
||||
const { finished } = Modal.createDialog(QuestionDialog, {
|
||||
|
@ -225,62 +226,64 @@ const SessionManagerTab: React.FC = () => {
|
|||
}
|
||||
|
||||
return (
|
||||
<SettingsTab heading={_t("Sessions")}>
|
||||
<SecurityRecommendations
|
||||
devices={devices}
|
||||
goToFilteredList={onGoToFilteredList}
|
||||
currentDeviceId={currentDeviceId}
|
||||
/>
|
||||
<CurrentDeviceSection
|
||||
device={currentDevice}
|
||||
localNotificationSettings={localNotificationSettings.get(currentDeviceId)}
|
||||
setPushNotifications={setPushNotifications}
|
||||
isSigningOut={signingOutDeviceIds.includes(currentDeviceId)}
|
||||
isLoading={isLoadingDeviceList}
|
||||
saveDeviceName={(deviceName) => saveDeviceName(currentDeviceId, deviceName)}
|
||||
onVerifyCurrentDevice={onVerifyCurrentDevice}
|
||||
onSignOutCurrentDevice={onSignOutCurrentDevice}
|
||||
signOutAllOtherSessions={signOutAllOtherSessions}
|
||||
otherSessionsCount={otherSessionsCount}
|
||||
/>
|
||||
{shouldShowOtherSessions && (
|
||||
<SettingsSubsection
|
||||
heading={
|
||||
<OtherSessionsSectionHeading
|
||||
otherSessionsCount={otherSessionsCount}
|
||||
signOutAllOtherSessions={signOutAllOtherSessions!}
|
||||
disabled={!!signingOutDeviceIds.length}
|
||||
/>
|
||||
}
|
||||
description={_t(
|
||||
`For best security, verify your sessions and sign out ` +
|
||||
`from any session that you don't recognize or use anymore.`,
|
||||
)}
|
||||
data-testid="other-sessions-section"
|
||||
>
|
||||
<FilteredDeviceList
|
||||
devices={otherDevices}
|
||||
pushers={pushers}
|
||||
localNotificationSettings={localNotificationSettings}
|
||||
filter={filter}
|
||||
expandedDeviceIds={expandedDeviceIds}
|
||||
signingOutDeviceIds={signingOutDeviceIds}
|
||||
selectedDeviceIds={selectedDeviceIds}
|
||||
setSelectedDeviceIds={setSelectedDeviceIds}
|
||||
onFilterChange={setFilter}
|
||||
onDeviceExpandToggle={onDeviceExpandToggle}
|
||||
onRequestDeviceVerification={
|
||||
requestDeviceVerification ? onTriggerDeviceVerification : undefined
|
||||
<SettingsTab>
|
||||
<SettingsSection heading={_t("Sessions")}>
|
||||
<SecurityRecommendations
|
||||
devices={devices}
|
||||
goToFilteredList={onGoToFilteredList}
|
||||
currentDeviceId={currentDeviceId}
|
||||
/>
|
||||
<CurrentDeviceSection
|
||||
device={currentDevice}
|
||||
localNotificationSettings={localNotificationSettings.get(currentDeviceId)}
|
||||
setPushNotifications={setPushNotifications}
|
||||
isSigningOut={signingOutDeviceIds.includes(currentDeviceId)}
|
||||
isLoading={isLoadingDeviceList}
|
||||
saveDeviceName={(deviceName) => saveDeviceName(currentDeviceId, deviceName)}
|
||||
onVerifyCurrentDevice={onVerifyCurrentDevice}
|
||||
onSignOutCurrentDevice={onSignOutCurrentDevice}
|
||||
signOutAllOtherSessions={signOutAllOtherSessions}
|
||||
otherSessionsCount={otherSessionsCount}
|
||||
/>
|
||||
{shouldShowOtherSessions && (
|
||||
<SettingsSubsection
|
||||
heading={
|
||||
<OtherSessionsSectionHeading
|
||||
otherSessionsCount={otherSessionsCount}
|
||||
signOutAllOtherSessions={signOutAllOtherSessions!}
|
||||
disabled={!!signingOutDeviceIds.length}
|
||||
/>
|
||||
}
|
||||
onSignOutDevices={onSignOutOtherDevices}
|
||||
saveDeviceName={saveDeviceName}
|
||||
setPushNotifications={setPushNotifications}
|
||||
ref={filteredDeviceListRef}
|
||||
supportsMSC3881={supportsMSC3881}
|
||||
/>
|
||||
</SettingsSubsection>
|
||||
)}
|
||||
<LoginWithQRSection onShowQr={onShowQrClicked} versions={clientVersions} capabilities={capabilities} />
|
||||
description={_t(
|
||||
`For best security, verify your sessions and sign out ` +
|
||||
`from any session that you don't recognize or use anymore.`,
|
||||
)}
|
||||
data-testid="other-sessions-section"
|
||||
>
|
||||
<FilteredDeviceList
|
||||
devices={otherDevices}
|
||||
pushers={pushers}
|
||||
localNotificationSettings={localNotificationSettings}
|
||||
filter={filter}
|
||||
expandedDeviceIds={expandedDeviceIds}
|
||||
signingOutDeviceIds={signingOutDeviceIds}
|
||||
selectedDeviceIds={selectedDeviceIds}
|
||||
setSelectedDeviceIds={setSelectedDeviceIds}
|
||||
onFilterChange={setFilter}
|
||||
onDeviceExpandToggle={onDeviceExpandToggle}
|
||||
onRequestDeviceVerification={
|
||||
requestDeviceVerification ? onTriggerDeviceVerification : undefined
|
||||
}
|
||||
onSignOutDevices={onSignOutOtherDevices}
|
||||
saveDeviceName={saveDeviceName}
|
||||
setPushNotifications={setPushNotifications}
|
||||
ref={filteredDeviceListRef}
|
||||
supportsMSC3881={supportsMSC3881}
|
||||
/>
|
||||
</SettingsSubsection>
|
||||
)}
|
||||
<LoginWithQRSection onShowQr={onShowQrClicked} versions={clientVersions} capabilities={capabilities} />
|
||||
</SettingsSection>
|
||||
</SettingsTab>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -22,7 +22,7 @@ import SettingsTab, { SettingsTabProps } from "../../../../../src/components/vie
|
|||
describe("<SettingsTab />", () => {
|
||||
const getComponent = (props: SettingsTabProps): ReactElement => <SettingsTab {...props} />;
|
||||
it("renders tab", () => {
|
||||
const { container } = render(getComponent({ heading: "Test Tab", children: <div>test</div> }));
|
||||
const { container } = render(getComponent({ children: <div>test</div> }));
|
||||
|
||||
expect(container).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -5,11 +5,6 @@ exports[`<SettingsTab /> renders tab 1`] = `
|
|||
<div
|
||||
class="mx_SettingsTab"
|
||||
>
|
||||
<h2
|
||||
class="mx_Heading_h2"
|
||||
>
|
||||
Test Tab
|
||||
</h2>
|
||||
<div
|
||||
class="mx_SettingsTab_sections"
|
||||
>
|
||||
|
|
Loading…
Reference in New Issue