diff --git a/res/css/structures/_SpaceRoomView.scss b/res/css/structures/_SpaceRoomView.scss index 0a42db130a..eaaaa2f797 100644 --- a/res/css/structures/_SpaceRoomView.scss +++ b/res/css/structures/_SpaceRoomView.scss @@ -188,6 +188,16 @@ $SpaceRoomViewInnerWidth: 428px; } } + &.mx_SpaceRoomView_landing_createButton { + &::before { + background-color: #368bd6; + } + + &::after { + mask-image: url('$(res)/img/element-icons/roomlist/explore.svg'); + } + } + &.mx_SpaceRoomView_landing_settingsButton { &::before { background-color: #5c56f5; diff --git a/src/components/structures/SpaceRoomView.tsx b/src/components/structures/SpaceRoomView.tsx index 49af14017e..4159a38cfe 100644 --- a/src/components/structures/SpaceRoomView.tsx +++ b/src/components/structures/SpaceRoomView.tsx @@ -46,7 +46,7 @@ import {RightPanelPhases} from "../../stores/RightPanelStorePhases"; import {SetRightPanelPhasePayload} from "../../dispatcher/payloads/SetRightPanelPhasePayload"; import {useStateArray} from "../../hooks/useStateArray"; import SpacePublicShare from "../views/spaces/SpacePublicShare"; -import {shouldShowSpaceSettings, showSpaceSettings} from "../../utils/space"; +import {showCreateNewRoom, shouldShowSpaceSettings, showSpaceSettings} from "../../utils/space"; import MemberAvatar from "../views/avatars/MemberAvatar"; interface IProps { @@ -119,6 +119,19 @@ const SpaceLanding = ({ space, onJoinButtonClicked, onRejectButtonClicked }) => ); } + const canAddRooms = myMembership === "join" && space.currentState.maySendStateEvent(EventType.SpaceChild, userId); + + let addRoomButtons; + if (canAddRooms) { + addRoomButtons = + { + showCreateNewRoom(cli, space); + }}> + { _t("Create a new room") } + + ; + } + let settingsButton; if (shouldShowSpaceSettings(cli, space)) { settingsButton = { @@ -189,6 +202,7 @@ const SpaceLanding = ({ space, onJoinButtonClicked, onRejectButtonClicked }) => { joinButtons }
{ inviteButton } + { addRoomButtons } { settingsButton }
; diff --git a/src/components/views/dialogs/CreateRoomDialog.js b/src/components/views/dialogs/CreateRoomDialog.js index 2b6bb5e187..0771b0ec45 100644 --- a/src/components/views/dialogs/CreateRoomDialog.js +++ b/src/components/views/dialogs/CreateRoomDialog.js @@ -17,6 +17,8 @@ limitations under the License. import React from 'react'; import PropTypes from 'prop-types'; +import {Room} from "matrix-js-sdk/src/models/room"; + import * as sdk from '../../../index'; import SdkConfig from '../../../SdkConfig'; import withValidation from '../elements/Validation'; @@ -30,6 +32,7 @@ export default class CreateRoomDialog extends React.Component { static propTypes = { onFinished: PropTypes.func.isRequired, defaultPublic: PropTypes.bool, + parentSpace: PropTypes.instanceOf(Room), }; constructor(props) { @@ -85,6 +88,10 @@ export default class CreateRoomDialog extends React.Component { opts.associatedWithCommunity = CommunityPrototypeStore.instance.getSelectedCommunityId(); } + if (this.props.parentSpace) { + opts.parentSpace = this.props.parentSpace; + } + return opts; } diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index cd2fcf1117..aeef76bf22 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2570,6 +2570,7 @@ "You have %(count)s unread notifications in a prior version of this room.|one": "You have %(count)s unread notification in a prior version of this room.", "Accept Invite": "Accept Invite", "Invite people": "Invite people", + "Create a new room": "Create a new room", "%(count)s members|other": "%(count)s members", "%(count)s members|one": "%(count)s member", " invited you to ": " invited you to ", diff --git a/src/utils/space.ts b/src/utils/space.ts index 2ee4d0071e..c995b860ee 100644 --- a/src/utils/space.ts +++ b/src/utils/space.ts @@ -21,6 +21,8 @@ import {EventType} from "matrix-js-sdk/src/@types/event"; import {calculateRoomVia} from "../utils/permalinks/Permalinks"; import Modal from "../Modal"; import SpaceSettingsDialog from "../components/views/dialogs/SpaceSettingsDialog"; +import CreateRoomDialog from "../components/views/dialogs/CreateRoomDialog"; +import createRoom, {IOpts} from "../createRoom"; export const shouldShowSpaceSettings = (cli: MatrixClient, space: Room) => { const userId = cli.getUserId(); @@ -46,3 +48,19 @@ export const showSpaceSettings = (cli: MatrixClient, space: Room) => { space, }, /*className=*/null, /*isPriority=*/false, /*isStatic=*/true); }; + +export const showCreateNewRoom = async (cli: MatrixClient, space: Room) => { + const modal = Modal.createTrackedDialog<[boolean, IOpts]>( + "Space Landing", + "Create Room", + CreateRoomDialog, + { + defaultPublic: space.getJoinRule() === "public", + parentSpace: space, + }, + ); + const [shouldCreate, opts] = await modal.finished; + if (shouldCreate) { + await createRoom(opts); + } +};