mirror of
https://github.com/vector-im/element-web.git
synced 2026-05-05 04:06:44 +02:00
Allow dismissing 'Key storage out of sync' temporarily (#31455)
This commit is contained in:
parent
828c4a47a4
commit
0947517746
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
@ -38,6 +38,7 @@ Please see LICENSE files in the repository root for full details.
|
||||
grid-template-columns: 22px 1fr;
|
||||
column-gap: 8px;
|
||||
row-gap: 4px;
|
||||
align-items: center;
|
||||
padding: var(--cpd-space-3x);
|
||||
|
||||
&.mx_Toast_hasIcon {
|
||||
@ -47,10 +48,17 @@ Please see LICENSE files in the repository root for full details.
|
||||
grid-column: 1;
|
||||
}
|
||||
|
||||
.mx_Toast_title,
|
||||
.mx_Toast_body {
|
||||
.mx_Toast_title {
|
||||
grid-column: 2;
|
||||
}
|
||||
|
||||
.mx_Toast_body {
|
||||
grid-column: 2 / 4;
|
||||
}
|
||||
|
||||
.mx_Toast_closebutton {
|
||||
grid-column: 3;
|
||||
}
|
||||
}
|
||||
&:not(.mx_Toast_hasIcon) {
|
||||
padding-left: 12px;
|
||||
|
||||
@ -8,10 +8,12 @@ Please see LICENSE files in the repository root for full details.
|
||||
|
||||
import React from "react";
|
||||
import classNames from "classnames";
|
||||
import { Text } from "@vector-im/compound-web";
|
||||
import { IconButton, Text } from "@vector-im/compound-web";
|
||||
import { type EmptyObject } from "matrix-js-sdk/src/matrix";
|
||||
import { CloseIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
|
||||
|
||||
import ToastStore, { type IToast } from "../../stores/ToastStore";
|
||||
import { _t } from "../../languageHandler";
|
||||
|
||||
interface IState {
|
||||
toasts: IToast<any>[];
|
||||
@ -47,7 +49,7 @@ export default class ToastContainer extends React.Component<EmptyObject, IState>
|
||||
let containerClasses;
|
||||
if (totalCount !== 0) {
|
||||
const topToast = this.state.toasts[0];
|
||||
const { title, icon, key, component, className, bodyClassName, props } = topToast;
|
||||
const { title, icon, key, component, className, bodyClassName, onCloseButtonClicked, props } = topToast;
|
||||
const bodyClasses = classNames("mx_Toast_body", bodyClassName);
|
||||
const toastClasses = classNames("mx_Toast_toast", className, {
|
||||
mx_Toast_hasIcon: !!icon,
|
||||
@ -61,11 +63,24 @@ export default class ToastContainer extends React.Component<EmptyObject, IState>
|
||||
let titleElement;
|
||||
if (title) {
|
||||
titleElement = (
|
||||
<div className="mx_Toast_title">
|
||||
<Text size="lg" weight="semibold" as="h2">
|
||||
{title}
|
||||
</Text>
|
||||
</div>
|
||||
<>
|
||||
<div className="mx_Toast_title">
|
||||
<Text size="lg" weight="semibold" as="h2">
|
||||
{title}
|
||||
</Text>
|
||||
</div>
|
||||
{onCloseButtonClicked && (
|
||||
<IconButton
|
||||
className="mx_Toast_closebutton"
|
||||
size="28px"
|
||||
onClick={onCloseButtonClicked}
|
||||
tooltip={_t("action|close")}
|
||||
kind="secondary"
|
||||
>
|
||||
<CloseIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -22,6 +22,15 @@ export interface IToast<C extends ComponentClass> {
|
||||
component: C;
|
||||
className?: string;
|
||||
bodyClassName?: string;
|
||||
|
||||
/**
|
||||
* What to do if the user clicks the close button. If this is undefined, the
|
||||
* close button is not displayed.
|
||||
*
|
||||
* Note: the close button is only displayed if the toast has a title (i.e. if {@link title} is truthy).
|
||||
*/
|
||||
onCloseButtonClicked?: () => void;
|
||||
|
||||
props?: Omit<React.ComponentProps<C>, "toastKey">; // toastKey is injected by ToastContainer
|
||||
}
|
||||
|
||||
|
||||
@ -65,6 +65,18 @@ const getIcon = (state: DeviceStateForToast): IToast<any>["icon"] => {
|
||||
}
|
||||
};
|
||||
|
||||
const shouldShowCloseButton = (state: DeviceStateForToast): boolean => {
|
||||
switch (state) {
|
||||
case "key_storage_out_of_sync":
|
||||
case "identity_needs_reset":
|
||||
return true;
|
||||
case "set_up_recovery":
|
||||
case "verify_this_session":
|
||||
case "turn_on_key_storage":
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
const getSetupCaption = (state: DeviceStateForToast): string => {
|
||||
switch (state) {
|
||||
case "set_up_recovery":
|
||||
@ -299,10 +311,15 @@ export const showToast = (state: DeviceStateForToast): void => {
|
||||
}
|
||||
};
|
||||
|
||||
const onCloseButtonClicked = shouldShowCloseButton(state)
|
||||
? () => DeviceListener.sharedInstance().dismissEncryptionSetup()
|
||||
: undefined;
|
||||
|
||||
ToastStore.sharedInstance().addOrReplaceToast({
|
||||
key: TOAST_KEY,
|
||||
title: getTitle(state),
|
||||
icon: getIcon(state),
|
||||
onCloseButtonClicked,
|
||||
props: {
|
||||
description: getDescription(state),
|
||||
primaryLabel: getSetupCaption(state),
|
||||
|
||||
@ -189,6 +189,17 @@ describe("SetupEncryptionToast", () => {
|
||||
props: { initialEncryptionState: "change_recovery_key" },
|
||||
});
|
||||
});
|
||||
|
||||
it("should dismiss the toast when the close button is clicked", async () => {
|
||||
jest.spyOn(DeviceListener.sharedInstance(), "dismissEncryptionSetup");
|
||||
|
||||
act(() => showToast("key_storage_out_of_sync"));
|
||||
|
||||
const user = userEvent.setup();
|
||||
await user.click(await screen.findByRole("button", { name: "Close" }));
|
||||
|
||||
expect(DeviceListener.sharedInstance().dismissEncryptionSetup).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Turn on key storage", () => {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user