=> {
if (e.errcode === "M_LIMIT_EXCEEDED") {
await sleep(e.data.retry_after_ms);
await SpaceStore.instance.addRoomToSpace(space, room.roomId, via); // retry
return;
}
throw e;
});
setProgress((i) => (i ?? 0) + 1);
} catch (e) {
logger.error("Failed to add rooms to space", e);
error = true;
break;
}
}
if (!error) {
onFinished(true);
} else {
setError(error);
}
};
const busy = progress !== null;
let footer;
if (error) {
footer = (
<>
{_t("Not all selected were added")}
{_t("Try again")}
{_t("Retry")}
>
);
} else if (busy) {
footer = (
{_t("Adding rooms... (%(progress)s out of %(count)s)", {
count: selectedToAdd.size,
progress,
})}
);
} else {
let button = emptySelectionButton;
if (!button || selectedToAdd.size > 0) {
button = (
{_t("Add")}
);
}
footer = (
<>
{footerPrompt}
{button}
>
);
}
const onChange =
!busy && !error
? (checked: boolean, room: Room) => {
if (checked) {
selectedToAdd.add(room);
} else {
selectedToAdd.delete(room);
}
setSelectedToAdd(new Set(selectedToAdd));
}
: undefined;
// only count spaces when alone as they're shown on a separate modal all on their own
const numSpaces = spacesRenderer && !dmsRenderer && !roomsRenderer ? spaces.length : 0;
const numRooms = roomsRenderer ? rooms.length : 0;
const numDms = dmsRenderer ? dms.length : 0;
let noResults = true;
if (numSpaces > 0 || numRooms > 0 || numDms > 0) {
noResults = false;
}
const onScroll = (): void => {
const body = scrollRef.current?.containerRef.current;
if (!body) return;
setScrollState({
scrollTop: body.scrollTop,
height: body.clientHeight,
});
};
const wrappedRef = (body: HTMLDivElement | null): void => {
if (!body) return;
setScrollState({
scrollTop: body.scrollTop,
height: body.clientHeight,
});
};
const roomsScrollState = getScrollState(scrollState, numRooms);
const spacesScrollState = getScrollState(scrollState, numSpaces, numRooms);
const dmsScrollState = getScrollState(scrollState, numDms, numSpaces, numRooms);
return (
{rooms.length > 0 && roomsRenderer
? roomsRenderer(rooms, selectedToAdd, roomsScrollState, onChange)
: undefined}
{spaces.length > 0 && spacesRenderer
? spacesRenderer(spaces, selectedToAdd, spacesScrollState, onChange)
: null}
{dms.length > 0 && dmsRenderer ? dmsRenderer(dms, selectedToAdd, dmsScrollState, onChange) : null}
{noResults ? (
{_t("common|no_results")}
) : undefined}
{footer}
);
};
const defaultRendererFactory =
(title: TranslationKey): Renderer =>
(rooms, selectedToAdd, { scrollTop, height }, onChange) =>
(
{_t(title)}
(
{
onChange(checked, room);
}
: undefined
}
/>
)}
/>
);
export const defaultRoomsRenderer = defaultRendererFactory(_td("Rooms"));
export const defaultSpacesRenderer = defaultRendererFactory(_td("Spaces"));
export const defaultDmsRenderer = defaultRendererFactory(_td("Direct Messages"));
interface ISubspaceSelectorProps {
title: string;
space: Room;
value: Room;
onChange(space: Room): void;
}
export const SubspaceSelector: React.FC = ({ title, space, value, onChange }) => {
const options = useMemo(() => {
return [
space,
...SpaceStore.instance.getChildSpaces(space.roomId).filter((space) => {
return space.currentState.maySendStateEvent(EventType.SpaceChild, space.client.getSafeUserId());
}),
];
}, [space]);
let body;
if (options.length > 1) {
body = (
{
onChange(options.find((space) => space.roomId === key) || space);
}}
value={value.roomId}
label={_t("Space selection")}
>
{
options.map((space) => {
const classes = classNames({
mx_SubspaceSelector_dropdownOptionActive: space === value,
});
return (
{space.name || getDisplayAliasForRoom(space) || space.roomId}
);
}) as NonEmptyArray
}
);
} else {
body = (
{space.name || getDisplayAliasForRoom(space) || space.roomId}
);
}
return (
);
};
const AddExistingToSpaceDialog: React.FC = ({ space, onCreateRoomClick, onAddSubspaceClick, onFinished }) => {
const [selectedSpace, setSelectedSpace] = useState(space);
return (
}
className="mx_AddExistingToSpaceDialog"
contentId="mx_AddExistingToSpace"
onFinished={onFinished}
fixedWidth={false}
>
{_t("Want to add a new room instead?")}
{
onCreateRoomClick(ev);
onFinished();
}}
>
{_t("Create a new room")}
>
}
filterPlaceholder={_t("Search for rooms")}
roomsRenderer={defaultRoomsRenderer}
spacesRenderer={() => (
{_t("Spaces")}
{
onAddSubspaceClick();
onFinished();
}}
>
{_t("Adding spaces has moved.")}
)}
dmsRenderer={defaultDmsRenderer}
/>
);
};
export default AddExistingToSpaceDialog;