diff --git a/res/css/_common.pcss b/res/css/_common.pcss index 908da2bdda6..10d3439c493 100644 --- a/res/css/_common.pcss +++ b/res/css/_common.pcss @@ -593,7 +593,7 @@ legend { .mx_Dialog button:not( .mx_EncryptionUserSettingsTab button, - .mx_EncryptionCard button, + .mx_InformationCard button, .mx_UserProfileSettings button, .mx_ShareDialog button, .mx_UnpinAllDialog button, diff --git a/res/css/views/dialogs/_ConfirmKeyStorageOffDialog.pcss b/res/css/views/dialogs/_ConfirmKeyStorageOffDialog.pcss index 5ac53c7b706..95fc3c5e2f9 100644 --- a/res/css/views/dialogs/_ConfirmKeyStorageOffDialog.pcss +++ b/res/css/views/dialogs/_ConfirmKeyStorageOffDialog.pcss @@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details. width: 600px; } - .mx_EncryptionCard { + .mx_InformationCard { text-align: center; } } diff --git a/res/css/views/dialogs/security/_AccessSecretStorageDialog.pcss b/res/css/views/dialogs/security/_AccessSecretStorageDialog.pcss index 2c78a62f8d1..25576aaa718 100644 --- a/res/css/views/dialogs/security/_AccessSecretStorageDialog.pcss +++ b/res/css/views/dialogs/security/_AccessSecretStorageDialog.pcss @@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details. */ .mx_AccessSecretStorageDialog { - &.mx_EncryptionCard { + &.mx_InformationCard { /* override some styles that we don't need */ border: 0px none; box-shadow: none; @@ -56,7 +56,7 @@ Please see LICENSE files in the repository root for full details. } } - .mx_EncryptionCard_buttons { + .mx_InformationCard_buttons { margin-top: var(--cpd-space-20x); } } diff --git a/res/css/views/settings/encryption/_EncryptionCard.pcss b/res/css/views/settings/encryption/_EncryptionCard.pcss index 5aba3fe7d75..49284ff5641 100644 --- a/res/css/views/settings/encryption/_EncryptionCard.pcss +++ b/res/css/views/settings/encryption/_EncryptionCard.pcss @@ -5,17 +5,18 @@ * Please see LICENSE files in the repository root for full details. */ -.mx_EncryptionCard { +.mx_InformationCard { display: flex; flex-direction: column; gap: var(--cpd-space-8x); - padding: var(--cpd-space-10x); border-radius: var(--cpd-space-4x); /* From figma */ - box-shadow: 0 1.2px 2.4px 0 rgb(27, 29, 34, 0.15); - border: 1px solid var(--cpd-color-gray-400); - .mx_EncryptionCard_header { + border: 0px none; + box-shadow: none; + padding: 0px; + + .mx_InformationCard_header { display: flex; flex-direction: column; gap: var(--cpd-space-4x); @@ -31,15 +32,14 @@ } } - /* extra class for specifying that we don't need a border */ - &.mx_EncryptionCard_noBorder { - border: 0px none; - box-shadow: none; - padding: 0px; + &.mx_InformationCard_border { + padding: var(--cpd-space-10x); + box-shadow: 0 1.2px 2.4px 0 rgb(27, 29, 34, 0.15); + border: 1px solid var(--cpd-color-gray-400); } } -.mx_EncryptionCard_buttons { +.mx_InformationCard_buttons { display: flex; flex-direction: column; gap: var(--cpd-space-4x); diff --git a/res/css/views/settings/encryption/_EncryptionCardEmphasisedContent.pcss b/res/css/views/settings/encryption/_EncryptionCardEmphasisedContent.pcss index 6b18fcff650..4c8573a26b6 100644 --- a/res/css/views/settings/encryption/_EncryptionCardEmphasisedContent.pcss +++ b/res/css/views/settings/encryption/_EncryptionCardEmphasisedContent.pcss @@ -5,7 +5,7 @@ * Please see LICENSE files in the repository root for full details. */ -.mx_EncryptionCard_emphasisedContent { +.mx_InformationCard_emphasisedContent { span { font: var(--cpd-font-body-md-medium); text-align: center; diff --git a/src/@types/matrix-js-sdk.d.ts b/src/@types/matrix-js-sdk.d.ts index ad75ca95f05..16074e19843 100644 --- a/src/@types/matrix-js-sdk.d.ts +++ b/src/@types/matrix-js-sdk.d.ts @@ -1,4 +1,5 @@ /* +Copyright 2025 Element Creations Ltd. Copyright 2024, 2025 New Vector Ltd. Copyright 2024 The Matrix.org Foundation C.I.C. @@ -36,6 +37,7 @@ declare module "matrix-js-sdk/src/types" { export interface StateEvents { // Jitsi-backed video room state events [JitsiCallMemberEventType]: JitsiCallMemberContent; + "org.matrix.msc4143.rtc.slot": any; // Unstable widgets state events "im.vector.modular.widgets": IWidget | EmptyObject; diff --git a/src/Notifier.ts b/src/Notifier.ts index aa68b386a34..e502585df38 100644 --- a/src/Notifier.ts +++ b/src/Notifier.ts @@ -25,7 +25,11 @@ import { } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { type PermissionChanged as PermissionChangedEvent } from "@matrix-org/analytics-events/types/typescript/PermissionChanged"; -import { type IRTCNotificationContent, MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc"; +import { + DefaultCallApplicationSlot, + type IRTCNotificationContent, + MatrixRTCSession, +} from "matrix-js-sdk/src/matrixrtc"; import { MatrixClientPeg } from "./MatrixClientPeg"; import { PosthogAnalytics } from "./PosthogAnalytics"; @@ -487,7 +491,10 @@ class NotifierClass extends TypedEventEmitter m.sender === cli.getUserId()); + room && + MatrixRTCSession.sessionMembershipsForSlot(room, DefaultCallApplicationSlot).some( + (m) => m.sender === cli.getUserId(), + ); if (EventType.RTCNotification === ev.getType() && !thisUserHasConnectedDevice) { const content = ev.getContent() as IRTCNotificationContent; diff --git a/src/components/views/settings/encryption/EncryptionCard.tsx b/src/components/structures/InformationCard.tsx similarity index 63% rename from src/components/views/settings/encryption/EncryptionCard.tsx rename to src/components/structures/InformationCard.tsx index 89ce2cbb17b..1aed8d3bdb3 100644 --- a/src/components/views/settings/encryption/EncryptionCard.tsx +++ b/src/components/structures/InformationCard.tsx @@ -9,7 +9,7 @@ import React, { type JSX, type PropsWithChildren, type ComponentType, type SVGAt import { BigIcon, Heading } from "@vector-im/compound-web"; import classNames from "classnames"; -interface EncryptionCardProps { +interface InformationCardProps { /** * CSS class name to apply to the card. */ @@ -26,26 +26,41 @@ interface EncryptionCardProps { * Whether this icon shows a destructive action. */ destructive?: boolean; + /** + * Whether the component should have a border + */ + border?: boolean; /** * The icon to display. */ Icon: ComponentType>; } +/** + * A component to present action buttons at the bottom of an {@link EncryptionCard} + * (mostly as somewhere for the common CSS to live). + */ +export function InformationCardButtons({ children }: PropsWithChildren): JSX.Element { + return
{children}
; +} + + /** * A styled card for encryption settings. + * Note: This was previously known as the EncryptionCard */ -export function EncryptionCard({ +export function InformationCard({ title, description, className, + border = true, destructive = false, Icon, children, -}: PropsWithChildren): JSX.Element { +}: PropsWithChildren): JSX.Element { return ( -
-
+
+
diff --git a/src/components/structures/auth/SetupEncryptionBody.tsx b/src/components/structures/auth/SetupEncryptionBody.tsx index 5098265e67f..c0fb423bd40 100644 --- a/src/components/structures/auth/SetupEncryptionBody.tsx +++ b/src/components/structures/auth/SetupEncryptionBody.tsx @@ -22,8 +22,7 @@ import EncryptionPanel from "../../views/right_panel/EncryptionPanel"; import AccessibleButton from "../../views/elements/AccessibleButton"; import Spinner from "../../views/elements/Spinner"; import { ResetIdentityDialog } from "../../views/dialogs/ResetIdentityDialog"; -import { EncryptionCard } from "../../views/settings/encryption/EncryptionCard"; -import { EncryptionCardButtons } from "../../views/settings/encryption/EncryptionCardButtons"; +import { InformationCard, InformationCardButtons } from "../../structures/InformationCard"; import { EncryptionCardEmphasisedContent } from "../../views/settings/encryption/EncryptionCardEmphasisedContent"; import ExternalLink from "../../views/elements/ExternalLink"; import dispatcher from "../../../dispatcher/dispatcher"; @@ -196,10 +195,11 @@ export default class SetupEncryptionBody extends React.Component } return ( - {_t("encryption|verification|confirm_identity_description")} @@ -209,15 +209,15 @@ export default class SetupEncryptionBody extends React.Component - + {verifyButton} {useRecoveryKeyButton} {signOutButton} - - + + ); } else if (phase === Phase.Done) { let message: JSX.Element; diff --git a/src/components/views/auth/InteractiveAuthEntryComponents.tsx b/src/components/views/auth/InteractiveAuthEntryComponents.tsx index a9bf8b75970..cc95ac69f31 100644 --- a/src/components/views/auth/InteractiveAuthEntryComponents.tsx +++ b/src/components/views/auth/InteractiveAuthEntryComponents.tsx @@ -23,8 +23,7 @@ import Field from "../elements/Field"; import Spinner from "../elements/Spinner"; import CaptchaForm from "./CaptchaForm"; import { pickBestPolicyLanguage } from "../../../Terms.ts"; -import { EncryptionCardButtons } from "../settings/encryption/EncryptionCardButtons.tsx"; -import { EncryptionCard } from "../settings/encryption/EncryptionCard.tsx"; +import { InformationCard, InformationCardButtons } from "../../structures/InformationCard.tsx"; /* This file contains a collection of components which are used by the * InteractiveAuth to prompt the user to enter the information needed @@ -973,14 +972,14 @@ export class MasUnlockCrossSigningAuthEntry extends FallbackAuthEntry<{ public render(): React.ReactNode { return ( - - + - - + + ); } } diff --git a/src/components/views/dialogs/ConfirmEnableCallDialog.tsx b/src/components/views/dialogs/ConfirmEnableCallDialog.tsx new file mode 100644 index 00000000000..2af09057ffc --- /dev/null +++ b/src/components/views/dialogs/ConfirmEnableCallDialog.tsx @@ -0,0 +1,26 @@ +import React, { ReactElement } from "react"; +import { _t } from "../../../languageHandler"; +import BaseDialog from "./BaseDialog"; +import { InformationCard, InformationCardButtons } from "../../structures/InformationCard"; +import { VideoCallSolidIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; +import { Button } from "@vector-im/compound-web"; + +export default function({onFinished}: {onFinished: (confirmed: boolean) => void}): ReactElement { + return onFinished(false)} + contentId="mx_Dialog_content" + hasCancel={true} + fixedWidth={true} + > + + + + + + + +} \ No newline at end of file diff --git a/src/components/views/dialogs/ConfirmKeyStorageOffDialog.tsx b/src/components/views/dialogs/ConfirmKeyStorageOffDialog.tsx index d6a5f79aebb..76199d67e78 100644 --- a/src/components/views/dialogs/ConfirmKeyStorageOffDialog.tsx +++ b/src/components/views/dialogs/ConfirmKeyStorageOffDialog.tsx @@ -12,8 +12,7 @@ import { PopOutIcon } from "@vector-im/compound-design-tokens/assets/web/icons"; import { _t } from "../../../languageHandler"; import defaultDispatcher from "../../../dispatcher/dispatcher"; -import { EncryptionCard } from "../settings/encryption/EncryptionCard"; -import { EncryptionCardButtons } from "../settings/encryption/EncryptionCardButtons"; +import { InformationCard, InformationCardButtons } from "../../structures/InformationCard"; import { type OpenToTabPayload } from "../../../dispatcher/payloads/OpenToTabPayload"; import { Action } from "../../../dispatcher/actions"; import { UserTab } from "./UserTab"; @@ -52,7 +51,7 @@ export default class ConfirmKeyStorageOffDialog extends React.Component { public render(): React.ReactNode { return ( - { ), })} - + - - + + ); } } diff --git a/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx b/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx index 94d9a30e547..b0bac0ec5e8 100644 --- a/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx +++ b/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx @@ -15,8 +15,7 @@ import { type SecretStorage } from "matrix-js-sdk/src/matrix"; import { Flex } from "../../../../../packages/shared-components/src/utils/Flex"; import { _t } from "../../../../languageHandler"; -import { EncryptionCard } from "../../settings/encryption/EncryptionCard"; -import { EncryptionCardButtons } from "../../settings/encryption/EncryptionCardButtons"; +import { InformationCard, InformationCardButtons } from "../../../structures/InformationCard"; import BaseDialog from "../BaseDialog"; // Don't shout at the user that their key is invalid every time they type a key: wait a short time @@ -192,14 +191,14 @@ export default class AccessSecretStorageDialog extends React.PureComponent
{recoveryKeyFeedback} - + - +
); @@ -208,14 +207,14 @@ export default class AccessSecretStorageDialog extends React.PureComponent - {content} - + ); } diff --git a/src/components/views/settings/encryption/ChangeRecoveryKey.tsx b/src/components/views/settings/encryption/ChangeRecoveryKey.tsx index ae568efc627..174471a8860 100644 --- a/src/components/views/settings/encryption/ChangeRecoveryKey.tsx +++ b/src/components/views/settings/encryption/ChangeRecoveryKey.tsx @@ -21,13 +21,12 @@ import CopyIcon from "@vector-im/compound-design-tokens/assets/web/icons/copy"; import KeyIcon from "@vector-im/compound-design-tokens/assets/web/icons/key-solid"; import { _t } from "../../../../languageHandler"; -import { EncryptionCard } from "./EncryptionCard"; +import { InformationCard, InformationCardButtons } from "../../../structures/InformationCard.tsx"; import { useMatrixClientContext } from "../../../../contexts/MatrixClientContext"; import { useAsyncMemo } from "../../../../hooks/useAsyncMemo"; import { copyPlaintext } from "../../../../utils/strings"; import { initialiseDehydrationIfEnabled } from "../../../../utils/device/dehydration.ts"; import { withSecretStorageKeyCache } from "../../../../SecurityManager"; -import { EncryptionCardButtons } from "./EncryptionCardButtons"; import { logErrorAndShowErrorDialog } from "../../../../utils/ErrorUtils.tsx"; import { RECOVERY_ACCOUNT_DATA_KEY } from "../../../../DeviceListener"; @@ -166,14 +165,14 @@ export function ChangeRecoveryKey({ pages={pages} onPageClick={onCancelClick} /> - {content} - + ); } @@ -245,12 +244,12 @@ function InformationPanel({ onContinueClick, onCancelClick }: InformationPanelPr {_t("settings|encryption|recovery|set_up_recovery_secondary_description")} - + - + ); } @@ -292,12 +291,12 @@ function KeyPanel({ recoveryKey, onConfirmClick, onCancelClick }: KeyPanelProps)
- + - + ); } @@ -367,12 +366,12 @@ function KeyForm({ onCancelClick, onSubmit, recoveryKey, submitButtonLabel }: Ke {_t("settings|encryption|recovery|enter_key_error")} )} - + - + ); } diff --git a/src/components/views/settings/encryption/DeleteKeyStoragePanel.tsx b/src/components/views/settings/encryption/DeleteKeyStoragePanel.tsx index d4f80d7eeef..143293d1a87 100644 --- a/src/components/views/settings/encryption/DeleteKeyStoragePanel.tsx +++ b/src/components/views/settings/encryption/DeleteKeyStoragePanel.tsx @@ -11,10 +11,9 @@ import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error- import React, { type JSX, useCallback, useState } from "react"; import { _t } from "../../../../languageHandler"; -import { EncryptionCard } from "./EncryptionCard"; +import { InformationCard, InformationCardButtons } from "../../../structures/InformationCard.tsx"; import { useKeyStoragePanelViewModel } from "../../../viewmodels/settings/encryption/KeyStoragePanelViewModel"; import SdkConfig from "../../../../SdkConfig"; -import { EncryptionCardButtons } from "./EncryptionCardButtons"; import { EncryptionCardEmphasisedContent } from "./EncryptionCardEmphasisedContent"; interface Props { @@ -49,7 +48,7 @@ export function DeleteKeyStoragePanel({ onFinish }: Props): JSX.Element { pages={[_t("settings|encryption|title"), _t("settings|encryption|delete_key_storage|breadcrumb_page")]} onPageClick={onFinish} /> - - + - - + + ); } diff --git a/src/components/views/settings/encryption/EncryptionCardButtons.tsx b/src/components/views/settings/encryption/EncryptionCardButtons.tsx deleted file mode 100644 index 06e5ef60d7f..00000000000 --- a/src/components/views/settings/encryption/EncryptionCardButtons.tsx +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2024 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only - * Please see LICENSE files in the repository root for full details. - */ - -import React, { type JSX, type PropsWithChildren } from "react"; - -/** - * A component to present action buttons at the bottom of an {@link EncryptionCard} - * (mostly as somewhere for the common CSS to live). - */ -export function EncryptionCardButtons({ children }: PropsWithChildren): JSX.Element { - return
{children}
; -} diff --git a/src/components/views/settings/encryption/EncryptionCardEmphasisedContent.tsx b/src/components/views/settings/encryption/EncryptionCardEmphasisedContent.tsx index 4ad472ee823..d78ee2bb932 100644 --- a/src/components/views/settings/encryption/EncryptionCardEmphasisedContent.tsx +++ b/src/components/views/settings/encryption/EncryptionCardEmphasisedContent.tsx @@ -19,7 +19,7 @@ export function EncryptionCardEmphasisedContent({ children }: PropsWithChildren) direction="column" gap="var(--cpd-space-3x)" align="normal" - className="mx_EncryptionCard_emphasisedContent" + className="mx_InformationCard_emphasisedContent" > {children} diff --git a/src/components/views/settings/encryption/ResetIdentityBody.tsx b/src/components/views/settings/encryption/ResetIdentityBody.tsx index 91b7d65b5d4..3b3c59ac73e 100644 --- a/src/components/views/settings/encryption/ResetIdentityBody.tsx +++ b/src/components/views/settings/encryption/ResetIdentityBody.tsx @@ -12,9 +12,8 @@ import ErrorIcon from "@vector-im/compound-design-tokens/assets/web/icons/error- import React, { type JSX, useState } from "react"; import { _t } from "../../../../languageHandler"; -import { EncryptionCard } from "./EncryptionCard"; +import { InformationCard, InformationCardButtons } from "../../../structures/InformationCard.tsx"; import { uiAuthCallback } from "../../../../CreateCrossSigning"; -import { EncryptionCardButtons } from "./EncryptionCardButtons"; import { EncryptionCardEmphasisedContent } from "./EncryptionCardEmphasisedContent"; import { useMatrixClientContext } from "../../../../contexts/MatrixClientContext"; @@ -68,7 +67,7 @@ export function ResetIdentityBody({ onCancelClick, onReset, variant }: ResetIden const [inProgress, setInProgress] = useState(false); return ( - + @@ -83,7 +82,7 @@ export function ResetIdentityBody({ onCancelClick, onReset, variant }: ResetIden {variant === "compromised" && {_t("settings|encryption|advanced|breadcrumb_warning")}} - +
should display the reset identity panel w
should display the reset identity panel w
    should display the reset identity panel w