element-portable/src/components/views/dialogs/CreateSubspaceDialog.tsx
Michael Telatynski a6e98b0b63
Use strong over b for improved a11y semantics
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2024-09-13 12:09:41 +01:00

194 lines
7.3 KiB
TypeScript

/*
Copyright 2024 New Vector Ltd.
Copyright 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
import React, { useRef, useState } from "react";
import { Room, JoinRule } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
import { _t } from "../../../languageHandler";
import BaseDialog from "./BaseDialog";
import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton";
import MatrixClientContext from "../../../contexts/MatrixClientContext";
import { BetaPill } from "../beta/BetaCard";
import Field from "../elements/Field";
import RoomAliasField from "../elements/RoomAliasField";
import { createSpace, SpaceCreateForm } from "../spaces/SpaceCreateMenu";
import { SubspaceSelector } from "./AddExistingToSpaceDialog";
import JoinRuleDropdown from "../elements/JoinRuleDropdown";
interface IProps {
space: Room;
onAddExistingSpaceClick(): void;
onFinished(added?: boolean): void;
}
const CreateSubspaceDialog: React.FC<IProps> = ({ space, onAddExistingSpaceClick, onFinished }) => {
const [parentSpace, setParentSpace] = useState(space);
const [busy, setBusy] = useState<boolean>(false);
const [name, setName] = useState("");
const spaceNameField = useRef<Field>(null);
const [alias, setAlias] = useState("");
const spaceAliasField = useRef<RoomAliasField>(null);
const [avatar, setAvatar] = useState<File | undefined>();
const [topic, setTopic] = useState<string>("");
const spaceJoinRule = space.getJoinRule();
let defaultJoinRule = JoinRule.Restricted;
if (spaceJoinRule === JoinRule.Public) {
defaultJoinRule = JoinRule.Public;
}
const [joinRule, setJoinRule] = useState<JoinRule>(defaultJoinRule);
const onCreateSubspaceClick = async (e: ButtonEvent): Promise<void> => {
e.preventDefault();
if (busy) return;
setBusy(true);
// require & validate the space name field
if (spaceNameField.current && !(await spaceNameField.current.validate({ allowEmpty: false }))) {
spaceNameField.current.focus();
spaceNameField.current.validate({ allowEmpty: false, focused: true });
setBusy(false);
return;
}
// validate the space name alias field but do not require it
if (
spaceAliasField.current &&
joinRule === JoinRule.Public &&
!(await spaceAliasField.current.validate({ allowEmpty: true }))
) {
spaceAliasField.current.focus();
spaceAliasField.current.validate({ allowEmpty: true, focused: true });
setBusy(false);
return;
}
try {
await createSpace(
space.client,
name,
joinRule === JoinRule.Public,
alias,
topic,
avatar,
{},
{ parentSpace, joinRule },
);
onFinished(true);
} catch (e) {
logger.error(e);
}
};
let joinRuleMicrocopy: JSX.Element | undefined;
if (joinRule === JoinRule.Restricted) {
joinRuleMicrocopy = (
<p>
{_t(
"create_space|subspace_join_rule_restricted_description",
{},
{
SpaceName: () => <strong>{parentSpace.name}</strong>,
},
)}
</p>
);
} else if (joinRule === JoinRule.Public) {
joinRuleMicrocopy = (
<p>
{_t(
"create_space|subspace_join_rule_public_description",
{},
{
SpaceName: () => <strong>{parentSpace.name}</strong>,
},
)}
</p>
);
} else if (joinRule === JoinRule.Invite) {
joinRuleMicrocopy = <p>{_t("create_space|subspace_join_rule_invite_description")}</p>;
}
return (
<BaseDialog
title={
<SubspaceSelector
title={_t("create_space|subspace_dropdown_title")}
space={space}
value={parentSpace}
onChange={setParentSpace}
/>
}
className="mx_CreateSubspaceDialog"
contentId="mx_CreateSubspaceDialog"
onFinished={onFinished}
fixedWidth={false}
>
<MatrixClientContext.Provider value={space.client}>
<div className="mx_CreateSubspaceDialog_content">
<div className="mx_CreateSubspaceDialog_betaNotice">
<BetaPill />
{_t("create_space|subspace_beta_notice")}
</div>
<SpaceCreateForm
busy={busy}
onSubmit={onCreateSubspaceClick}
setAvatar={setAvatar}
name={name}
setName={setName}
nameFieldRef={spaceNameField}
topic={topic}
setTopic={setTopic}
alias={alias}
setAlias={setAlias}
showAliasField={joinRule === JoinRule.Public}
aliasFieldRef={spaceAliasField}
>
<JoinRuleDropdown
label={_t("create_space|subspace_join_rule_label")}
labelInvite={_t("create_space|subspace_join_rule_invite_only")}
labelPublic={_t("common|public_space")}
labelRestricted={_t("create_room|join_rule_restricted")}
width={478}
value={joinRule}
onChange={setJoinRule}
/>
{joinRuleMicrocopy}
</SpaceCreateForm>
</div>
<div className="mx_CreateSubspaceDialog_footer">
<div className="mx_CreateSubspaceDialog_footer_prompt">
<div>{_t("create_space|subspace_existing_space_prompt")}</div>
<AccessibleButton
kind="link"
onClick={() => {
onAddExistingSpaceClick();
onFinished();
}}
>
{_t("space|add_existing_subspace|space_dropdown_title")}
</AccessibleButton>
</div>
<AccessibleButton kind="primary_outline" disabled={busy} onClick={() => onFinished(false)}>
{_t("action|cancel")}
</AccessibleButton>
<AccessibleButton kind="primary" disabled={busy} onClick={onCreateSubspaceClick}>
{busy ? _t("create_space|subspace_adding") : _t("action|add")}
</AccessibleButton>
</div>
</MatrixClientContext.Provider>
</BaseDialog>
);
};
export default CreateSubspaceDialog;