Merge pull request #12336 from matrix-org/andybalaam/stas-demydiuk-membership-type3

Introduce Membership type (take 2)
This commit is contained in:
David Baker
2024-03-22 15:36:39 +00:00
committed by GitHub
113 changed files with 711 additions and 517 deletions

View File

@@ -38,6 +38,7 @@ import {
ISearchResults,
THREAD_RELATION_TYPE,
} from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { logger } from "matrix-js-sdk/src/logger";
import { CallState, MatrixCall } from "matrix-js-sdk/src/webrtc/call";
import { throttle } from "lodash";
@@ -1454,7 +1455,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
private async loadMembersIfJoined(room: Room): Promise<void> {
// lazy load members if enabled
if (this.context.client?.hasLazyLoadMembersEnabled()) {
if (room && room.getMyMembership() === "join") {
if (room && room.getMyMembership() === KnownMembership.Join) {
try {
await room.loadMembersIfNeeded();
if (!this.unmounted) {
@@ -1588,7 +1589,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
if (room && this.context.client) {
const me = this.context.client.getSafeUserId();
const canReact =
room.getMyMembership() === "join" && room.currentState.maySendEvent(EventType.Reaction, me);
room.getMyMembership() === KnownMembership.Join &&
room.currentState.maySendEvent(EventType.Reaction, me);
const canSendMessages = room.maySendMessage();
const canSelfRedact = room.currentState.maySendEvent(EventType.RoomRedaction, me);
@@ -1622,10 +1624,10 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
private updateDMState(): void {
const room = this.state.room;
if (room?.getMyMembership() !== "join") {
if (room?.getMyMembership() != KnownMembership.Join) {
return;
}
const dmInviter = room.getDMInviter();
const dmInviter = room?.getDMInviter();
if (dmInviter) {
Rooms.setDMRoom(room.client, room.roomId, dmInviter);
}
@@ -1662,7 +1664,8 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
action: Action.JoinRoom,
roomId,
opts: { inviteSignUrl: signUrl },
metricsTrigger: this.state.room?.getMyMembership() === "invite" ? "Invite" : "RoomPreview",
metricsTrigger:
this.state.room?.getMyMembership() === KnownMembership.Invite ? "Invite" : "RoomPreview",
canAskToJoin: this.state.canAskToJoin,
});
}
@@ -2183,7 +2186,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
const myMembership = this.state.room.getMyMembership();
if (
isVideoRoom(this.state.room) &&
!(SettingsStore.getValue("feature_video_rooms") && myMembership === "join")
!(SettingsStore.getValue("feature_video_rooms") && myMembership === KnownMembership.Join)
) {
return (
<ErrorBoundary>
@@ -2200,7 +2203,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
}
// SpaceRoomView handles invites itself
if (myMembership === "invite" && !this.state.room.isSpaceRoom()) {
if (myMembership === KnownMembership.Invite && !this.state.room.isSpaceRoom()) {
if (this.state.joining || this.state.rejecting) {
return (
<ErrorBoundary>
@@ -2247,16 +2250,19 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
}
}
if (this.state.canAskToJoin && ["knock", "leave"].includes(myMembership)) {
if (
this.state.canAskToJoin &&
([KnownMembership.Knock, KnownMembership.Leave] as Array<string>).includes(myMembership)
) {
return (
<div className="mx_RoomView" data-room-header={roomHeaderType}>
<ErrorBoundary>
<RoomPreviewBar
onJoinClick={this.onJoinButtonClicked}
room={this.state.room}
canAskToJoinAndMembershipIsLeave={myMembership === "leave"}
canAskToJoinAndMembershipIsLeave={myMembership === KnownMembership.Leave}
promptAskToJoin={this.state.promptAskToJoin}
knocked={myMembership === "knock"}
knocked={myMembership === KnownMembership.Knock}
onSubmitAskToJoin={this.onSubmitAskToJoin}
onCancelAskToJoin={this.onCancelAskToJoin}
onForgetClick={this.onForgetClick}
@@ -2288,7 +2294,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
statusBar = (
<RoomStatusBar
room={this.state.room}
isPeeking={myMembership !== "join"}
isPeeking={myMembership !== KnownMembership.Join}
onInviteClick={this.onInviteClick}
onVisible={this.onStatusBarVisible}
onHidden={this.onStatusBarHidden}
@@ -2332,7 +2338,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
);
} else if (showRoomUpgradeBar) {
aux = <RoomUpgradeWarningBar room={this.state.room} />;
} else if (myMembership !== "join") {
} else if (myMembership !== KnownMembership.Join) {
// We do have a room object for this room, but we're not currently in it.
// We may have a 3rd party invite to it.
let inviterName: string | undefined;
@@ -2406,7 +2412,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
let messageComposer;
const showComposer =
// joined and not showing search results
myMembership === "join" && !this.state.search;
myMembership === KnownMembership.Join && !this.state.search;
if (showComposer) {
messageComposer = (
<MessageComposer
@@ -2603,7 +2609,9 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
const myMember = this.state.room!.getMember(this.context.client!.getSafeUserId());
const showForgetButton =
!this.context.client.isGuest() && (["leave", "ban"].includes(myMembership) || myMember?.isKicked());
!this.context.client.isGuest() &&
(([KnownMembership.Leave, KnownMembership.Ban] as Array<string>).includes(myMembership) ||
myMember?.isKicked());
return (
<RoomContext.Provider value={this.state}>
@@ -2640,7 +2648,7 @@ export class RoomView extends React.Component<IRoomProps, IRoomState> {
room={this.state.room}
searchInfo={this.state.search}
oobData={this.props.oobData}
inRoom={myMembership === "join"}
inRoom={myMembership === KnownMembership.Join}
onSearchClick={onSearchClick}
onInviteClick={onInviteClick}
onForgetClick={showForgetButton ? onForgetClick : null}

View File

@@ -46,7 +46,7 @@ import { RoomHierarchy } from "matrix-js-sdk/src/room-hierarchy";
import classNames from "classnames";
import { sortBy, uniqBy } from "lodash";
import { logger } from "matrix-js-sdk/src/logger";
import { SpaceChildEventContent } from "matrix-js-sdk/src/types";
import { KnownMembership, SpaceChildEventContent } from "matrix-js-sdk/src/types";
import defaultDispatcher from "../../dispatcher/dispatcher";
import { _t } from "../../languageHandler";
@@ -113,7 +113,7 @@ const Tile: React.FC<ITileProps> = ({
const cli = useContext(MatrixClientContext);
const joinedRoom = useTypedEventEmitterState(cli, ClientEvent.Room, () => {
const cliRoom = cli?.getRoom(room.room_id);
return cliRoom?.getMyMembership() === "join" ? cliRoom : undefined;
return cliRoom?.getMyMembership() === KnownMembership.Join ? cliRoom : undefined;
});
const joinedRoomName = useTypedEventEmitterState(joinedRoom, RoomEvent.Name, (room) => room?.name);
const name =
@@ -829,7 +829,7 @@ const SpaceHierarchy: React.FC<IProps> = ({ space, initialText = "", showRoom, a
content = <Spinner />;
} else {
const hasPermissions =
space?.getMyMembership() === "join" &&
space?.getMyMembership() === KnownMembership.Join &&
space.currentState.maySendStateEvent(EventType.SpaceChild, cli.getSafeUserId());
const root = hierarchy.roomMap.get(space.roomId);
@@ -847,7 +847,7 @@ const SpaceHierarchy: React.FC<IProps> = ({ space, initialText = "", showRoom, a
onViewRoomClick={(roomId, roomType) => showRoom(cli, hierarchy, roomId, roomType)}
onJoinRoomClick={async (roomId, parents) => {
for (const parent of parents) {
if (cli.getRoom(parent)?.getMyMembership() !== "join") {
if (cli.getRoom(parent)?.getMyMembership() !== KnownMembership.Join) {
await joinRoom(cli, hierarchy, parent);
}
}

View File

@@ -15,6 +15,7 @@ limitations under the License.
*/
import { EventType, RoomType, JoinRule, Preset, Room, RoomEvent } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { logger } from "matrix-js-sdk/src/logger";
import React, { useCallback, useContext, useRef, useState } from "react";
@@ -237,7 +238,7 @@ const SpaceLanding: React.FC<{ space: Room }> = ({ space }) => {
}
const hasAddRoomPermissions =
myMembership === "join" && space.currentState.maySendStateEvent(EventType.SpaceChild, userId);
myMembership === KnownMembership.Join && space.currentState.maySendStateEvent(EventType.SpaceChild, userId);
let addRoomButton;
if (hasAddRoomPermissions) {
@@ -678,7 +679,7 @@ export default class SpaceRoomView extends React.PureComponent<IProps, IState> {
private renderBody(): JSX.Element {
switch (this.state.phase) {
case Phase.Landing:
if (this.state.myMembership === "join") {
if (this.state.myMembership === KnownMembership.Join) {
return <SpaceLanding space={this.props.space} />;
} else {
return (

View File

@@ -39,6 +39,7 @@ import {
ThreadEvent,
ReceiptType,
} from "matrix-js-sdk/src/matrix";
import { KnownMembership, Membership } from "matrix-js-sdk/src/types";
import { debounce, findLastIndex, throttle } from "lodash";
import { logger } from "matrix-js-sdk/src/logger";
@@ -1824,7 +1825,7 @@ class TimelinePanel extends React.Component<IProps, IState> {
// that the event belongs to, and traversing the timeline looking for
// that event, while keeping track of the user's membership
let i = events.length - 1;
let userMembership = "leave";
let userMembership: Membership = KnownMembership.Leave;
for (; i >= 0; i--) {
const timeline = this.props.timelineSet.getTimelineForEvent(events[i].getId()!);
if (!timeline) {
@@ -1837,14 +1838,15 @@ class TimelinePanel extends React.Component<IProps, IState> {
continue;
}
userMembership = timeline.getState(EventTimeline.FORWARDS)?.getMember(userId)?.membership ?? "leave";
userMembership =
timeline.getState(EventTimeline.FORWARDS)?.getMember(userId)?.membership ?? KnownMembership.Leave;
const timelineEvents = timeline.getEvents();
for (let j = timelineEvents.length - 1; j >= 0; j--) {
const event = timelineEvents[j];
if (event.getId() === events[i].getId()) {
break;
} else if (event.getStateKey() === userId && event.getType() === EventType.RoomMember) {
userMembership = event.getPrevContent().membership || "leave";
userMembership = event.getPrevContent().membership || KnownMembership.Leave;
}
}
break;
@@ -1855,8 +1857,11 @@ class TimelinePanel extends React.Component<IProps, IState> {
for (; i >= 0; i--) {
const event = events[i];
if (event.getStateKey() === userId && event.getType() === EventType.RoomMember) {
userMembership = event.getPrevContent().membership || "leave";
} else if (userMembership === "leave" && (event.isDecryptionFailure() || event.isBeingDecrypted())) {
userMembership = event.getPrevContent().membership || KnownMembership.Leave;
} else if (
userMembership === KnownMembership.Leave &&
(event.isDecryptionFailure() || event.isBeingDecrypted())
) {
// reached an undecryptable message when the user wasn't in the room -- don't try to load any more
// Note: for now, we assume that events that are being decrypted are
// not decryptable - we will be called once more when it is decrypted.

View File

@@ -16,6 +16,7 @@ limitations under the License.
import React, { ReactNode } from "react";
import { EventType, M_BEACON_INFO, MatrixEvent } from "matrix-js-sdk/src/matrix";
import { KnownMembership } from "matrix-js-sdk/src/types";
import { BaseGrouper } from "./BaseGrouper";
import MessagePanel, { WrappedEvent } from "../MessagePanel";
@@ -48,7 +49,8 @@ export class CreationGrouper extends BaseGrouper {
const eventType = event.getType();
if (
eventType === EventType.RoomMember &&
(event.getStateKey() !== createEvent.getSender() || event.getContent()["membership"] !== "join")
(event.getStateKey() !== createEvent.getSender() ||
event.getContent()["membership"] !== KnownMembership.Join)
) {
return false;
}