Merge branch 'develop' of github.com:matrix-org/matrix-react-sdk into t3chguy/fix/18088

This commit is contained in:
Michael Telatynski 2021-09-16 10:05:20 +01:00
commit e17318a364
52 changed files with 1571 additions and 1266 deletions

View file

@ -56,7 +56,7 @@ export const createSpace = async (
power_level_content_override: {
// Only allow Admins to write to the timeline to prevent hidden sync spam
events_default: 100,
...isPublic ? { invite: 0 } : {},
invite: isPublic ? 0 : 50,
},
room_alias_name: isPublic && alias ? alias.substr(1, alias.indexOf(":") - 1) : undefined,
topic,
@ -97,9 +97,8 @@ const spaceNameValidator = withValidation({
],
});
const nameToAlias = (name: string, domain: string): string => {
const localpart = name.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9_-]+/gi, "");
return `#${localpart}:${domain}`;
const nameToLocalpart = (name: string): string => {
return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9_-]+/gi, "");
};
// XXX: Temporary for the Spaces release only
@ -174,8 +173,9 @@ export const SpaceCreateForm: React.FC<ISpaceCreateFormProps> = ({
value={name}
onChange={ev => {
const newName = ev.target.value;
if (!alias || alias === nameToAlias(name, domain)) {
setAlias(nameToAlias(newName, domain));
if (!alias || alias === `#${nameToLocalpart(name)}:${domain}`) {
setAlias(`#${nameToLocalpart(newName)}:${domain}`);
aliasFieldRef.current?.validate({ allowEmpty: true });
}
setName(newName);
}}
@ -192,7 +192,7 @@ export const SpaceCreateForm: React.FC<ISpaceCreateFormProps> = ({
onChange={setAlias}
domain={domain}
value={alias}
placeholder={name ? nameToAlias(name, domain) : _t("e.g. my-space")}
placeholder={name ? nameToLocalpart(name) : _t("e.g. my-space")}
label={_t("Address")}
disabled={busy}
onKeyDown={onKeyDown}
@ -215,6 +215,7 @@ export const SpaceCreateForm: React.FC<ISpaceCreateFormProps> = ({
};
const SpaceCreateMenu = ({ onFinished }) => {
const cli = useContext(MatrixClientContext);
const [visibility, setVisibility] = useState<Visibility>(null);
const [busy, setBusy] = useState<boolean>(false);
@ -231,14 +232,18 @@ const SpaceCreateMenu = ({ onFinished }) => {
setBusy(true);
// require & validate the space name field
if (!await spaceNameField.current.validate({ allowEmpty: false })) {
if (!(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 (visibility === Visibility.Public && !await spaceAliasField.current.validate({ allowEmpty: true })) {
// validate the space alias field but do not require it
const aliasLocalpart = alias.substring(1, alias.length - cli.getDomain().length - 1);
if (visibility === Visibility.Public && aliasLocalpart &&
(await spaceAliasField.current.validate({ allowEmpty: true })) === false
) {
spaceAliasField.current.focus();
spaceAliasField.current.validate({ allowEmpty: true, focused: true });
setBusy(false);
@ -246,7 +251,13 @@ const SpaceCreateMenu = ({ onFinished }) => {
}
try {
await createSpace(name, visibility === Visibility.Public, alias, topic, avatar);
await createSpace(
name,
visibility === Visibility.Public,
aliasLocalpart ? alias : undefined,
topic,
avatar,
);
onFinished();
} catch (e) {

View file

@ -25,49 +25,22 @@ import AccessibleButton from "../elements/AccessibleButton";
import AliasSettings from "../room_settings/AliasSettings";
import { useStateToggle } from "../../../hooks/useStateToggle";
import LabelledToggleSwitch from "../elements/LabelledToggleSwitch";
import StyledRadioGroup from "../elements/StyledRadioGroup";
import { useLocalEcho } from "../../../hooks/useLocalEcho";
import JoinRuleSettings from "../settings/JoinRuleSettings";
import { useRoomState } from "../../../hooks/useRoomState";
interface IProps {
matrixClient: MatrixClient;
space: Room;
closeSettingsFn(): void;
}
enum SpaceVisibility {
Unlisted = "unlisted",
Private = "private",
}
const useLocalEcho = <T extends any>(
currentFactory: () => T,
setterFn: (value: T) => Promise<unknown>,
errorFn: (error: Error) => void,
): [value: T, handler: (value: T) => void] => {
const [value, setValue] = useState(currentFactory);
const handler = async (value: T) => {
setValue(value);
try {
await setterFn(value);
} catch (e) {
setValue(currentFactory());
errorFn(e);
}
};
return [value, handler];
};
const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space }: IProps) => {
const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space, closeSettingsFn }: IProps) => {
const [error, setError] = useState("");
const userId = cli.getUserId();
const [visibility, setVisibility] = useLocalEcho<SpaceVisibility>(
() => space.getJoinRule() === JoinRule.Invite ? SpaceVisibility.Private : SpaceVisibility.Unlisted,
visibility => cli.sendStateEvent(space.roomId, EventType.RoomJoinRules, {
join_rule: visibility === SpaceVisibility.Unlisted ? JoinRule.Public : JoinRule.Invite,
}, ""),
() => setError(_t("Failed to update the visibility of this space")),
);
const joinRule = useRoomState(space, state => state.getJoinRule());
const [guestAccessEnabled, setGuestAccessEnabled] = useLocalEcho<boolean>(
() => space.currentState.getStateEvents(EventType.RoomGuestAccess, "")
?.getContent()?.guest_access === GuestAccess.CanJoin,
@ -87,14 +60,13 @@ const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space }: IProps) => {
const [showAdvancedSection, toggleAdvancedSection] = useStateToggle();
const canSetJoinRule = space.currentState.maySendStateEvent(EventType.RoomJoinRules, userId);
const canSetGuestAccess = space.currentState.maySendStateEvent(EventType.RoomGuestAccess, userId);
const canSetHistoryVisibility = space.currentState.maySendStateEvent(EventType.RoomHistoryVisibility, userId);
const canSetCanonical = space.currentState.mayClientSendStateEvent(EventType.RoomCanonicalAlias, cli);
const canonicalAliasEv = space.currentState.getStateEvents(EventType.RoomCanonicalAlias, "");
let advancedSection;
if (visibility === SpaceVisibility.Unlisted) {
if (joinRule === JoinRule.Public) {
if (showAdvancedSection) {
advancedSection = <>
<AccessibleButton onClick={toggleAdvancedSection} kind="link" className="mx_SettingsTab_showAdvanced">
@ -123,7 +95,7 @@ const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space }: IProps) => {
}
let addressesSection;
if (visibility !== SpaceVisibility.Private) {
if (space.getJoinRule() === JoinRule.Public) {
addressesSection = <>
<span className="mx_SettingsTab_subheading">{ _t("Address") }</span>
<div className="mx_SettingsTab_section mx_SettingsTab_subsectionText">
@ -149,22 +121,10 @@ const SpaceSettingsVisibilityTab = ({ matrixClient: cli, space }: IProps) => {
</div>
<div>
<StyledRadioGroup
name="spaceVisibility"
value={visibility}
onChange={setVisibility}
disabled={!canSetJoinRule}
definitions={[
{
value: SpaceVisibility.Unlisted,
label: _t("Public"),
description: _t("anyone with the link can view and join"),
}, {
value: SpaceVisibility.Private,
label: _t("Invite only"),
description: _t("only invited people can view and join"),
},
]}
<JoinRuleSettings
room={space}
onError={() => setError(_t("Failed to update the visibility of this space"))}
closeSettingsFn={closeSettingsFn}
/>
</div>

View file

@ -93,6 +93,7 @@ export const SpaceButton: React.FC<IButtonProps> = ({
notification={notificationState}
aria-label={ariaLabel}
tabIndex={tabIndex}
showUnsentTooltip={true}
/>
</div>;
}
@ -260,7 +261,7 @@ export class SpaceItem extends React.PureComponent<IItemProps, IItemState> {
render() {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { space, activeSpaces, isNested, isPanelCollapsed, onExpand, parents, innerRef,
const { space, activeSpaces, isNested, isPanelCollapsed, onExpand, parents, innerRef, dragHandleProps,
...otherProps } = this.props;
const collapsed = this.isCollapsed;
@ -299,7 +300,7 @@ export class SpaceItem extends React.PureComponent<IItemProps, IItemState> {
/> : null;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { tabIndex, ...dragHandleProps } = this.props.dragHandleProps || {};
const { tabIndex, ...restDragHandleProps } = dragHandleProps || {};
return (
<li
@ -310,7 +311,7 @@ export class SpaceItem extends React.PureComponent<IItemProps, IItemState> {
role="treeitem"
>
<SpaceButton
{...dragHandleProps}
{...restDragHandleProps}
space={space}
className={isInvite ? "mx_SpaceButton_invite" : undefined}
selected={activeSpaces.includes(space)}