alias cleanup and fixes

This commit is contained in:
or-else
2025-05-09 19:19:02 +03:00
parent 360b37ae13
commit 837013e97c
7 changed files with 83 additions and 58 deletions
+8 -5
View File
@@ -61,17 +61,20 @@ class NewTopicView extends React.Component {
if (!query) {
query = Tinode.DEL_CHAR;
} else if (!/[\s,:]/.test(query) && query != Tinode.DEL_CHAR) {
// No colons, spaces or commas, not DEL char. Try as email or phone.
// If not email or phone, treat as alias.
// No colons, spaces or commas, not DEL char. Try as email, phone, or alias.
const email = asEmail(query);
if (email) {
query = `email:${email}`;
query = `${Tinode.TAG_EMAIL}${email}`;
} else {
const tel = asPhone(query);
if (tel) {
query = `tel:${tel}`;
query = `${Tinode.TAG_PHONE}${tel}`;
} else {
query = `alias:${query}`;
if (query[0] == '@') {
// Strip the leading '@' sign if present.
query = query.substring(1);
}
query = `${Tinode.TAG_ALIAS}${query}`;
}
}
}
+18 -5
View File
@@ -15,6 +15,7 @@ export default class TagManager extends React.Component {
this.state = {
tags: this.props.tags || [],
alias: Tinode.tagByPrefix(this.props.tags, Tinode.TAG_ALIAS) || '',
tagInput: '',
activated: this.props.activated
};
@@ -29,7 +30,10 @@ export default class TagManager extends React.Component {
static getDerivedStateFromProps(nextProps, prevState) {
const tags = nextProps.tags || [];
if (!arrayEqual(tags, prevState.tags) && !prevState.activated) {
return {tags: tags};
return {
tags: tags || [],
alias: Tinode.tagByPrefix(tags, Tinode.TAG_ALIAS) || '',
};
}
return null;
}
@@ -76,8 +80,12 @@ export default class TagManager extends React.Component {
}
handleSubmit() {
// Add unprocessed input to tags, submit the list.
this.props.onSubmit(this.handleAddTag(this.state.tagInput.trim()));
// Add unprocessed input to tags.
let tags = this.handleAddTag(this.state.tagInput.trim());
// Add back the alias (and overwrite one possibly added by hand).
tags = Tinode.setUniqueTag(tags, this.state.alias);
// Submit the updated list.
this.props.onSubmit(tags);
this.setState({activated: false, tags: this.props.tags || []});
}
@@ -95,11 +103,16 @@ export default class TagManager extends React.Component {
let tags = [];
if (this.state.activated) {
this.state.tags.forEach(tag => {
tags.push({user: tag, invalid: (tag.length < minTagLength || tag.length > maxTagLength)});
if (tag != this.state.alias) {
tags.push({user: tag, invalid: (tag.length < minTagLength || tag.length > maxTagLength)});
}
});
} else {
this.state.tags.forEach(tag => {
tags.push(<span className="badge" key={tags.length}>{tag}</span>);
if (tag != this.state.alias) {
tags.push(<span className="badge" key={tags.length}>{tag}</span>);
}
});
if (tags.length == 0) {
tags = (
+16 -16
View File
@@ -38,7 +38,6 @@ const messages = defineMessages({
}
});
const ALIAS_REGEX = /^[a-z0-9][a-z0-9_\-]{3,23}$/i; // 4-24 characters, starting with letter or digit, then letters, digits, hyphen, underscore.
const ALIAS_AVAILABILITY_CHECK_DELAY = 1000; // milliseconds
class TopicDescEdit extends React.Component {
@@ -179,11 +178,10 @@ class TopicDescEdit extends React.Component {
}
handleAliasUpdate(alias) {
alias = alias.trim() || '';
const tags = this.state.tags.filter(t => !t.startsWith('alias:'));
if (alias) {
tags.push('alias:' + alias.toLowerCase());
}
alias = (alias || '').trim();
const tags = alias ?
Tinode.setUniqueTag(this.state.tags, Tinode.TAG_ALIAS + alias.toLowerCase()) :
Tinode.clearTagPrefix(this.state.tags, Tinode.TAG_ALIAS);
this.handleTagsUpdated(tags);
}
@@ -191,12 +189,13 @@ class TopicDescEdit extends React.Component {
// Reset pending delayed check.
this.cancelValidator();
alias = alias.trim();
if (!alias) {
this.setState({aliasError: ''});
return true;
}
const valid = ALIAS_REGEX.test(alias);
const valid = Tinode.isValidTagValue(alias);
if (!valid) {
this.setState({aliasError: this.props.intl.formatMessage(messages.alias_invalid)});
return false;
@@ -204,6 +203,12 @@ class TopicDescEdit extends React.Component {
this.setState({aliasError: ''});
// Setup a delayed check for alias availability.
const fnd = topic._tinode.getOrCreateFndTopic();
if (!fnd) {
// Unable to check alias availability.
this.setState({aliasError: ''});
return true;
}
this.aliasCheckPromise = {};
const validationPromise = new Promise((resolve, reject) => {
this.aliasCheckPromise.resolve = resolve;
@@ -211,15 +216,10 @@ class TopicDescEdit extends React.Component {
});
this.aliasCheckTimer = setTimeout(_ => {
this.aliasCheckTimer = null;
const fnd = this.props.tinode.getFndTopic();
fnd.subscribe()
.then(_ => fnd.setMeta({desc: {public: `alias:${alias}`}}))
.then(_ => fnd.getMeta(fnd.startMetaQuery().withTags().build()))
.then(meta => {
const taken = Array.isArray(meta.tags);
this.setState({aliasError: taken ?
this.props.intl.formatMessage(messages.alias_already_taken) : ''});
this.aliasCheckPromise.resolve(!taken)
fnd.checkTagUniqueness(`${Tinode.TAG_ALIAS}${alias}`, this.name())
.then(ok => {
this.aliasCheckPromise.resolve(ok)
this.setState({aliasError: ok ? '' : this.props.intl.formatMessage(messages.alias_already_taken)});
})
.catch(err => {
this.aliasCheckPromise.reject(err);