2021-07-23 08:46:20 +01:00
|
|
|
/*
|
2024-09-09 14:57:16 +01:00
|
|
|
Copyright 2024 New Vector Ltd.
|
2021-07-23 08:46:20 +01:00
|
|
|
Copyright 2021 The Matrix.org Foundation C.I.C.
|
|
|
|
|
|
2025-01-06 11:18:54 +00:00
|
|
|
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
|
2024-09-09 14:57:16 +01:00
|
|
|
Please see LICENSE files in the repository root for full details.
|
2021-07-23 08:46:20 +01:00
|
|
|
*/
|
|
|
|
|
|
2025-03-27 10:43:58 +00:00
|
|
|
import React, { type JSX, useRef, useState } from "react";
|
2025-02-05 13:25:06 +00:00
|
|
|
import { type Room, JoinRule } from "matrix-js-sdk/src/matrix";
|
2021-10-22 17:23:32 -05:00
|
|
|
import { logger } from "matrix-js-sdk/src/logger";
|
2021-07-23 08:46:20 +01:00
|
|
|
|
|
|
|
|
import { _t } from "../../../languageHandler";
|
|
|
|
|
import BaseDialog from "./BaseDialog";
|
2025-02-05 13:25:06 +00:00
|
|
|
import AccessibleButton, { type ButtonEvent } from "../elements/AccessibleButton";
|
2021-07-23 08:46:20 +01:00
|
|
|
import MatrixClientContext from "../../../contexts/MatrixClientContext";
|
|
|
|
|
import { BetaPill } from "../beta/BetaCard";
|
2025-02-05 13:25:06 +00:00
|
|
|
import type Field from "../elements/Field";
|
|
|
|
|
import type RoomAliasField from "../elements/RoomAliasField";
|
2021-08-04 10:37:35 +01:00
|
|
|
import { createSpace, SpaceCreateForm } from "../spaces/SpaceCreateMenu";
|
2021-07-23 08:46:20 +01:00
|
|
|
import { SubspaceSelector } from "./AddExistingToSpaceDialog";
|
|
|
|
|
import JoinRuleDropdown from "../elements/JoinRuleDropdown";
|
|
|
|
|
|
|
|
|
|
interface IProps {
|
|
|
|
|
space: Room;
|
2026-02-23 15:37:58 +00:00
|
|
|
onAddExistingSpaceClick(this: void): void;
|
|
|
|
|
onFinished(this: void, added?: boolean): void;
|
2021-07-23 08:46:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const CreateSubspaceDialog: React.FC<IProps> = ({ space, onAddExistingSpaceClick, onFinished }) => {
|
|
|
|
|
const [parentSpace, setParentSpace] = useState(space);
|
|
|
|
|
|
|
|
|
|
const [busy, setBusy] = useState<boolean>(false);
|
|
|
|
|
const [name, setName] = useState("");
|
2023-04-17 08:31:58 +01:00
|
|
|
const spaceNameField = useRef<Field>(null);
|
2021-07-23 08:46:20 +01:00
|
|
|
const [alias, setAlias] = useState("");
|
2023-04-17 08:31:58 +01:00
|
|
|
const spaceAliasField = useRef<RoomAliasField>(null);
|
2023-03-14 11:09:35 +00:00
|
|
|
const [avatar, setAvatar] = useState<File | undefined>();
|
2021-07-23 08:46:20 +01:00
|
|
|
const [topic, setTopic] = useState<string>("");
|
|
|
|
|
|
|
|
|
|
const spaceJoinRule = space.getJoinRule();
|
2022-07-08 00:32:38 -06:00
|
|
|
let defaultJoinRule = JoinRule.Restricted;
|
2021-07-23 08:46:20 +01:00
|
|
|
if (spaceJoinRule === JoinRule.Public) {
|
|
|
|
|
defaultJoinRule = JoinRule.Public;
|
|
|
|
|
}
|
|
|
|
|
const [joinRule, setJoinRule] = useState<JoinRule>(defaultJoinRule);
|
|
|
|
|
|
2023-02-13 11:39:16 +00:00
|
|
|
const onCreateSubspaceClick = async (e: ButtonEvent): Promise<void> => {
|
2021-07-23 08:46:20 +01:00
|
|
|
e.preventDefault();
|
2023-04-18 17:00:55 +01:00
|
|
|
if (busy) return;
|
2021-07-23 08:46:20 +01:00
|
|
|
|
|
|
|
|
setBusy(true);
|
|
|
|
|
// require & validate the space name field
|
2023-04-18 17:00:55 +01:00
|
|
|
if (spaceNameField.current && !(await spaceNameField.current.validate({ allowEmpty: false }))) {
|
2021-07-23 08:46:20 +01:00
|
|
|
spaceNameField.current.focus();
|
|
|
|
|
spaceNameField.current.validate({ allowEmpty: false, focused: true });
|
|
|
|
|
setBusy(false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// validate the space name alias field but do not require it
|
2023-04-18 17:00:55 +01:00
|
|
|
if (
|
|
|
|
|
spaceAliasField.current &&
|
|
|
|
|
joinRule === JoinRule.Public &&
|
2023-08-07 09:22:03 +01:00
|
|
|
!(await spaceAliasField.current.validate({ allowEmpty: true }))
|
2023-04-18 17:00:55 +01:00
|
|
|
) {
|
2021-07-23 08:46:20 +01:00
|
|
|
spaceAliasField.current.focus();
|
|
|
|
|
spaceAliasField.current.validate({ allowEmpty: true, focused: true });
|
|
|
|
|
setBusy(false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
try {
|
2023-05-30 10:36:34 +01:00
|
|
|
await createSpace(
|
|
|
|
|
space.client,
|
|
|
|
|
name,
|
|
|
|
|
joinRule === JoinRule.Public,
|
|
|
|
|
alias,
|
|
|
|
|
topic,
|
|
|
|
|
avatar,
|
|
|
|
|
{},
|
|
|
|
|
{ parentSpace, joinRule },
|
|
|
|
|
);
|
2021-07-23 08:46:20 +01:00
|
|
|
|
|
|
|
|
onFinished(true);
|
|
|
|
|
} catch (e) {
|
2021-10-15 16:30:53 +02:00
|
|
|
logger.error(e);
|
2021-07-23 08:46:20 +01:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2023-03-14 11:09:35 +00:00
|
|
|
let joinRuleMicrocopy: JSX.Element | undefined;
|
2021-07-28 19:23:33 +01:00
|
|
|
if (joinRule === JoinRule.Restricted) {
|
|
|
|
|
joinRuleMicrocopy = (
|
|
|
|
|
<p>
|
|
|
|
|
{_t(
|
2023-10-03 19:17:26 +01:00
|
|
|
"create_space|subspace_join_rule_restricted_description",
|
2021-07-28 19:23:33 +01:00
|
|
|
{},
|
|
|
|
|
{
|
2024-09-13 12:09:41 +01:00
|
|
|
SpaceName: () => <strong>{parentSpace.name}</strong>,
|
2021-07-28 19:23:33 +01:00
|
|
|
},
|
|
|
|
|
)}
|
|
|
|
|
</p>
|
|
|
|
|
);
|
|
|
|
|
} else if (joinRule === JoinRule.Public) {
|
|
|
|
|
joinRuleMicrocopy = (
|
|
|
|
|
<p>
|
|
|
|
|
{_t(
|
2023-10-03 19:17:26 +01:00
|
|
|
"create_space|subspace_join_rule_public_description",
|
2021-07-28 19:23:33 +01:00
|
|
|
{},
|
|
|
|
|
{
|
2024-09-13 12:09:41 +01:00
|
|
|
SpaceName: () => <strong>{parentSpace.name}</strong>,
|
2021-07-28 19:23:33 +01:00
|
|
|
},
|
|
|
|
|
)}
|
|
|
|
|
</p>
|
|
|
|
|
);
|
|
|
|
|
} else if (joinRule === JoinRule.Invite) {
|
2023-10-03 19:17:26 +01:00
|
|
|
joinRuleMicrocopy = <p>{_t("create_space|subspace_join_rule_invite_description")}</p>;
|
2021-07-28 19:23:33 +01:00
|
|
|
}
|
|
|
|
|
|
2021-07-23 08:46:20 +01:00
|
|
|
return (
|
|
|
|
|
<BaseDialog
|
|
|
|
|
title={
|
|
|
|
|
<SubspaceSelector
|
2023-10-03 19:17:26 +01:00
|
|
|
title={_t("create_space|subspace_dropdown_title")}
|
2021-07-23 08:46:20 +01:00
|
|
|
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 />
|
2023-10-03 19:17:26 +01:00
|
|
|
{_t("create_space|subspace_beta_notice")}
|
2022-12-12 12:24:14 +01:00
|
|
|
</div>
|
|
|
|
|
|
2021-07-23 08:46:20 +01:00
|
|
|
<SpaceCreateForm
|
|
|
|
|
busy={busy}
|
|
|
|
|
onSubmit={onCreateSubspaceClick}
|
|
|
|
|
setAvatar={setAvatar}
|
|
|
|
|
name={name}
|
2021-07-29 13:02:07 +01:00
|
|
|
setName={setName}
|
2021-07-23 08:46:20 +01:00
|
|
|
nameFieldRef={spaceNameField}
|
|
|
|
|
topic={topic}
|
|
|
|
|
setTopic={setTopic}
|
2021-07-29 13:02:07 +01:00
|
|
|
alias={alias}
|
2021-07-23 08:46:20 +01:00
|
|
|
setAlias={setAlias}
|
2021-07-29 13:02:07 +01:00
|
|
|
showAliasField={joinRule === JoinRule.Public}
|
|
|
|
|
aliasFieldRef={spaceAliasField}
|
2022-12-12 12:24:14 +01:00
|
|
|
>
|
2021-07-23 08:46:20 +01:00
|
|
|
<JoinRuleDropdown
|
2023-10-03 19:17:26 +01:00
|
|
|
label={_t("create_space|subspace_join_rule_label")}
|
|
|
|
|
labelInvite={_t("create_space|subspace_join_rule_invite_only")}
|
2023-09-26 18:35:55 +01:00
|
|
|
labelPublic={_t("common|public_space")}
|
2023-09-14 18:47:29 +01:00
|
|
|
labelRestricted={_t("create_room|join_rule_restricted")}
|
2021-07-23 08:46:20 +01:00
|
|
|
width={478}
|
|
|
|
|
value={joinRule}
|
2021-07-29 13:02:07 +01:00
|
|
|
onChange={setJoinRule}
|
2022-12-12 12:24:14 +01:00
|
|
|
/>
|
2021-07-29 13:02:07 +01:00
|
|
|
{joinRuleMicrocopy}
|
2021-07-23 08:46:20 +01:00
|
|
|
</SpaceCreateForm>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div className="mx_CreateSubspaceDialog_footer">
|
|
|
|
|
<div className="mx_CreateSubspaceDialog_footer_prompt">
|
2023-10-03 19:17:26 +01:00
|
|
|
<div>{_t("create_space|subspace_existing_space_prompt")}</div>
|
2021-07-29 13:02:07 +01:00
|
|
|
<AccessibleButton
|
2021-07-26 12:41:52 +01:00
|
|
|
kind="link"
|
2021-07-29 13:02:07 +01:00
|
|
|
onClick={() => {
|
|
|
|
|
onAddExistingSpaceClick();
|
|
|
|
|
onFinished();
|
|
|
|
|
}}
|
2022-12-12 12:24:14 +01:00
|
|
|
>
|
2023-10-03 19:17:26 +01:00
|
|
|
{_t("space|add_existing_subspace|space_dropdown_title")}
|
2022-07-08 00:32:38 -06:00
|
|
|
</AccessibleButton>
|
2021-07-23 08:46:20 +01:00
|
|
|
</div>
|
|
|
|
|
|
2021-07-23 16:03:15 +01:00
|
|
|
<AccessibleButton kind="primary_outline" disabled={busy} onClick={() => onFinished(false)}>
|
2023-08-23 11:57:22 +01:00
|
|
|
{_t("action|cancel")}
|
2021-07-26 12:41:52 +01:00
|
|
|
</AccessibleButton>
|
|
|
|
|
<AccessibleButton kind="primary" disabled={busy} onClick={onCreateSubspaceClick}>
|
2023-10-03 19:17:26 +01:00
|
|
|
{busy ? _t("create_space|subspace_adding") : _t("action|add")}
|
2021-07-23 08:46:20 +01:00
|
|
|
</AccessibleButton>
|
2021-07-23 16:03:15 +01:00
|
|
|
</div>
|
2021-07-23 08:46:20 +01:00
|
|
|
</MatrixClientContext.Provider>
|
|
|
|
|
</BaseDialog>
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
export default CreateSubspaceDialog;
|