mirror of
https://github.com/element-hq/element-web.git
synced 2025-12-27 23:11:21 +00:00
Update algorithm for history visible banner. (#31577)
* feat: Update algorithm for history visible banner. - The banner now only shows for rooms with `shared` or `worldReadable` history visibility. - The banner does not show in rooms in which the current user cannot send messages. * tests: Add `getHistoryVisibility` to stub room. * docs: Add description to `visible` condition check. * docs: Fix spelling. Co-authored-by: Florian Duros <florian.duros@ormaz.fr> * chore: Remove `jest-sonar.xml`. --------- Co-authored-by: Florian Duros <florian.duros@ormaz.fr>
This commit is contained in:
parent
aa84b2e07c
commit
ce9c66ba4c
@ -16,6 +16,9 @@ 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.
|
||||
|
||||
@ -675,7 +675,11 @@ export class MessageComposer extends React.Component<IProps, IState> {
|
||||
|
||||
return (
|
||||
<div className={classes} ref={this.ref} role="region" aria-label={_t("a11y|message_composer")}>
|
||||
<HistoryVisibleBanner room={this.props.room} threadId={threadId ?? null} />
|
||||
<HistoryVisibleBanner
|
||||
room={this.props.room}
|
||||
canSendMessages={canSendMessages}
|
||||
threadId={threadId ?? null}
|
||||
/>
|
||||
<div className="mx_MessageComposer_wrapper">
|
||||
<UserIdentityWarning room={this.props.room} key={this.props.room.roomId} />
|
||||
<ReplyPreview
|
||||
|
||||
@ -15,12 +15,22 @@ import { HistoryVisibility, RoomStateEvent, type Room } from "matrix-js-sdk/src/
|
||||
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
|
||||
@ -66,23 +76,33 @@ export class HistoryVisibleBannerViewModel
|
||||
|
||||
/**
|
||||
* Computes the latest banner snapshot given the VM's props.
|
||||
* @param room - The room the banner will be shown in.
|
||||
* @param threadId - The thread ID passed in from the parent {@link MessageComposer}.
|
||||
* @param props - See {@link Props}.
|
||||
* @returns The latest snapshot. See {@link HistoryVisibleBannerViewSnapshot}.
|
||||
*/
|
||||
private static readonly computeSnapshot = (
|
||||
room: Room,
|
||||
threadId?: string | null,
|
||||
): 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 &&
|
||||
!threadId &&
|
||||
room.hasEncryptionStateEvent() &&
|
||||
room.getHistoryVisibility() !== HistoryVisibility.Joined &&
|
||||
canSendMessages &&
|
||||
isHistoryVisible &&
|
||||
!threadId &&
|
||||
!acknowledged,
|
||||
};
|
||||
};
|
||||
@ -92,7 +112,7 @@ export class HistoryVisibleBannerViewModel
|
||||
* @param props - Properties for this view model. See {@link Props}.
|
||||
*/
|
||||
public constructor(props: Props) {
|
||||
super(props, HistoryVisibleBannerViewModel.computeSnapshot(props.room, props.threadId));
|
||||
super(props, HistoryVisibleBannerViewModel.computeSnapshot(props));
|
||||
|
||||
this.disposables.trackListener(props.room, RoomStateEvent.Update, () => this.setSnapshot());
|
||||
|
||||
@ -126,7 +146,7 @@ export class HistoryVisibleBannerViewModel
|
||||
);
|
||||
}
|
||||
|
||||
this.snapshot.set(HistoryVisibleBannerViewModel.computeSnapshot(this.props.room, this.props.threadId));
|
||||
this.snapshot.set(HistoryVisibleBannerViewModel.computeSnapshot(this.props));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -677,6 +677,7 @@ 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),
|
||||
|
||||
@ -54,7 +54,7 @@ describe("HistoryVisibleBannerViewModel", () => {
|
||||
});
|
||||
|
||||
it("should not show the banner in unencrypted rooms", () => {
|
||||
const vm = new HistoryVisibleBannerViewModel({ room, threadId: null });
|
||||
const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: null });
|
||||
expect(vm.getSnapshot().visible).toBe(false);
|
||||
});
|
||||
|
||||
@ -76,7 +76,7 @@ describe("HistoryVisibleBannerViewModel", () => {
|
||||
}),
|
||||
]);
|
||||
|
||||
const vm = new HistoryVisibleBannerViewModel({ room, threadId: null });
|
||||
const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: null });
|
||||
expect(vm.getSnapshot().visible).toBe(false);
|
||||
});
|
||||
|
||||
@ -99,7 +99,7 @@ describe("HistoryVisibleBannerViewModel", () => {
|
||||
}),
|
||||
]);
|
||||
|
||||
const vm = new HistoryVisibleBannerViewModel({ room, threadId: null });
|
||||
const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: null });
|
||||
expect(vm.getSnapshot().visible).toBe(false);
|
||||
vm.dispose();
|
||||
});
|
||||
@ -122,12 +122,12 @@ describe("HistoryVisibleBannerViewModel", () => {
|
||||
}),
|
||||
]);
|
||||
|
||||
const vm = new HistoryVisibleBannerViewModel({ room, threadId: "some thread ID" });
|
||||
const vm = new HistoryVisibleBannerViewModel({ room, canSendMessages: true, threadId: "some thread ID" });
|
||||
expect(vm.getSnapshot().visible).toBe(false);
|
||||
vm.dispose();
|
||||
});
|
||||
|
||||
it("should show the banner in encrypted rooms with non-joined history visibility", async () => {
|
||||
it("should not show the banner if the user cannot send messages", () => {
|
||||
upsertRoomStateEvents(room, [
|
||||
mkEvent({
|
||||
event: true,
|
||||
@ -145,7 +145,53 @@ describe("HistoryVisibleBannerViewModel", () => {
|
||||
}),
|
||||
]);
|
||||
|
||||
const vm = new HistoryVisibleBannerViewModel({ room, threadId: null });
|
||||
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);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user