Convert RoomAliasField to Typescript
This commit is contained in:
parent
12e013508d
commit
b2b95257a8
3 changed files with 48 additions and 36 deletions
|
@ -29,6 +29,11 @@ function getId() {
|
||||||
return `${BASE_ID}_${count++}`;
|
return `${BASE_ID}_${count++}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IValidateOpts {
|
||||||
|
focused?: boolean;
|
||||||
|
allowEmpty?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
// The field's ID, which binds the input and label together. Immutable.
|
// The field's ID, which binds the input and label together. Immutable.
|
||||||
id?: string;
|
id?: string;
|
||||||
|
@ -180,7 +185,7 @@ export default class Field extends React.PureComponent<PropShapes, IState> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public async validate({ focused, allowEmpty = true }: {focused?: boolean, allowEmpty?: boolean}) {
|
public async validate({ focused, allowEmpty = true }: IValidateOpts) {
|
||||||
if (!this.props.onValidate) {
|
if (!this.props.onValidate) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
Copyright 2019 New Vector Ltd
|
Copyright 2019, 2021 The Matrix.org Foundation C.I.C.
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
you may not use this file except in compliance with the License.
|
you may not use this file except in compliance with the License.
|
||||||
|
@ -13,67 +13,74 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
See the License for the specific language governing permissions and
|
See the License for the specific language governing permissions and
|
||||||
limitations under the License.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import React, { createRef } from "react";
|
||||||
|
|
||||||
import { _t } from '../../../languageHandler';
|
import { _t } from '../../../languageHandler';
|
||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import * as sdk from '../../../index';
|
|
||||||
import withValidation from './Validation';
|
import withValidation from './Validation';
|
||||||
import {MatrixClientPeg} from '../../../MatrixClientPeg';
|
import { MatrixClientPeg } from '../../../MatrixClientPeg';
|
||||||
import {replaceableComponent} from "../../../utils/replaceableComponent";
|
import { replaceableComponent } from "../../../utils/replaceableComponent";
|
||||||
|
import Field, { IValidateOpts } from "./Field";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
domain: string;
|
||||||
|
value: string;
|
||||||
|
label?: string;
|
||||||
|
placeholder?: string;
|
||||||
|
onChange?(value: string): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IState {
|
||||||
|
isValid: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
// Controlled form component wrapping Field for inputting a room alias scoped to a given domain
|
// Controlled form component wrapping Field for inputting a room alias scoped to a given domain
|
||||||
@replaceableComponent("views.elements.RoomAliasField")
|
@replaceableComponent("views.elements.RoomAliasField")
|
||||||
export default class RoomAliasField extends React.PureComponent {
|
export default class RoomAliasField extends React.PureComponent<IProps, IState> {
|
||||||
static propTypes = {
|
private fieldRef = createRef<Field>();
|
||||||
domain: PropTypes.string.isRequired,
|
|
||||||
onChange: PropTypes.func,
|
public state = {
|
||||||
value: PropTypes.string.isRequired,
|
isValid: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
constructor(props) {
|
private asFullAlias(localpart: string): string {
|
||||||
super(props);
|
|
||||||
this.state = {isValid: true};
|
|
||||||
}
|
|
||||||
|
|
||||||
_asFullAlias(localpart) {
|
|
||||||
return `#${localpart}:${this.props.domain}`;
|
return `#${localpart}:${this.props.domain}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const Field = sdk.getComponent('views.elements.Field');
|
|
||||||
const poundSign = (<span>#</span>);
|
const poundSign = (<span>#</span>);
|
||||||
const aliasPostfix = ":" + this.props.domain;
|
const aliasPostfix = ":" + this.props.domain;
|
||||||
const domain = (<span title={aliasPostfix}>{aliasPostfix}</span>);
|
const domain = (<span title={aliasPostfix}>{aliasPostfix}</span>);
|
||||||
const maxlength = 255 - this.props.domain.length - 2; // 2 for # and :
|
const maxlength = 255 - this.props.domain.length - 2; // 2 for # and :
|
||||||
return (
|
return (
|
||||||
<Field
|
<Field
|
||||||
label={_t("Room address")}
|
label={this.props.label || _t("Room address")}
|
||||||
className="mx_RoomAliasField"
|
className="mx_RoomAliasField"
|
||||||
prefixComponent={poundSign}
|
prefixComponent={poundSign}
|
||||||
postfixComponent={domain}
|
postfixComponent={domain}
|
||||||
ref={ref => this._fieldRef = ref}
|
ref={this.fieldRef}
|
||||||
onValidate={this._onValidate}
|
onValidate={this.onValidate}
|
||||||
placeholder={_t("e.g. my-room")}
|
placeholder={this.props.placeholder || _t("e.g. my-room")}
|
||||||
onChange={this._onChange}
|
onChange={this.onChange}
|
||||||
value={this.props.value.substring(1, this.props.value.length - this.props.domain.length - 1)}
|
value={this.props.value.substring(1, this.props.value.length - this.props.domain.length - 1)}
|
||||||
maxLength={maxlength}
|
maxLength={maxlength}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
_onChange = (ev) => {
|
private onChange = (ev) => {
|
||||||
if (this.props.onChange) {
|
if (this.props.onChange) {
|
||||||
this.props.onChange(this._asFullAlias(ev.target.value));
|
this.props.onChange(this.asFullAlias(ev.target.value));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
_onValidate = async (fieldState) => {
|
private onValidate = async (fieldState) => {
|
||||||
const result = await this._validationRules(fieldState);
|
const result = await this.validationRules(fieldState);
|
||||||
this.setState({isValid: result.valid});
|
this.setState({isValid: result.valid});
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
_validationRules = withValidation({
|
private validationRules = withValidation({
|
||||||
rules: [
|
rules: [
|
||||||
{
|
{
|
||||||
key: "safeLocalpart",
|
key: "safeLocalpart",
|
||||||
|
@ -81,7 +88,7 @@ export default class RoomAliasField extends React.PureComponent {
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const fullAlias = this._asFullAlias(value);
|
const fullAlias = this.asFullAlias(value);
|
||||||
// XXX: FIXME https://github.com/matrix-org/matrix-doc/issues/668
|
// XXX: FIXME https://github.com/matrix-org/matrix-doc/issues/668
|
||||||
return !value.includes("#") && !value.includes(":") && !value.includes(",") &&
|
return !value.includes("#") && !value.includes(":") && !value.includes(",") &&
|
||||||
encodeURI(fullAlias) === fullAlias;
|
encodeURI(fullAlias) === fullAlias;
|
||||||
|
@ -90,7 +97,7 @@ export default class RoomAliasField extends React.PureComponent {
|
||||||
}, {
|
}, {
|
||||||
key: "required",
|
key: "required",
|
||||||
test: async ({ value, allowEmpty }) => allowEmpty || !!value,
|
test: async ({ value, allowEmpty }) => allowEmpty || !!value,
|
||||||
invalid: () => _t("Please provide a room address"),
|
invalid: () => _t("Please provide an address"),
|
||||||
}, {
|
}, {
|
||||||
key: "taken",
|
key: "taken",
|
||||||
final: true,
|
final: true,
|
||||||
|
@ -100,7 +107,7 @@ export default class RoomAliasField extends React.PureComponent {
|
||||||
}
|
}
|
||||||
const client = MatrixClientPeg.get();
|
const client = MatrixClientPeg.get();
|
||||||
try {
|
try {
|
||||||
await client.getRoomIdForAlias(this._asFullAlias(value));
|
await client.getRoomIdForAlias(this.asFullAlias(value));
|
||||||
// we got a room id, so the alias is taken
|
// we got a room id, so the alias is taken
|
||||||
return false;
|
return false;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -120,11 +127,11 @@ export default class RoomAliasField extends React.PureComponent {
|
||||||
return this.state.isValid;
|
return this.state.isValid;
|
||||||
}
|
}
|
||||||
|
|
||||||
validate(options) {
|
validate(options: IValidateOpts) {
|
||||||
return this._fieldRef.validate(options);
|
return this.fieldRef.current?.validate(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
focus() {
|
focus() {
|
||||||
this._fieldRef.focus();
|
this.fieldRef.current?.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2014,7 +2014,7 @@
|
||||||
"Room address": "Room address",
|
"Room address": "Room address",
|
||||||
"e.g. my-room": "e.g. my-room",
|
"e.g. my-room": "e.g. my-room",
|
||||||
"Some characters not allowed": "Some characters not allowed",
|
"Some characters not allowed": "Some characters not allowed",
|
||||||
"Please provide a room address": "Please provide a room address",
|
"Please provide an address": "Please provide an address",
|
||||||
"This address is available to use": "This address is available to use",
|
"This address is available to use": "This address is available to use",
|
||||||
"This address is already in use": "This address is already in use",
|
"This address is already in use": "This address is already in use",
|
||||||
"Server Options": "Server Options",
|
"Server Options": "Server Options",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue