Improve interaction modal error handling (#26795)

This commit is contained in:
Claire 2023-09-05 23:49:48 +02:00 committed by GitHub
parent ea7de25de0
commit 548c032dbb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 51 additions and 7 deletions

View file

@ -41,5 +41,7 @@ class Api::V1::Peers::SearchController < Api::BaseController
domain = TagManager.instance.normalize_domain(domain) domain = TagManager.instance.normalize_domain(domain)
@domains = Instance.searchable.where(Instance.arel_table[:domain].matches("#{Instance.sanitize_sql_like(domain)}%", false, true)).limit(10).pluck(:domain) @domains = Instance.searchable.where(Instance.arel_table[:domain].matches("#{Instance.sanitize_sql_like(domain)}%", false, true)).limit(10).pluck(:domain)
end end
rescue Addressable::URI::InvalidURIError
@domains = []
end end
end end

View file

@ -100,8 +100,41 @@ class LoginForm extends React.PureComponent {
this.input = c; this.input = c;
}; };
isValueValid = (value) => {
let likelyAcct = false;
let url = null;
if (value.startsWith('/')) {
return false;
}
if (value.startsWith('@')) {
value = value.slice(1);
likelyAcct = true;
}
// The user is in the middle of typing something, do not error out
if (value === '') {
return true;
}
if (/^https?:\/\//.test(value) && !likelyAcct) {
url = value;
} else {
url = `https://${value}`;
}
try {
new URL(url);
return true;
} catch(_) {
return false;
}
};
handleChange = ({ target }) => { handleChange = ({ target }) => {
this.setState(state => ({ value: target.value, isLoading: true, error: false, options: addInputToOptions(target.value, state.networkOptions) }), () => this._loadOptions()); const error = !this.isValueValid(target.value);
this.setState(state => ({ error, value: target.value, isLoading: true, options: addInputToOptions(target.value, state.networkOptions) }), () => this._loadOptions());
}; };
handleMessage = (event) => { handleMessage = (event) => {
@ -115,11 +148,18 @@ class LoginForm extends React.PureComponent {
this.setState({ isSubmitting: false, error: true }); this.setState({ isSubmitting: false, error: true });
} else if (event.data?.type === 'fetchInteractionURL-success') { } else if (event.data?.type === 'fetchInteractionURL-success') {
if (/^https?:\/\//.test(event.data.template)) { if (/^https?:\/\//.test(event.data.template)) {
try {
const url = new URL(event.data.template.replace('{uri}', encodeURIComponent(resourceUrl)));
if (localStorage) { if (localStorage) {
localStorage.setItem(PERSISTENCE_KEY, event.data.uri_or_domain); localStorage.setItem(PERSISTENCE_KEY, event.data.uri_or_domain);
} }
window.location.href = event.data.template.replace('{uri}', encodeURIComponent(resourceUrl)); window.location.href = url;
} catch (e) {
console.error(e);
this.setState({ isSubmitting: false, error: true });
}
} else { } else {
this.setState({ isSubmitting: false, error: true }); this.setState({ isSubmitting: false, error: true });
} }
@ -259,7 +299,7 @@ class LoginForm extends React.PureComponent {
spellcheck='false' spellcheck='false'
/> />
<Button onClick={this.handleSubmit} disabled={isSubmitting}><FormattedMessage id='interaction_modal.login.action' defaultMessage='Take me home' /></Button> <Button onClick={this.handleSubmit} disabled={isSubmitting || error}><FormattedMessage id='interaction_modal.login.action' defaultMessage='Take me home' /></Button>
</div> </div>
{hasPopOut && ( {hasPopOut && (

View file

@ -140,7 +140,9 @@ const fromAcct = (acct: string) => {
}; };
const fetchInteractionURL = (uri_or_domain: string) => { const fetchInteractionURL = (uri_or_domain: string) => {
if (/^https?:\/\//.test(uri_or_domain)) { if (uri_or_domain === '') {
fetchInteractionURLFailure();
} else if (/^https?:\/\//.test(uri_or_domain)) {
fromURL(uri_or_domain); fromURL(uri_or_domain);
} else if (uri_or_domain.includes('@')) { } else if (uri_or_domain.includes('@')) {
fromAcct(uri_or_domain); fromAcct(uri_or_domain);