Allow knocking rooms (#11353)

Signed-off-by: Charly Nguyen <charly.nguyen@nordeck.net>
This commit is contained in:
Charly Nguyen 2023-08-07 08:27:09 +02:00 committed by GitHub
parent e6af09e424
commit 5152aad059
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 689 additions and 7 deletions

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import React, { ReactNode } from "react";
import React, { ChangeEvent, ReactNode } from "react";
import { Room, RoomMember } from "matrix-js-sdk/src/matrix";
import { MatrixError } from "matrix-js-sdk/src/http-api";
import { EventType, RoomType } from "matrix-js-sdk/src/@types/event";
@ -35,6 +35,8 @@ import RoomAvatar from "../avatars/RoomAvatar";
import SettingsStore from "../../../settings/SettingsStore";
import { UIFeature } from "../../../settings/UIFeature";
import { ModuleRunner } from "../../../modules/ModuleRunner";
import { Icon as AskToJoinIcon } from "../../../../res/img/element-icons/ask-to-join.svg";
import Field from "../elements/Field";
const MemberEventHtmlReasonField = "io.element.html_reason";
@ -53,6 +55,8 @@ enum MessageCase {
ViewingRoom = "ViewingRoom",
RoomNotFound = "RoomNotFound",
OtherError = "OtherError",
PromptAskToJoin = "PromptAskToJoin",
Knocked = "Knocked",
}
interface IProps {
@ -95,6 +99,11 @@ interface IProps {
onRejectClick?(): void;
onRejectAndIgnoreClick?(): void;
onForgetClick?(): void;
promptAskToJoin?: boolean;
knocked?: boolean;
onSubmitAskToJoin?(reason?: string): void;
onCancelAskToJoin?(): void;
}
interface IState {
@ -102,6 +111,7 @@ interface IState {
accountEmails?: string[];
invitedEmailMxid?: string;
threePidFetchError?: MatrixError;
reason?: string;
}
export default class RoomPreviewBar extends React.Component<IProps, IState> {
@ -186,6 +196,10 @@ export default class RoomPreviewBar extends React.Component<IProps, IState> {
return MessageCase.Rejecting;
} else if (this.props.loading || this.state.busy) {
return MessageCase.Loading;
} else if (this.props.knocked) {
return MessageCase.Knocked;
} else if (this.props.promptAskToJoin) {
return MessageCase.PromptAskToJoin;
}
if (this.props.inviterName) {
@ -281,6 +295,10 @@ export default class RoomPreviewBar extends React.Component<IProps, IState> {
dis.dispatch({ action: "start_registration", screenAfterLogin: this.makeScreenAfterLogin() });
};
private onChangeReason = (event: ChangeEvent<HTMLTextAreaElement>): void => {
this.setState({ reason: event.target.value });
};
public render(): React.ReactNode {
const brand = SdkConfig.get().brand;
const roomName = this.props.room?.name ?? this.props.roomAlias ?? "";
@ -581,6 +599,54 @@ export default class RoomPreviewBar extends React.Component<IProps, IState> {
];
break;
}
case MessageCase.PromptAskToJoin: {
if (roomName) {
title = _t("Ask to join %(roomName)s?", { roomName });
} else {
title = _t("Ask to join?");
}
const avatar = <RoomAvatar room={this.props.room} oobData={this.props.oobData} />;
subTitle = [
avatar,
_t(
"You need to be granted access to this room in order to view or participate in the conversation. You can send a request to join below.",
),
];
reasonElement = (
<Field
autoFocus
className="mx_RoomPreviewBar_fullWidth"
element="textarea"
onChange={this.onChangeReason}
placeholder={_t("Message (optional)")}
type="text"
value={this.state.reason ?? ""}
/>
);
primaryActionHandler = () =>
this.props.onSubmitAskToJoin && this.props.onSubmitAskToJoin(this.state.reason);
primaryActionLabel = _t("Request access");
break;
}
case MessageCase.Knocked: {
title = _t("Request to join sent");
subTitle = [
<>
<AskToJoinIcon className="mx_Icon mx_Icon_16 mx_RoomPreviewBar_icon" />
{_t("Your request to join is pending.")}
</>,
];
secondaryActionHandler = this.props.onCancelAskToJoin;
secondaryActionLabel = _t("Cancel request");
break;
}
}
let subTitleElements;
@ -650,7 +716,13 @@ export default class RoomPreviewBar extends React.Component<IProps, IState> {
{subTitleElements}
</div>
{reasonElement}
<div className="mx_RoomPreviewBar_actions">{actions}</div>
<div
className={classNames("mx_RoomPreviewBar_actions", {
mx_RoomPreviewBar_fullWidth: messageCase === MessageCase.PromptAskToJoin,
})}
>
{actions}
</div>
<div className="mx_RoomPreviewBar_footer">{footer}</div>
</div>
);