Consolidate AddExistingToSpace between Dialog and Just Me integrated flow
This commit is contained in:
parent
654ce95c74
commit
423c515708
3 changed files with 243 additions and 273 deletions
|
@ -105,6 +105,90 @@ limitations under the License.
|
||||||
mask-position: center;
|
mask-position: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mx_AddExistingToSpace_footer {
|
||||||
|
display: flex;
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
|
> span {
|
||||||
|
flex-grow: 1;
|
||||||
|
font-size: $font-12px;
|
||||||
|
line-height: $font-15px;
|
||||||
|
color: $secondary-fg-color;
|
||||||
|
|
||||||
|
.mx_ProgressBar {
|
||||||
|
height: 8px;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
|
@mixin ProgressBarBorderRadius 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AddExistingToSpace_progressText {
|
||||||
|
margin-top: 8px;
|
||||||
|
font-size: $font-15px;
|
||||||
|
line-height: $font-24px;
|
||||||
|
color: $primary-fg-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
> * {
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AddExistingToSpace_error {
|
||||||
|
padding-left: 12px;
|
||||||
|
|
||||||
|
> img {
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AddExistingToSpace_errorHeading {
|
||||||
|
font-weight: $font-semi-bold;
|
||||||
|
font-size: $font-15px;
|
||||||
|
line-height: $font-18px;
|
||||||
|
color: $notice-primary-color;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AddExistingToSpace_errorCaption {
|
||||||
|
margin-top: 4px;
|
||||||
|
font-size: $font-12px;
|
||||||
|
line-height: $font-15px;
|
||||||
|
color: $primary-fg-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AccessibleButton {
|
||||||
|
display: inline-block;
|
||||||
|
align-self: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AccessibleButton_kind_primary {
|
||||||
|
padding: 8px 36px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AddExistingToSpace_retryButton {
|
||||||
|
margin-left: 12px;
|
||||||
|
padding-left: 24px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
background-color: $primary-fg-color;
|
||||||
|
mask-repeat: no-repeat;
|
||||||
|
mask-position: center;
|
||||||
|
mask-size: contain;
|
||||||
|
mask-image: url('$(res)/img/element-icons/retry.svg');
|
||||||
|
width: 18px;
|
||||||
|
height: 18px;
|
||||||
|
left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_AccessibleButton_kind_link {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_AddExistingToSpaceDialog {
|
.mx_AddExistingToSpaceDialog {
|
||||||
|
@ -189,88 +273,4 @@ limitations under the License.
|
||||||
.mx_AddExistingToSpace {
|
.mx_AddExistingToSpace {
|
||||||
display: contents;
|
display: contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_AddExistingToSpaceDialog_footer {
|
|
||||||
display: flex;
|
|
||||||
margin-top: 20px;
|
|
||||||
|
|
||||||
> span {
|
|
||||||
flex-grow: 1;
|
|
||||||
font-size: $font-12px;
|
|
||||||
line-height: $font-15px;
|
|
||||||
color: $secondary-fg-color;
|
|
||||||
|
|
||||||
.mx_ProgressBar {
|
|
||||||
height: 8px;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
@mixin ProgressBarBorderRadius 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_AddExistingToSpaceDialog_progressText {
|
|
||||||
margin-top: 8px;
|
|
||||||
font-size: $font-15px;
|
|
||||||
line-height: $font-24px;
|
|
||||||
color: $primary-fg-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
> * {
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_AddExistingToSpaceDialog_error {
|
|
||||||
padding-left: 12px;
|
|
||||||
|
|
||||||
> img {
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_AddExistingToSpaceDialog_errorHeading {
|
|
||||||
font-weight: $font-semi-bold;
|
|
||||||
font-size: $font-15px;
|
|
||||||
line-height: $font-18px;
|
|
||||||
color: $notice-primary-color;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_AddExistingToSpaceDialog_errorCaption {
|
|
||||||
margin-top: 4px;
|
|
||||||
font-size: $font-12px;
|
|
||||||
line-height: $font-15px;
|
|
||||||
color: $primary-fg-color;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_AccessibleButton {
|
|
||||||
display: inline-block;
|
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_AccessibleButton_kind_primary {
|
|
||||||
padding: 8px 36px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_AddExistingToSpaceDialog_retryButton {
|
|
||||||
margin-left: 12px;
|
|
||||||
padding-left: 24px;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
background-color: $primary-fg-color;
|
|
||||||
mask-repeat: no-repeat;
|
|
||||||
mask-position: center;
|
|
||||||
mask-size: contain;
|
|
||||||
mask-image: url('$(res)/img/element-icons/retry.svg');
|
|
||||||
width: 18px;
|
|
||||||
height: 18px;
|
|
||||||
left: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_AccessibleButton_kind_link {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -517,40 +517,6 @@ const SpaceSetupFirstRooms = ({ space, title, description, onFinished }) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const SpaceAddExistingRooms = ({ space, onFinished }) => {
|
const SpaceAddExistingRooms = ({ space, onFinished }) => {
|
||||||
const [selectedToAdd, setSelectedToAdd] = useState(new Set<Room>());
|
|
||||||
|
|
||||||
const [busy, setBusy] = useState(false);
|
|
||||||
const [error, setError] = useState("");
|
|
||||||
|
|
||||||
let onClick = onFinished;
|
|
||||||
let buttonLabel = _t("Skip for now");
|
|
||||||
if (selectedToAdd.size > 0) {
|
|
||||||
onClick = async () => {
|
|
||||||
setBusy(true);
|
|
||||||
|
|
||||||
for (const room of selectedToAdd) {
|
|
||||||
const via = calculateRoomVia(room);
|
|
||||||
try {
|
|
||||||
await SpaceStore.instance.addRoomToSpace(space, room.roomId, via).catch(async e => {
|
|
||||||
if (e.errcode === "M_LIMIT_EXCEEDED") {
|
|
||||||
await sleep(e.data.retry_after_ms);
|
|
||||||
return SpaceStore.instance.addRoomToSpace(space, room.roomId, via); // retry
|
|
||||||
}
|
|
||||||
|
|
||||||
throw e;
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to add rooms to space", e);
|
|
||||||
setError(_t("Failed to add rooms to space"));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setBusy(false);
|
|
||||||
onFinished();
|
|
||||||
};
|
|
||||||
buttonLabel = busy ? _t("Adding...") : _t("Add");
|
|
||||||
}
|
|
||||||
|
|
||||||
return <div>
|
return <div>
|
||||||
<h1>{ _t("What do you want to organise?") }</h1>
|
<h1>{ _t("What do you want to organise?") }</h1>
|
||||||
<div className="mx_SpaceRoomView_description">
|
<div className="mx_SpaceRoomView_description">
|
||||||
|
@ -558,29 +524,18 @@ const SpaceAddExistingRooms = ({ space, onFinished }) => {
|
||||||
"no one will be informed. You can add more later.") }
|
"no one will be informed. You can add more later.") }
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{ error && <div className="mx_SpaceRoomView_errorText">{ error }</div> }
|
|
||||||
|
|
||||||
<AddExistingToSpace
|
<AddExistingToSpace
|
||||||
space={space}
|
space={space}
|
||||||
selected={selectedToAdd}
|
emptySelectionButton={
|
||||||
onChange={(checked, room) => {
|
<AccessibleButton kind="primary" onClick={onFinished}>
|
||||||
if (checked) {
|
{ _t("Skip for now") }
|
||||||
selectedToAdd.add(room);
|
</AccessibleButton>
|
||||||
} else {
|
}
|
||||||
selectedToAdd.delete(room);
|
onFinished={onFinished}
|
||||||
}
|
|
||||||
setSelectedToAdd(new Set(selectedToAdd));
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div className="mx_SpaceRoomView_buttons">
|
<div className="mx_SpaceRoomView_buttons">
|
||||||
<AccessibleButton
|
|
||||||
kind="primary"
|
|
||||||
disabled={busy}
|
|
||||||
onClick={onClick}
|
|
||||||
>
|
|
||||||
{ buttonLabel }
|
|
||||||
</AccessibleButton>
|
|
||||||
</div>
|
</div>
|
||||||
<SpaceFeedbackPrompt />
|
<SpaceFeedbackPrompt />
|
||||||
</div>;
|
</div>;
|
||||||
|
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, {useContext, useMemo, useState} from "react";
|
import React, {ReactNode, useContext, useMemo, useState} from "react";
|
||||||
import classNames from "classnames";
|
import classNames from "classnames";
|
||||||
import {Room} from "matrix-js-sdk/src/models/room";
|
import {Room} from "matrix-js-sdk/src/models/room";
|
||||||
import {MatrixClient} from "matrix-js-sdk/src/client";
|
import {MatrixClient} from "matrix-js-sdk/src/client";
|
||||||
|
@ -58,14 +58,23 @@ const Entry = ({ room, checked, onChange }) => {
|
||||||
|
|
||||||
interface IAddExistingToSpaceProps {
|
interface IAddExistingToSpaceProps {
|
||||||
space: Room;
|
space: Room;
|
||||||
selected: Set<Room>;
|
footerPrompt?: ReactNode;
|
||||||
onChange(checked: boolean, room: Room): void;
|
emptySelectionButton?: ReactNode;
|
||||||
|
onFinished(added: boolean): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const AddExistingToSpace: React.FC<IAddExistingToSpaceProps> = ({ space, selected, onChange }) => {
|
export const AddExistingToSpace: React.FC<IAddExistingToSpaceProps> = ({
|
||||||
|
space,
|
||||||
|
footerPrompt,
|
||||||
|
emptySelectionButton,
|
||||||
|
onFinished,
|
||||||
|
}) => {
|
||||||
const cli = useContext(MatrixClientContext);
|
const cli = useContext(MatrixClientContext);
|
||||||
const visibleRooms = useMemo(() => sortRooms(cli.getVisibleRooms()), [cli]);
|
const visibleRooms = useMemo(() => sortRooms(cli.getVisibleRooms()), [cli]);
|
||||||
|
|
||||||
|
const [selectedToAdd, setSelectedToAdd] = useState(new Set<Room>());
|
||||||
|
const [progress, setProgress] = useState<number>(null);
|
||||||
|
const [error, setError] = useState<Error>(null);
|
||||||
const [query, setQuery] = useState("");
|
const [query, setQuery] = useState("");
|
||||||
const lcQuery = query.toLowerCase();
|
const lcQuery = query.toLowerCase();
|
||||||
|
|
||||||
|
@ -93,120 +102,6 @@ export const AddExistingToSpace: React.FC<IAddExistingToSpaceProps> = ({ space,
|
||||||
return arr;
|
return arr;
|
||||||
}, [[], [], []]);
|
}, [[], [], []]);
|
||||||
|
|
||||||
return <div className="mx_AddExistingToSpace">
|
|
||||||
<SearchBox
|
|
||||||
className="mx_textinput_icon mx_textinput_search"
|
|
||||||
placeholder={ _t("Filter your rooms and spaces") }
|
|
||||||
onSearch={setQuery}
|
|
||||||
autoComplete={true}
|
|
||||||
autoFocus={true}
|
|
||||||
/>
|
|
||||||
<AutoHideScrollbar className="mx_AddExistingToSpace_content" id="mx_AddExistingToSpace">
|
|
||||||
{ rooms.length > 0 ? (
|
|
||||||
<div className="mx_AddExistingToSpace_section">
|
|
||||||
<h3>{ _t("Rooms") }</h3>
|
|
||||||
{ rooms.map(room => {
|
|
||||||
return <Entry
|
|
||||||
key={room.roomId}
|
|
||||||
room={room}
|
|
||||||
checked={selected.has(room)}
|
|
||||||
onChange={onChange ? (checked) => {
|
|
||||||
onChange(checked, room);
|
|
||||||
} : null}
|
|
||||||
/>;
|
|
||||||
}) }
|
|
||||||
</div>
|
|
||||||
) : undefined }
|
|
||||||
|
|
||||||
{ spaces.length > 0 ? (
|
|
||||||
<div className="mx_AddExistingToSpace_section mx_AddExistingToSpace_section_spaces">
|
|
||||||
<h3>{ _t("Spaces") }</h3>
|
|
||||||
<div className="mx_AddExistingToSpace_section_experimental">
|
|
||||||
<div>{ _t("Feeling experimental?") }</div>
|
|
||||||
<div>{ _t("You can add existing spaces to a space.") }</div>
|
|
||||||
</div>
|
|
||||||
{ spaces.map(space => {
|
|
||||||
return <Entry
|
|
||||||
key={space.roomId}
|
|
||||||
room={space}
|
|
||||||
checked={selected.has(space)}
|
|
||||||
onChange={onChange ? (checked) => {
|
|
||||||
onChange(checked, space);
|
|
||||||
} : null}
|
|
||||||
/>;
|
|
||||||
}) }
|
|
||||||
</div>
|
|
||||||
) : null }
|
|
||||||
|
|
||||||
{ dms.length > 0 ? (
|
|
||||||
<div className="mx_AddExistingToSpace_section">
|
|
||||||
<h3>{ _t("Direct Messages") }</h3>
|
|
||||||
{ dms.map(room => {
|
|
||||||
return <Entry
|
|
||||||
key={room.roomId}
|
|
||||||
room={room}
|
|
||||||
checked={selected.has(room)}
|
|
||||||
onChange={onChange ? (checked) => {
|
|
||||||
onChange(checked, room);
|
|
||||||
} : null}
|
|
||||||
/>;
|
|
||||||
}) }
|
|
||||||
</div>
|
|
||||||
) : null }
|
|
||||||
|
|
||||||
{ spaces.length + rooms.length + dms.length < 1 ? <span className="mx_AddExistingToSpace_noResults">
|
|
||||||
{ _t("No results") }
|
|
||||||
</span> : undefined }
|
|
||||||
</AutoHideScrollbar>
|
|
||||||
</div>;
|
|
||||||
};
|
|
||||||
|
|
||||||
const AddExistingToSpaceDialog: React.FC<IProps> = ({ matrixClient: cli, space, onCreateRoomClick, onFinished }) => {
|
|
||||||
const [selectedSpace, setSelectedSpace] = useState(space);
|
|
||||||
const existingSubspaces = SpaceStore.instance.getChildSpaces(space.roomId);
|
|
||||||
const [selectedToAdd, setSelectedToAdd] = useState(new Set<Room>());
|
|
||||||
|
|
||||||
const [progress, setProgress] = useState<number>(null);
|
|
||||||
const [error, setError] = useState<Error>(null);
|
|
||||||
|
|
||||||
let spaceOptionSection;
|
|
||||||
if (existingSubspaces.length > 0) {
|
|
||||||
const options = [space, ...existingSubspaces].map((space) => {
|
|
||||||
const classes = classNames("mx_AddExistingToSpaceDialog_dropdownOption", {
|
|
||||||
mx_AddExistingToSpaceDialog_dropdownOptionActive: space === selectedSpace,
|
|
||||||
});
|
|
||||||
return <div key={space.roomId} className={classes}>
|
|
||||||
<RoomAvatar room={space} width={24} height={24} />
|
|
||||||
{ space.name || getDisplayAliasForRoom(space) || space.roomId }
|
|
||||||
</div>;
|
|
||||||
});
|
|
||||||
|
|
||||||
spaceOptionSection = (
|
|
||||||
<Dropdown
|
|
||||||
id="mx_SpaceSelectDropdown"
|
|
||||||
onOptionChange={(key: string) => {
|
|
||||||
setSelectedSpace(existingSubspaces.find(space => space.roomId === key) || space);
|
|
||||||
}}
|
|
||||||
value={selectedSpace.roomId}
|
|
||||||
label={_t("Space selection")}
|
|
||||||
>
|
|
||||||
{ options }
|
|
||||||
</Dropdown>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
spaceOptionSection = <div className="mx_AddExistingToSpaceDialog_onlySpace">
|
|
||||||
{ space.name || getDisplayAliasForRoom(space) || space.roomId }
|
|
||||||
</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const title = <React.Fragment>
|
|
||||||
<RoomAvatar room={selectedSpace} height={40} width={40} />
|
|
||||||
<div>
|
|
||||||
<h1>{ _t("Add existing rooms") }</h1>
|
|
||||||
{ spaceOptionSection }
|
|
||||||
</div>
|
|
||||||
</React.Fragment>;
|
|
||||||
|
|
||||||
const addRooms = async () => {
|
const addRooms = async () => {
|
||||||
setError(null);
|
setError(null);
|
||||||
setProgress(0);
|
setProgress(0);
|
||||||
|
@ -269,20 +164,145 @@ const AddExistingToSpaceDialog: React.FC<IProps> = ({ matrixClient: cli, space,
|
||||||
</div>
|
</div>
|
||||||
</span>;
|
</span>;
|
||||||
} else {
|
} else {
|
||||||
|
let button = emptySelectionButton;
|
||||||
|
if (!button || selectedToAdd.size > 0) {
|
||||||
|
button = <AccessibleButton kind="primary" disabled={selectedToAdd.size < 1} onClick={addRooms}>
|
||||||
|
{ _t("Add") }
|
||||||
|
</AccessibleButton>;
|
||||||
|
}
|
||||||
|
|
||||||
footer = <>
|
footer = <>
|
||||||
<span>
|
<span>
|
||||||
<div>{ _t("Want to add a new room instead?") }</div>
|
{ footerPrompt }
|
||||||
<AccessibleButton onClick={() => onCreateRoomClick(cli, space)} kind="link">
|
|
||||||
{ _t("Create a new room") }
|
|
||||||
</AccessibleButton>
|
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<AccessibleButton kind="primary" disabled={selectedToAdd.size < 1} onClick={addRooms}>
|
{ button }
|
||||||
{ _t("Add") }
|
|
||||||
</AccessibleButton>
|
|
||||||
</>;
|
</>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const onChange = !busy && !error ? (checked, room) => {
|
||||||
|
if (checked) {
|
||||||
|
selectedToAdd.add(room);
|
||||||
|
} else {
|
||||||
|
selectedToAdd.delete(room);
|
||||||
|
}
|
||||||
|
setSelectedToAdd(new Set(selectedToAdd));
|
||||||
|
} : null;
|
||||||
|
|
||||||
|
return <div className="mx_AddExistingToSpace">
|
||||||
|
<SearchBox
|
||||||
|
className="mx_textinput_icon mx_textinput_search"
|
||||||
|
placeholder={ _t("Filter your rooms and spaces") }
|
||||||
|
onSearch={setQuery}
|
||||||
|
autoComplete={true}
|
||||||
|
autoFocus={true}
|
||||||
|
/>
|
||||||
|
<AutoHideScrollbar className="mx_AddExistingToSpace_content" id="mx_AddExistingToSpace">
|
||||||
|
{ rooms.length > 0 ? (
|
||||||
|
<div className="mx_AddExistingToSpace_section">
|
||||||
|
<h3>{ _t("Rooms") }</h3>
|
||||||
|
{ rooms.map(room => {
|
||||||
|
return <Entry
|
||||||
|
key={room.roomId}
|
||||||
|
room={room}
|
||||||
|
checked={selectedToAdd.has(room)}
|
||||||
|
onChange={onChange ? (checked) => {
|
||||||
|
onChange(checked, room);
|
||||||
|
} : null}
|
||||||
|
/>;
|
||||||
|
}) }
|
||||||
|
</div>
|
||||||
|
) : undefined }
|
||||||
|
|
||||||
|
{ spaces.length > 0 ? (
|
||||||
|
<div className="mx_AddExistingToSpace_section mx_AddExistingToSpace_section_spaces">
|
||||||
|
<h3>{ _t("Spaces") }</h3>
|
||||||
|
<div className="mx_AddExistingToSpace_section_experimental">
|
||||||
|
<div>{ _t("Feeling experimental?") }</div>
|
||||||
|
<div>{ _t("You can add existing spaces to a space.") }</div>
|
||||||
|
</div>
|
||||||
|
{ spaces.map(space => {
|
||||||
|
return <Entry
|
||||||
|
key={space.roomId}
|
||||||
|
room={space}
|
||||||
|
checked={selectedToAdd.has(space)}
|
||||||
|
onChange={onChange ? (checked) => {
|
||||||
|
onChange(checked, space);
|
||||||
|
} : null}
|
||||||
|
/>;
|
||||||
|
}) }
|
||||||
|
</div>
|
||||||
|
) : null }
|
||||||
|
|
||||||
|
{ dms.length > 0 ? (
|
||||||
|
<div className="mx_AddExistingToSpace_section">
|
||||||
|
<h3>{ _t("Direct Messages") }</h3>
|
||||||
|
{ dms.map(room => {
|
||||||
|
return <Entry
|
||||||
|
key={room.roomId}
|
||||||
|
room={room}
|
||||||
|
checked={selectedToAdd.has(room)}
|
||||||
|
onChange={onChange ? (checked) => {
|
||||||
|
onChange(checked, room);
|
||||||
|
} : null}
|
||||||
|
/>;
|
||||||
|
}) }
|
||||||
|
</div>
|
||||||
|
) : null }
|
||||||
|
|
||||||
|
{ spaces.length + rooms.length + dms.length < 1 ? <span className="mx_AddExistingToSpace_noResults">
|
||||||
|
{ _t("No results") }
|
||||||
|
</span> : undefined }
|
||||||
|
</AutoHideScrollbar>
|
||||||
|
|
||||||
|
<div className="mx_AddExistingToSpace_footer">
|
||||||
|
{ footer }
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
};
|
||||||
|
|
||||||
|
const AddExistingToSpaceDialog: React.FC<IProps> = ({ matrixClient: cli, space, onCreateRoomClick, onFinished }) => {
|
||||||
|
const [selectedSpace, setSelectedSpace] = useState(space);
|
||||||
|
const existingSubspaces = SpaceStore.instance.getChildSpaces(space.roomId);
|
||||||
|
|
||||||
|
let spaceOptionSection;
|
||||||
|
if (existingSubspaces.length > 0) {
|
||||||
|
const options = [space, ...existingSubspaces].map((space) => {
|
||||||
|
const classes = classNames("mx_AddExistingToSpaceDialog_dropdownOption", {
|
||||||
|
mx_AddExistingToSpaceDialog_dropdownOptionActive: space === selectedSpace,
|
||||||
|
});
|
||||||
|
return <div key={space.roomId} className={classes}>
|
||||||
|
<RoomAvatar room={space} width={24} height={24} />
|
||||||
|
{ space.name || getDisplayAliasForRoom(space) || space.roomId }
|
||||||
|
</div>;
|
||||||
|
});
|
||||||
|
|
||||||
|
spaceOptionSection = (
|
||||||
|
<Dropdown
|
||||||
|
id="mx_SpaceSelectDropdown"
|
||||||
|
onOptionChange={(key: string) => {
|
||||||
|
setSelectedSpace(existingSubspaces.find(space => space.roomId === key) || space);
|
||||||
|
}}
|
||||||
|
value={selectedSpace.roomId}
|
||||||
|
label={_t("Space selection")}
|
||||||
|
>
|
||||||
|
{ options }
|
||||||
|
</Dropdown>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
spaceOptionSection = <div className="mx_AddExistingToSpaceDialog_onlySpace">
|
||||||
|
{ space.name || getDisplayAliasForRoom(space) || space.roomId }
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const title = <React.Fragment>
|
||||||
|
<RoomAvatar room={selectedSpace} height={40} width={40} />
|
||||||
|
<div>
|
||||||
|
<h1>{ _t("Add existing rooms") }</h1>
|
||||||
|
{ spaceOptionSection }
|
||||||
|
</div>
|
||||||
|
</React.Fragment>;
|
||||||
|
|
||||||
return <BaseDialog
|
return <BaseDialog
|
||||||
title={title}
|
title={title}
|
||||||
className="mx_AddExistingToSpaceDialog"
|
className="mx_AddExistingToSpaceDialog"
|
||||||
|
@ -293,21 +313,16 @@ const AddExistingToSpaceDialog: React.FC<IProps> = ({ matrixClient: cli, space,
|
||||||
<MatrixClientContext.Provider value={cli}>
|
<MatrixClientContext.Provider value={cli}>
|
||||||
<AddExistingToSpace
|
<AddExistingToSpace
|
||||||
space={space}
|
space={space}
|
||||||
selected={selectedToAdd}
|
onFinished={onFinished}
|
||||||
onChange={!busy && !error ? (checked, room) => {
|
footerPrompt={<>
|
||||||
if (checked) {
|
<div>{ _t("Want to add a new room instead?") }</div>
|
||||||
selectedToAdd.add(room);
|
<AccessibleButton onClick={() => onCreateRoomClick(cli, space)} kind="link">
|
||||||
} else {
|
{ _t("Create a new room") }
|
||||||
selectedToAdd.delete(room);
|
</AccessibleButton>
|
||||||
}
|
</>}
|
||||||
setSelectedToAdd(new Set(selectedToAdd));
|
|
||||||
} : null}
|
|
||||||
/>
|
/>
|
||||||
</MatrixClientContext.Provider>
|
</MatrixClientContext.Provider>
|
||||||
|
|
||||||
<div className="mx_AddExistingToSpaceDialog_footer">
|
|
||||||
{ footer }
|
|
||||||
</div>
|
|
||||||
<SpaceFeedbackPrompt onClick={() => onFinished(false)} />
|
<SpaceFeedbackPrompt onClick={() => onFinished(false)} />
|
||||||
</BaseDialog>;
|
</BaseDialog>;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue