Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/components/views/composer/HistoryVisibleBanner.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 5 additions & 1 deletion src/components/views/rooms/MessageComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
30 changes: 21 additions & 9 deletions src/viewmodels/composer/HistoryVisibleBannerViewModel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -66,23 +76,25 @@ 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());

return {
visible:
featureEnabled &&
canSendMessages &&
!threadId &&
room.hasEncryptionStateEvent() &&
room.getHistoryVisibility() !== HistoryVisibility.Joined &&
isHistoryVisible &&
!acknowledged,
Comment on lines 100 to 106

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Documentation about visible is welcomed, there is a lot of checks here

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment above detailing why each term is in the conjunction - might be a bit excessive? 1ab3184

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me

};
};
Expand All @@ -92,7 +104,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());

Expand Down Expand Up @@ -126,7 +138,7 @@ export class HistoryVisibleBannerViewModel
);
}

this.snapshot.set(HistoryVisibleBannerViewModel.computeSnapshot(this.props.room, this.props.threadId));
this.snapshot.set(HistoryVisibleBannerViewModel.computeSnapshot(this.props));
}

/**
Expand Down
1 change: 1 addition & 0 deletions test/test-utils/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
});

Expand All @@ -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);
});

Expand All @@ -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();
});
Expand All @@ -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,
Expand All @@ -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);
Expand Down
Loading