Fix handling of enter/return in space creation menu
							parent
							
								
									45acf70b00
								
							
						
					
					
						commit
						3a75eb1226
					
				|  | @ -32,17 +32,11 @@ interface IProps { | |||
|     setTopic(topic: string): void; | ||||
| } | ||||
| 
 | ||||
| const SpaceBasicSettings = ({ | ||||
| export const SpaceAvatar = ({ | ||||
|     avatarUrl, | ||||
|     avatarDisabled = false, | ||||
|     setAvatar, | ||||
|     name = "", | ||||
|     nameDisabled = false, | ||||
|     setName, | ||||
|     topic = "", | ||||
|     topicDisabled = false, | ||||
|     setTopic, | ||||
| }: IProps) => { | ||||
| }: Pick<IProps, "avatarUrl" | "avatarDisabled" | "setAvatar">) => { | ||||
|     const avatarUploadRef = useRef<HTMLInputElement>(); | ||||
|     const [avatar, setAvatarDataUrl] = useState(avatarUrl); // avatar data url cache
 | ||||
| 
 | ||||
|  | @ -81,20 +75,34 @@ const SpaceBasicSettings = ({ | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return <div className="mx_SpaceBasicSettings_avatarContainer"> | ||||
|         { avatarSection } | ||||
|         <input type="file" ref={avatarUploadRef} onChange={(e) => { | ||||
|             if (!e.target.files?.length) return; | ||||
|             const file = e.target.files[0]; | ||||
|             setAvatar(file); | ||||
|             const reader = new FileReader(); | ||||
|             reader.onload = (ev) => { | ||||
|                 setAvatarDataUrl(ev.target.result as string); | ||||
|             }; | ||||
|             reader.readAsDataURL(file); | ||||
|         }} accept="image/*" /> | ||||
|     </div>; | ||||
| }; | ||||
| 
 | ||||
| const SpaceBasicSettings = ({ | ||||
|     avatarUrl, | ||||
|     avatarDisabled = false, | ||||
|     setAvatar, | ||||
|     name = "", | ||||
|     nameDisabled = false, | ||||
|     setName, | ||||
|     topic = "", | ||||
|     topicDisabled = false, | ||||
|     setTopic, | ||||
| }: IProps) => { | ||||
|     return <div className="mx_SpaceBasicSettings"> | ||||
|         <div className="mx_SpaceBasicSettings_avatarContainer"> | ||||
|             { avatarSection } | ||||
|             <input type="file" ref={avatarUploadRef} onChange={(e) => { | ||||
|                 if (!e.target.files?.length) return; | ||||
|                 const file = e.target.files[0]; | ||||
|                 setAvatar(file); | ||||
|                 const reader = new FileReader(); | ||||
|                 reader.onload = (ev) => { | ||||
|                     setAvatarDataUrl(ev.target.result as string); | ||||
|                 }; | ||||
|                 reader.readAsDataURL(file); | ||||
|             }} accept="image/*" /> | ||||
|         </div> | ||||
|         <SpaceAvatar avatarUrl={avatarUrl} avatarDisabled={avatarDisabled} setAvatar={setAvatar} /> | ||||
| 
 | ||||
|         <Field | ||||
|             name="spaceName" | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ See the License for the specific language governing permissions and | |||
| limitations under the License. | ||||
| */ | ||||
| 
 | ||||
| import React, {useContext, useState} from "react"; | ||||
| import React, {useContext, useRef, useState} from "react"; | ||||
| import classNames from "classnames"; | ||||
| import {EventType, RoomType, RoomCreateTypeField} from "matrix-js-sdk/src/@types/event"; | ||||
| 
 | ||||
|  | @ -23,9 +23,11 @@ import AccessibleTooltipButton from "../elements/AccessibleTooltipButton"; | |||
| import {ChevronFace, ContextMenu} from "../../structures/ContextMenu"; | ||||
| import createRoom, {IStateEvent, Preset} from "../../../createRoom"; | ||||
| import MatrixClientContext from "../../../contexts/MatrixClientContext"; | ||||
| import SpaceBasicSettings from "./SpaceBasicSettings"; | ||||
| import {SpaceAvatar} from "./SpaceBasicSettings"; | ||||
| import AccessibleButton from "../elements/AccessibleButton"; | ||||
| import FocusLock from "react-focus-lock"; | ||||
| import Field from "../elements/Field"; | ||||
| import withValidation from "../elements/Validation"; | ||||
| 
 | ||||
| const SpaceCreateMenuType = ({ title, description, className, onClick }) => { | ||||
|     return ( | ||||
|  | @ -41,17 +43,39 @@ enum Visibility { | |||
|     Private, | ||||
| } | ||||
| 
 | ||||
| const spaceNameValidator = withValidation({ | ||||
|     rules: [ | ||||
|         { | ||||
|             key: "required", | ||||
|             test: async ({ value }) => !!value, | ||||
|             invalid: () => _t("Please enter a name for the space"), | ||||
|         }, | ||||
|     ], | ||||
| }); | ||||
| 
 | ||||
| const SpaceCreateMenu = ({ onFinished }) => { | ||||
|     const cli = useContext(MatrixClientContext); | ||||
|     const [visibility, setVisibility] = useState<Visibility>(null); | ||||
|     const [name, setName] = useState(""); | ||||
|     const [avatar, setAvatar] = useState<File>(null); | ||||
|     const [topic, setTopic] = useState<string>(""); | ||||
|     const [busy, setBusy] = useState<boolean>(false); | ||||
| 
 | ||||
|     const onSpaceCreateClick = async () => { | ||||
|     const [name, setName] = useState(""); | ||||
|     const spaceNameField = useRef<Field>(); | ||||
|     const [avatar, setAvatar] = useState<File>(null); | ||||
|     const [topic, setTopic] = useState<string>(""); | ||||
| 
 | ||||
|     const onSpaceCreateClick = async (e) => { | ||||
|         e.preventDefault(); | ||||
|         if (busy) return; | ||||
| 
 | ||||
|         setBusy(true); | ||||
|         // require & validate the space name field
 | ||||
|         if (!await spaceNameField.current.validate({ allowEmpty: false })) { | ||||
|             spaceNameField.current.focus(); | ||||
|             spaceNameField.current.validate({ allowEmpty: false, focused: true }); | ||||
|             setBusy(false); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const initialState: IStateEvent[] = [ | ||||
|             { | ||||
|                 type: EventType.RoomHistoryVisibility, | ||||
|  | @ -146,9 +170,30 @@ const SpaceCreateMenu = ({ onFinished }) => { | |||
|                 } | ||||
|             </p> | ||||
| 
 | ||||
|             <SpaceBasicSettings setAvatar={setAvatar} name={name} setName={setName} topic={topic} setTopic={setTopic} /> | ||||
|             <form className="mx_SpaceBasicSettings" onSubmit={onSpaceCreateClick}> | ||||
|                 <SpaceAvatar setAvatar={setAvatar} /> | ||||
| 
 | ||||
|             <AccessibleButton kind="primary" onClick={onSpaceCreateClick} disabled={!name || busy}> | ||||
|                 <Field | ||||
|                     name="spaceName" | ||||
|                     label={_t("Name")} | ||||
|                     autoFocus={true} | ||||
|                     value={name} | ||||
|                     onChange={ev => setName(ev.target.value)} | ||||
|                     ref={spaceNameField} | ||||
|                     onValidate={spaceNameValidator} | ||||
|                 /> | ||||
| 
 | ||||
|                 <Field | ||||
|                     name="spaceTopic" | ||||
|                     element="textarea" | ||||
|                     label={_t("Description")} | ||||
|                     value={topic} | ||||
|                     onChange={ev => setTopic(ev.target.value)} | ||||
|                     rows={3} | ||||
|                 /> | ||||
|             </form> | ||||
| 
 | ||||
|             <AccessibleButton kind="primary" onClick={onSpaceCreateClick} disabled={busy}> | ||||
|                 { busy ? _t("Creating...") : _t("Create") } | ||||
|             </AccessibleButton> | ||||
|         </React.Fragment>; | ||||
|  |  | |||
|  | @ -996,6 +996,7 @@ | |||
|     "Upload": "Upload", | ||||
|     "Name": "Name", | ||||
|     "Description": "Description", | ||||
|     "Please enter a name for the space": "Please enter a name for the space", | ||||
|     "Create a space": "Create a space", | ||||
|     "Spaces are new ways to group rooms and people. To join an existing space you'll need an invite.": "Spaces are new ways to group rooms and people. To join an existing space you'll need an invite.", | ||||
|     "Public": "Public", | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Michael Telatynski
						Michael Telatynski