diff --git a/packages/shared-components/src/composer/HistoryVisibleBannerView/HistoryVisibleBannerView.stories.tsx b/packages/shared-components/src/composer/HistoryVisibleBannerView/HistoryVisibleBannerView.stories.tsx deleted file mode 100644 index 45c2a0b703..0000000000 --- a/packages/shared-components/src/composer/HistoryVisibleBannerView/HistoryVisibleBannerView.stories.tsx +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ -import { type Meta, type StoryFn } from "@storybook/react-vite"; -import React, { type JSX } from "react"; -import { fn } from "storybook/test"; - -import { useMockedViewModel } from "../../viewmodel"; -import { - HistoryVisibleBannerView, - type HistoryVisibleBannerViewActions, - type HistoryVisibleBannerViewSnapshot, -} from "./HistoryVisibleBannerView"; - -type HistoryVisibleBannerProps = HistoryVisibleBannerViewSnapshot & HistoryVisibleBannerViewActions; - -const HistoryVisibleBannerViewWrapper = ({ onClose, ...rest }: HistoryVisibleBannerProps): JSX.Element => { - const vm = useMockedViewModel(rest, { - onClose, - }); - return ; -}; - -export default { - title: "composer/HistoryVisibleBannerView", - component: HistoryVisibleBannerViewWrapper, - tags: ["autodocs"], - argTypes: {}, - args: { - visible: true, - onClose: fn(), - }, -} as Meta; - -const Template: StoryFn = (args) => ( - -); - -export const Default = Template.bind({}); diff --git a/packages/shared-components/src/composer/HistoryVisibleBannerView/HistoryVisibleBannerView.test.tsx b/packages/shared-components/src/composer/HistoryVisibleBannerView/HistoryVisibleBannerView.test.tsx deleted file mode 100644 index f5dbb63d6d..0000000000 --- a/packages/shared-components/src/composer/HistoryVisibleBannerView/HistoryVisibleBannerView.test.tsx +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -import React from "react"; -import { render } from "@test-utils"; -import { composeStories } from "@storybook/react-vite"; -import { describe, it, vi, expect } from "vitest"; - -import * as stories from "./HistoryVisibleBannerView.stories.tsx"; - -const { Default } = composeStories(stories); - -describe("HistoryVisibleBannerView", () => { - it("renders a history visible banner", () => { - const dismissFn = vi.fn(); - - const { container } = render(); - expect(container).toMatchSnapshot(); - - const button = container.querySelector("button"); - expect(button).not.toBeNull(); - button?.click(); - expect(dismissFn).toHaveBeenCalled(); - }); -}); diff --git a/packages/shared-components/src/composer/HistoryVisibleBannerView/HistoryVisibleBannerView.tsx b/packages/shared-components/src/composer/HistoryVisibleBannerView/HistoryVisibleBannerView.tsx deleted file mode 100644 index 4353db4bd5..0000000000 --- a/packages/shared-components/src/composer/HistoryVisibleBannerView/HistoryVisibleBannerView.tsx +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -import { Link } from "@vector-im/compound-web"; -import React, { type JSX } from "react"; - -import { _t } from "../../utils/i18n"; -import { type ViewModel, useViewModel } from "../../viewmodel"; -import { Banner } from "../Banner"; - -export interface HistoryVisibleBannerViewActions { - /** - * Called when the user dismisses the banner. - */ - onClose: () => void; -} - -export interface HistoryVisibleBannerViewSnapshot { - /** - * Whether the banner is currently visible. - */ - visible: boolean; -} - -/** - * The view model for the banner. - */ -export type HistoryVisibleBannerViewModel = ViewModel & - HistoryVisibleBannerViewActions; - -interface HistoryVisibleBannerViewProps { - /** - * The view model for the banner. - */ - vm: HistoryVisibleBannerViewModel; -} - -/** - * A component to alert that history is shared to new members of the room. - * - * @example - * ```tsx - * - * ``` - */ -export function HistoryVisibleBannerView({ vm }: Readonly): JSX.Element { - const { visible } = useViewModel(vm); - - const contents = _t( - "room|status_bar|history_visible", - {}, - { - a: substituteATag, - }, - ); - - return ( - <> - {visible && ( - vm.onClose()}> - {contents} - - )} - - ); -} - -function substituteATag(sub: string): JSX.Element { - return ( - - {sub} - - ); -} diff --git a/packages/shared-components/src/composer/HistoryVisibleBannerView/__snapshots__/HistoryVisibleBannerView.test.tsx.snap b/packages/shared-components/src/composer/HistoryVisibleBannerView/__snapshots__/HistoryVisibleBannerView.test.tsx.snap deleted file mode 100644 index 612014f93e..0000000000 --- a/packages/shared-components/src/composer/HistoryVisibleBannerView/__snapshots__/HistoryVisibleBannerView.test.tsx.snap +++ /dev/null @@ -1,62 +0,0 @@ -// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html - -exports[`HistoryVisibleBannerView > renders a history visible banner 1`] = ` -
- -
-`; diff --git a/packages/shared-components/src/composer/HistoryVisibleBannerView/index.ts b/packages/shared-components/src/composer/HistoryVisibleBannerView/index.ts deleted file mode 100644 index 96bf208bea..0000000000 --- a/packages/shared-components/src/composer/HistoryVisibleBannerView/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -export * from "./HistoryVisibleBannerView"; diff --git a/packages/shared-components/src/i18n/strings/en_EN.json b/packages/shared-components/src/i18n/strings/en_EN.json index a1d2276ba5..b174a5c8d6 100644 --- a/packages/shared-components/src/i18n/strings/en_EN.json +++ b/packages/shared-components/src/i18n/strings/en_EN.json @@ -32,7 +32,6 @@ "exceeded_resource_limit_description": "Please contact your service administrator to continue using the service.", "exceeded_resource_limit_title": "Your message wasn't sent because this homeserver has exceeded a resource limit.", "failed_to_create_room_title": "Could not start a chat with this user", - "history_visible": "This room has been configured so that new members can read history. Learn More", "homeserver_blocked_title": "Your message wasn't sent because this homeserver has been blocked by its administrator.", "monthly_user_limit_reached_title": "Your message wasn't sent because this homeserver has hit its Monthly Active User Limit.", "requires_consent_agreement_title": "You can't send any messages until you review and agree to our terms and conditions.", diff --git a/packages/shared-components/src/index.ts b/packages/shared-components/src/index.ts index 49f6b4389f..83f074fa66 100644 --- a/packages/shared-components/src/index.ts +++ b/packages/shared-components/src/index.ts @@ -12,7 +12,6 @@ export * from "./audio/PlayPauseButton"; export * from "./audio/SeekBar"; export * from "./avatar/AvatarWithDetails"; export * from "./composer/Banner"; -export * from "./composer/HistoryVisibleBannerView"; export * from "./event-tiles/TextualEventView"; export * from "./message-body/MediaBody"; export * from "./pill-input/Pill"; diff --git a/playwright/snapshots/crypto/history-sharing.spec.ts/shared-history-invite-accepted-linux.png b/playwright/snapshots/crypto/history-sharing.spec.ts/shared-history-invite-accepted-linux.png index bdf1a0de47..9131b77c24 100644 Binary files a/playwright/snapshots/crypto/history-sharing.spec.ts/shared-history-invite-accepted-linux.png and b/playwright/snapshots/crypto/history-sharing.spec.ts/shared-history-invite-accepted-linux.png differ diff --git a/src/components/views/composer/HistoryVisibleBanner.tsx b/src/components/views/composer/HistoryVisibleBanner.tsx deleted file mode 100644 index 85a6bd7fb9..0000000000 --- a/src/components/views/composer/HistoryVisibleBanner.tsx +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -import { HistoryVisibleBannerView, useCreateAutoDisposedViewModel } from "@element-hq/web-shared-components"; -import React from "react"; -import { type Room } from "matrix-js-sdk/src/matrix"; - -import { HistoryVisibleBannerViewModel } from "../../../viewmodels/composer/HistoryVisibleBannerViewModel"; - -/** Wrapper around {@link HistoryVisibleBannerViewModel} for the creation of an auto-disposed view model. */ -export const HistoryVisibleBanner: React.FC<{ - /** The room instance associated with this banner view model. */ - room: Room; - - /** Whether the current user can send messages in the room. */ - canSendMessages: boolean; - - /** - * If not null, specifies the ID of the thread currently being viewed in the thread timeline side view, - * where the banner view is displayed as a child of the message composer. - */ - threadId: string | null; -}> = (props) => { - const vm = useCreateAutoDisposedViewModel(() => new HistoryVisibleBannerViewModel(props)); - return ; -}; diff --git a/src/components/views/rooms/MessageComposer.tsx b/src/components/views/rooms/MessageComposer.tsx index c23bc7917d..06c843f190 100644 --- a/src/components/views/rooms/MessageComposer.tsx +++ b/src/components/views/rooms/MessageComposer.tsx @@ -54,7 +54,6 @@ import { type MatrixClientProps, withMatrixClientHOC } from "../../../contexts/M import { UIFeature } from "../../../settings/UIFeature"; import { formatTimeLeft } from "../../../DateUtils"; import RoomReplacedSvg from "../../../../res/img/room_replaced.svg"; -import { HistoryVisibleBanner } from "../composer/HistoryVisibleBanner"; // The prefix used when persisting editor drafts to localstorage. export const WYSIWYG_EDITOR_STATE_STORAGE_PREFIX = "mx_wysiwyg_state_"; @@ -675,11 +674,6 @@ export class MessageComposer extends React.Component { return (
-
; "blockInvites": IBaseSetting; "Developer.elementCallUrl": IBaseSetting; - "acknowledgedHistoryVisibility": IBaseSetting; } export type SettingKey = keyof Settings; @@ -1499,8 +1498,4 @@ export const SETTINGS: Settings = { displayName: _td("devtools|settings|elementCallUrl"), default: "", }, - "acknowledgedHistoryVisibility": { - supportedLevels: [SettingLevel.ROOM_ACCOUNT], - default: false, - }, }; diff --git a/src/viewmodels/composer/HistoryVisibleBannerViewModel.tsx b/src/viewmodels/composer/HistoryVisibleBannerViewModel.tsx deleted file mode 100644 index 7d1ce9ec81..0000000000 --- a/src/viewmodels/composer/HistoryVisibleBannerViewModel.tsx +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2025 Element Creations Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -import { - BaseViewModel, - type HistoryVisibleBannerViewModel as HistoryVisibleBannerViewModelInterface, - type HistoryVisibleBannerViewSnapshot, -} from "@element-hq/web-shared-components"; -import { HistoryVisibility, RoomStateEvent, type Room } from "matrix-js-sdk/src/matrix"; - -import SettingsStore from "../../settings/SettingsStore"; -import { SettingLevel } from "../../settings/SettingLevel"; - -/** - * A collection of {@link HistoryVisibility} levels that trigger the display of the history visible banner. - */ -const BANNER_VISIBLE_LEVELS = [HistoryVisibility.Shared, HistoryVisibility.WorldReadable]; - -interface Props { - /** - * The room instance associated with this banner view model. - */ - room: Room; - - /** - * Whether or not the current user is able to send messages in this room. - */ - canSendMessages: boolean; - - /** - * If not null, indicates the ID of the thread currently being viewed in the thread - * timeline side view, where the banner view is displayed as a child of the message - * composer. - */ - threadId: string | null; -} - -/** - * View model for the history visible banner, which prompts users that the current room - * history may be shared with new invitees, if they have not already acknowledged the - * banner. - * - * The view model operates using a simple 2-case algorithm: - * - * 1. When a user opens an encrypted room where `history_visibility` is not set to `joined`, - * and the user hasn't previously dismissed it for this particular room, display a banner. - * If the user dismisses the banner, update the client's local store to record that the - * banner has been dismissed. - * 2. When the user opens an encrypted room where `history_visibility` is set to `joined`, clear - * the dismissal flag if it was previously set. This ensures that if the room's history - * visibility changes from public to private and back to public, the banner will reappear - * when appropriate. - * - * This banner is only shown in the regular timeline view, not the thread timeline view, which is - * done by conditioning on the presence of `threadId` in the viewmodel's {@link Props}. - * - * See https://github.com/element-hq/element-meta/issues/2875 for more information. - */ -export class HistoryVisibleBannerViewModel - extends BaseViewModel - implements HistoryVisibleBannerViewModelInterface -{ - /** - * Watcher ID for the "feature_share_history_on_invite" setting. - */ - private readonly featureWatcher: string; - - /** - * Watcher ID for the "acknowledgedHistoryVisibility" setting specific to the room. - */ - private readonly acknowledgedWatcher: string; - - /** - * Computes the latest banner snapshot given the VM's props. - * @param props - See {@link Props}. - * @returns The latest snapshot. See {@link HistoryVisibleBannerViewSnapshot}. - */ - private static readonly computeSnapshot = ({ - room, - canSendMessages, - threadId, - }: Props): HistoryVisibleBannerViewSnapshot => { - const featureEnabled = SettingsStore.getValue("feature_share_history_on_invite"); - const acknowledged = SettingsStore.getValue("acknowledgedHistoryVisibility", room.roomId); - const isHistoryVisible = BANNER_VISIBLE_LEVELS.includes(room.getHistoryVisibility()); - - // This implements point 1. of the algorithm described above. In the order below, all - // of the following must be true for the banner to display: - // - The room history sharing feature must be enabled. - // - The room must be encrypted. - // - The user must be able to send messages. - // - The history must be visible. - // - The view should not be part of a thread timeline. - // - The user must not have acknowledged the banner. - return { - visible: - featureEnabled && - room.hasEncryptionStateEvent() && - canSendMessages && - isHistoryVisible && - !threadId && - !acknowledged, - }; - }; - - /** - * Creates a new view model instance. - * @param props - Properties for this view model. See {@link Props}. - */ - public constructor(props: Props) { - super(props, HistoryVisibleBannerViewModel.computeSnapshot(props)); - - this.disposables.trackListener(props.room, RoomStateEvent.Update, () => this.setSnapshot()); - - // `SettingsStore` is not an `EventListener`, so we must manage these manually. - this.featureWatcher = SettingsStore.watchSetting( - "feature_share_history_on_invite", - null, - (_key, _roomId, _level, value: boolean) => this.setSnapshot(), - ); - this.acknowledgedWatcher = SettingsStore.watchSetting( - "acknowledgedHistoryVisibility", - props.room.roomId, - (_key, _roomId, _level, value: boolean) => this.setSnapshot(), - ); - } - - /** - * Recompute and update this VM instance's snapshot. This will update the `acknowledgedHistoryVisibility` - * store entry if necessary. - */ - private setSnapshot(): void { - const acknowledged = SettingsStore.getValue("acknowledgedHistoryVisibility", this.props.room.roomId); - - // Reset the acknowleded flag when the history visibility is set back to joined. - if (this.props.room.getHistoryVisibility() === HistoryVisibility.Joined && acknowledged) { - SettingsStore.setValue( - "acknowledgedHistoryVisibility", - this.props.room.roomId, - SettingLevel.ROOM_ACCOUNT, - false, - ); - } - - this.snapshot.set(HistoryVisibleBannerViewModel.computeSnapshot(this.props)); - } - - /** - * Revoke the banner's acknoledgement status. - */ - public async revoke(): Promise { - await SettingsStore.setValue( - "acknowledgedHistoryVisibility", - this.props.room.roomId, - SettingLevel.ROOM_ACCOUNT, - false, - ); - } - - /** - * Called when the user dismisses the banner. - */ - public async onClose(): Promise { - await SettingsStore.setValue( - "acknowledgedHistoryVisibility", - this.props.room.roomId, - SettingLevel.ROOM_ACCOUNT, - true, - ); - } - - /** - * Dispose of the viewmodel and its settings listeners. - */ - public dispose(): void { - super.dispose(); - SettingsStore.unwatchSetting(this.featureWatcher); - SettingsStore.unwatchSetting(this.acknowledgedWatcher); - } -} diff --git a/test/test-utils/test-utils.ts b/test/test-utils/test-utils.ts index 9ebfdbf1f3..9bafa55c10 100644 --- a/test/test-utils/test-utils.ts +++ b/test/test-utils/test-utils.ts @@ -9,7 +9,6 @@ Please see LICENSE files in the repository root for full details. import EventEmitter from "events"; import { mocked, type MockedObject } from "jest-mock"; import { - type EventTimeline, MatrixEvent, type Room, type User, @@ -17,7 +16,7 @@ import { type IEvent, type RoomMember, type MatrixClient, - RoomState, + type EventTimeline, EventType, type IEventRelation, type IUnsigned, @@ -30,9 +29,9 @@ import { JoinRule, type OidcClientConfig, type GroupCall, - HistoryVisibility, - type ICreateRoomOpts, type EventStatus, + type ICreateRoomOpts, + RoomState, } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; import { normalize } from "matrix-js-sdk/src/utils"; @@ -668,7 +667,6 @@ export function mkStubRoom( createThreadsTimelineSets: jest.fn().mockReturnValue(new Promise(() => {})), currentState: { getStateEvents: jest.fn((_type, key) => (key === undefined ? [] : null)), - getHistoryVisibility: jest.fn().mockReturnValue(HistoryVisibility.Joined), getMember: jest.fn(), mayClientSendStateEvent: jest.fn().mockReturnValue(true), maySendStateEvent: jest.fn().mockReturnValue(true), @@ -689,7 +687,6 @@ export function mkStubRoom( getCanonicalAlias: jest.fn(), getDMInviter: jest.fn(), getEventReadUpTo: jest.fn(() => null), - getHistoryVisibility: jest.fn().mockReturnValue(HistoryVisibility.Joined), getInvitedAndJoinedMemberCount: jest.fn().mockReturnValue(1), getJoinRule: jest.fn().mockReturnValue("invite"), getJoinedMemberCount: jest.fn().mockReturnValue(1), diff --git a/test/unit-tests/components/viewmodels/composer/HistoryVisibleBannerViewModel-test.tsx b/test/unit-tests/components/viewmodels/composer/HistoryVisibleBannerViewModel-test.tsx deleted file mode 100644 index b1ab6ef7ff..0000000000 --- a/test/unit-tests/components/viewmodels/composer/HistoryVisibleBannerViewModel-test.tsx +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2025 New Vector Ltd. - * - * SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial - * Please see LICENSE files in the repository root for full details. - */ - -import { Room } from "matrix-js-sdk/src/matrix"; - -import { SettingLevel } from "../../../../../src/settings/SettingLevel"; -import SettingsStore, { type CallbackFn } from "../../../../../src/settings/SettingsStore"; -import { mkEvent, stubClient, upsertRoomStateEvents } from "../../../../test-utils"; -import { HistoryVisibleBannerViewModel } from "../../../../../src/viewmodels/composer/HistoryVisibleBannerViewModel"; - -describe("HistoryVisibleBannerViewModel", () => { - const ROOM_ID = "!roomId:example.org"; - - let room: Room; - let watcherCallbacks: CallbackFn[]; - let acknowledgedHistoryVisibility: boolean; - - beforeEach(() => { - watcherCallbacks = []; - acknowledgedHistoryVisibility = false; - - jest.spyOn(SettingsStore, "setValue").mockImplementation(async (settingName, roomId, level, value) => { - if (settingName === "acknowledgedHistoryVisibility") { - acknowledgedHistoryVisibility = value; - } - watcherCallbacks.forEach((callbackFn) => callbackFn(settingName, roomId, level, value, value)); - }); - - jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName, roomId) => { - if (settingName === "acknowledgedHistoryVisibility") { - return acknowledgedHistoryVisibility; - } - if (settingName === "feature_share_history_on_invite") { - return true; - } - return SettingsStore.getDefaultValue(settingName); - }); - - jest.spyOn(SettingsStore, "watchSetting").mockImplementation((settingName, roomId, callbackFn) => { - watcherCallbacks.push(callbackFn); - return `mockWatcherId-${settingName}-${roomId}`; - }); - - stubClient(); - room = new Room(ROOM_ID, {} as any, "@user:example.org"); - }); - - afterEach(() => { - jest.clearAllMocks(); - }); - - it("should not show the banner in unencrypted rooms", () => { - const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: null }); - expect(vm.getSnapshot().visible).toBe(false); - }); - - it("should not show the banner in encrypted rooms with joined history visibility", () => { - upsertRoomStateEvents(room, [ - mkEvent({ - event: true, - type: "m.room.encryption", - user: "@user1:server", - content: {}, - }), - mkEvent({ - event: true, - type: "m.room.history_visibility", - content: { - history_visibility: "joined", - }, - user: "@user1:server", - }), - ]); - - const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: null }); - expect(vm.getSnapshot().visible).toBe(false); - }); - - it("should not show the banner if it has been dismissed", async () => { - await SettingsStore.setValue("acknowledgedHistoryVisibility", ROOM_ID, SettingLevel.ROOM_ACCOUNT, true); - upsertRoomStateEvents(room, [ - mkEvent({ - event: true, - type: "m.room.encryption", - user: "@user1:server", - content: {}, - }), - mkEvent({ - event: true, - type: "m.room.history_visibility", - user: "@user1:server", - content: { - history_visibility: "shared", - }, - }), - ]); - - const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: null }); - expect(vm.getSnapshot().visible).toBe(false); - vm.dispose(); - }); - - it("should not show the banner in threads", () => { - upsertRoomStateEvents(room, [ - mkEvent({ - event: true, - type: "m.room.encryption", - user: "@user1:server", - content: {}, - }), - mkEvent({ - event: true, - type: "m.room.history_visibility", - user: "@user1:server", - content: { - history_visibility: "shared", - }, - }), - ]); - - const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: "some thread ID" }); - expect(vm.getSnapshot().visible).toBe(false); - vm.dispose(); - }); - - it("should not show the banner if the user cannot send messages", () => { - upsertRoomStateEvents(room, [ - mkEvent({ - event: true, - type: "m.room.encryption", - user: "@user1:server", - content: {}, - }), - mkEvent({ - event: true, - type: "m.room.history_visibility", - user: "@user1:server", - content: { - history_visibility: "shared", - }, - }), - ]); - - const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: false, threadId: null }); - expect(vm.getSnapshot().visible).toBe(false); - vm.dispose(); - }); - - it("should not show the banner if history visibility is `invited`", () => { - upsertRoomStateEvents(room, [ - mkEvent({ - event: true, - type: "m.room.encryption", - user: "@user1:server", - content: {}, - }), - mkEvent({ - event: true, - type: "m.room.history_visibility", - user: "@user1:server", - content: { - history_visibility: "invited", - }, - }), - ]); - - const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: null }); - expect(vm.getSnapshot().visible).toBe(false); - vm.dispose(); - }); - - it("should show the banner in encrypted rooms with shared history visibility", async () => { - upsertRoomStateEvents(room, [ - mkEvent({ - event: true, - type: "m.room.encryption", - user: "@user1:server", - content: {}, - }), - mkEvent({ - event: true, - type: "m.room.history_visibility", - user: "@user1:server", - content: { - history_visibility: "shared", - }, - }), - ]); - - const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: null }); - expect(vm.getSnapshot().visible).toBe(true); - await vm.onClose(); - expect(vm.getSnapshot().visible).toBe(false); - }); -});