-
+
+
diff --git a/app/soapbox/features/auth_login/components/login_page.js b/app/soapbox/features/auth_login/components/login_page.js
index c660c467e..3e2cea0e1 100644
--- a/app/soapbox/features/auth_login/components/login_page.js
+++ b/app/soapbox/features/auth_login/components/login_page.js
@@ -28,7 +28,7 @@ class LoginPage extends ImmutablePureComponent {
getFormData = (form) => {
return Object.fromEntries(
- Array.from(form).map(i => [i.name, i.value])
+ Array.from(form).map(i => [i.name, i.value]),
);
}
diff --git a/app/soapbox/features/auth_login/components/otp_auth_form.js b/app/soapbox/features/auth_login/components/otp_auth_form.js
index 49aa3c735..091d2a48f 100644
--- a/app/soapbox/features/auth_login/components/otp_auth_form.js
+++ b/app/soapbox/features/auth_login/components/otp_auth_form.js
@@ -29,7 +29,7 @@ class OtpAuthForm extends ImmutablePureComponent {
getFormData = (form) => {
return Object.fromEntries(
- Array.from(form).map(i => [i.name, i.value])
+ Array.from(form).map(i => [i.name, i.value]),
);
}
diff --git a/app/soapbox/features/auth_login/components/password_reset.js b/app/soapbox/features/auth_login/components/password_reset.js
index efc1c816c..f7ca59712 100644
--- a/app/soapbox/features/auth_login/components/password_reset.js
+++ b/app/soapbox/features/auth_login/components/password_reset.js
@@ -4,7 +4,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
import { resetPassword } from 'soapbox/actions/auth';
import { SimpleForm, FieldsGroup, TextInput } from 'soapbox/features/forms';
import { Redirect } from 'react-router-dom';
-import { showAlert } from 'soapbox/actions/alerts';
+import snackbar from 'soapbox/actions/snackbar';
export default @connect()
class PasswordReset extends ImmutablePureComponent {
@@ -20,7 +20,7 @@ class PasswordReset extends ImmutablePureComponent {
this.setState({ isLoading: true });
dispatch(resetPassword(nicknameOrEmail)).then(() => {
this.setState({ isLoading: false, success: true });
- dispatch(showAlert('Password reset received. Check your email for further instructions.', ''));
+ dispatch(snackbar.info('Check your email for confirmation.'));
}).catch(error => {
this.setState({ isLoading: false });
});
@@ -37,6 +37,7 @@ class PasswordReset extends ImmutablePureComponent {
name='nickname_or_email'
label='Email or username'
placeholder='me@example.com'
+ required
/>
diff --git a/app/soapbox/features/blocks/index.js b/app/soapbox/features/blocks/index.js
index 5b34287dd..a25c6337c 100644
--- a/app/soapbox/features/blocks/index.js
+++ b/app/soapbox/features/blocks/index.js
@@ -62,7 +62,7 @@ class Blocks extends ImmutablePureComponent {
emptyMessage={emptyMessage}
>
{accountIds.map(id =>
-
+ ,
)}
diff --git a/app/soapbox/features/chats/components/chat_message_list.js b/app/soapbox/features/chats/components/chat_message_list.js
index af35f216d..b51915ae6 100644
--- a/app/soapbox/features/chats/components/chat_message_list.js
+++ b/app/soapbox/features/chats/components/chat_message_list.js
@@ -87,7 +87,7 @@ class ChatMessageList extends ImmutablePureComponent {
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
- }
+ },
);
};
@@ -110,9 +110,9 @@ class ChatMessageList extends ImmutablePureComponent {
return scrollBottom < elem.offsetHeight * 1.5;
}
- handleResize = (e) => {
+ handleResize = throttle((e) => {
if (this.isNearBottom()) this.scrollToBottom();
- }
+ }, 150);
componentDidMount() {
const { dispatch, chatId } = this.props;
diff --git a/app/soapbox/features/chats/components/chat_panes.js b/app/soapbox/features/chats/components/chat_panes.js
index 876ff9666..d16a02ee6 100644
--- a/app/soapbox/features/chats/components/chat_panes.js
+++ b/app/soapbox/features/chats/components/chat_panes.js
@@ -29,7 +29,7 @@ const mapStateToProps = state => {
return {
panesData: addChatsToPanes(state, panesData),
- unreadCount: state.get('chats').reduce((acc, curr) => acc + curr.get('unread'), 0),
+ unreadCount: state.get('chats').reduce((acc, curr) => acc + Math.min(curr.get('unread', 0), 1), 0),
};
};
@@ -78,7 +78,7 @@ class ChatPanes extends ImmutablePureComponent {
{mainWindowPane}
{panes.map((pane, i) =>
-
+ ,
)}
);
diff --git a/app/soapbox/features/compose/components/compose_form.js b/app/soapbox/features/compose/components/compose_form.js
index af8ce4263..0f3f45f41 100644
--- a/app/soapbox/features/compose/components/compose_form.js
+++ b/app/soapbox/features/compose/components/compose_form.js
@@ -160,11 +160,6 @@ class ComposeForm extends ImmutablePureComponent {
this.props.onChangeSpoilerText(e.target.value);
}
- doFocus = () => {
- if (!this.autosuggestTextarea) return;
- this.autosuggestTextarea.textarea.focus();
- }
-
setCursor = (start, end = start) => {
if (!this.autosuggestTextarea) return;
this.autosuggestTextarea.textarea.setSelectionRange(start, end);
@@ -219,8 +214,22 @@ class ComposeForm extends ImmutablePureComponent {
}
}
+ maybeUpdateCursor = prevProps => {
+ const shouldUpdate = [
+ // Autosuggest has been updated and
+ // the cursor position explicitly set
+ this.props.focusDate !== prevProps.focusDate,
+ typeof this.props.caretPosition === 'number',
+ ].every(Boolean);
+
+ if (shouldUpdate) {
+ this.setCursor(this.props.caretPosition);
+ }
+ }
+
componentDidUpdate(prevProps) {
this.maybeUpdateFocus(prevProps);
+ this.maybeUpdateCursor(prevProps);
}
render() {
diff --git a/app/soapbox/features/domain_blocks/index.js b/app/soapbox/features/domain_blocks/index.js
index 9c1e313cc..96969f1f8 100644
--- a/app/soapbox/features/domain_blocks/index.js
+++ b/app/soapbox/features/domain_blocks/index.js
@@ -63,7 +63,7 @@ class Blocks extends ImmutablePureComponent {
emptyMessage={emptyMessage}
>
{domains.map(domain =>
-
+
,
)}
diff --git a/app/soapbox/features/edit_profile/index.js b/app/soapbox/features/edit_profile/index.js
index 41a32419b..643c19c0f 100644
--- a/app/soapbox/features/edit_profile/index.js
+++ b/app/soapbox/features/edit_profile/index.js
@@ -4,7 +4,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
-import { showAlert } from 'soapbox/actions/alerts';
+import snackbar from 'soapbox/actions/snackbar';
import Column from '../ui/components/column';
import {
SimpleForm,
@@ -40,7 +40,7 @@ const mapStateToProps = state => {
// Forces fields to be maxFields size, filling empty values
const normalizeFields = (fields, maxFields) => (
ImmutableList(fields).setSize(maxFields).map(field =>
- field ? field : ImmutableMap({ name: '', value: '' })
+ field ? field : ImmutableMap({ name: '', value: '' }),
)
);
@@ -91,7 +91,7 @@ class EditProfile extends ImmutablePureComponent {
this.state.fields.forEach((f, i) =>
params = params
.set(`fields_attributes[${i}][name]`, f.get('name'))
- .set(`fields_attributes[${i}][value]`, f.get('value'))
+ .set(`fields_attributes[${i}][value]`, f.get('value')),
);
return params;
}
@@ -124,7 +124,7 @@ class EditProfile extends ImmutablePureComponent {
const { dispatch } = this.props;
dispatch(patchMe(this.getFormdata())).then(() => {
this.setState({ isLoading: false });
- dispatch(showAlert('', 'Profile saved!'));
+ dispatch(snackbar.success('Profile saved!'));
}).catch((error) => {
this.setState({ isLoading: false });
});
diff --git a/app/soapbox/features/favourites/index.js b/app/soapbox/features/favourites/index.js
index 851a4059a..1b91a0c55 100644
--- a/app/soapbox/features/favourites/index.js
+++ b/app/soapbox/features/favourites/index.js
@@ -56,7 +56,7 @@ class Favourites extends ImmutablePureComponent {
emptyMessage={emptyMessage}
>
{accountIds.map(id =>
-
+
,
)}
diff --git a/app/soapbox/features/filters/index.js b/app/soapbox/features/filters/index.js
index 60b406a82..1573263d8 100644
--- a/app/soapbox/features/filters/index.js
+++ b/app/soapbox/features/filters/index.js
@@ -14,7 +14,7 @@ import {
SelectDropdown,
Checkbox,
} from 'soapbox/features/forms';
-import { showAlert } from 'soapbox/actions/alerts';
+import snackbar from 'soapbox/actions/snackbar';
import Icon from 'soapbox/components/icon';
import ColumnSubheading from '../ui/components/column_subheading';
@@ -114,7 +114,7 @@ class Filters extends ImmutablePureComponent {
dispatch(createFilter(phrase, expires_at, context, whole_word, irreversible)).then(response => {
return dispatch(fetchFilters());
}).catch(error => {
- dispatch(showAlert('', intl.formatMessage(messages.create_error)));
+ dispatch(snackbar.error(intl.formatMessage(messages.create_error)));
});
}
@@ -123,7 +123,7 @@ class Filters extends ImmutablePureComponent {
dispatch(deleteFilter(e.currentTarget.dataset.value)).then(response => {
return dispatch(fetchFilters());
}).catch(error => {
- dispatch(showAlert('', intl.formatMessage(messages.delete_error)));
+ dispatch(snackbar.error(intl.formatMessage(messages.delete_error)));
});
}
diff --git a/app/soapbox/features/follow_requests/index.js b/app/soapbox/features/follow_requests/index.js
index b0b5d54b8..f09624cec 100644
--- a/app/soapbox/features/follow_requests/index.js
+++ b/app/soapbox/features/follow_requests/index.js
@@ -62,7 +62,7 @@ class FollowRequests extends ImmutablePureComponent {
emptyMessage={emptyMessage}
>
{accountIds.map(id =>
-
+
,
)}
diff --git a/app/soapbox/features/followers/index.js b/app/soapbox/features/followers/index.js
index 5b7be99a5..ca0d6d2be 100644
--- a/app/soapbox/features/followers/index.js
+++ b/app/soapbox/features/followers/index.js
@@ -122,7 +122,7 @@ class Followers extends ImmutablePureComponent {
emptyMessage={
}
>
{accountIds.map(id =>
-
+
,
)}
diff --git a/app/soapbox/features/following/index.js b/app/soapbox/features/following/index.js
index df2f55fb4..6a1d4c461 100644
--- a/app/soapbox/features/following/index.js
+++ b/app/soapbox/features/following/index.js
@@ -122,7 +122,7 @@ class Following extends ImmutablePureComponent {
emptyMessage={
}
>
{accountIds.map(id =>
-
+
,
)}
diff --git a/app/soapbox/features/forms/__tests__/forms-test.js b/app/soapbox/features/forms/__tests__/forms-test.js
index ffb30b273..881f6f053 100644
--- a/app/soapbox/features/forms/__tests__/forms-test.js
+++ b/app/soapbox/features/forms/__tests__/forms-test.js
@@ -15,7 +15,7 @@ import {
describe('
', () => {
it('renders correctly', () => {
expect(renderer.create(
-
+
,
).toJSON()).toMatchSnapshot();
});
});
@@ -23,7 +23,7 @@ describe('
', () => {
describe('
', () => {
it('renders correctly', () => {
expect(renderer.create(
-
+
,
).toJSON()).toMatchSnapshot();
});
});
@@ -31,7 +31,7 @@ describe('
', () => {
describe('
', () => {
it('renders correctly', () => {
expect(renderer.create(
-
+
,
).toJSON()).toMatchSnapshot();
});
});
@@ -39,7 +39,7 @@ describe('
', () => {
describe('
', () => {
it('renders correctly', () => {
expect(renderer.create(
-
+
,
).toJSON()).toMatchSnapshot();
});
});
@@ -47,7 +47,7 @@ describe('
', () => {
describe('
', () => {
it('renders correctly', () => {
expect(renderer.create(
-
+
,
).toJSON()).toMatchSnapshot();
});
});
@@ -55,7 +55,7 @@ describe('
', () => {
describe('
', () => {
it('renders correctly', () => {
expect(renderer.create(
-
+
,
).toJSON()).toMatchSnapshot();
});
});
@@ -63,7 +63,7 @@ describe('
', () => {
describe('
', () => {
it('renders correctly', () => {
expect(renderer.create(
-
+
,
).toJSON()).toMatchSnapshot();
});
});
@@ -71,7 +71,7 @@ describe('
', () => {
describe('
', () => {
it('renders correctly', () => {
expect(renderer.create(
-
+
,
).toJSON()).toMatchSnapshot();
});
});
@@ -79,7 +79,7 @@ describe('
', () => {
describe('
', () => {
it('renders correctly', () => {
expect(renderer.create(
-
+
,
).toJSON()).toMatchSnapshot();
});
});
diff --git a/app/soapbox/features/forms/index.js b/app/soapbox/features/forms/index.js
index 35e221e5f..cb3514948 100644
--- a/app/soapbox/features/forms/index.js
+++ b/app/soapbox/features/forms/index.js
@@ -173,7 +173,7 @@ export class RadioGroup extends ImmutablePureComponent {
const { label, children, onChange } = this.props;
const childrenWithProps = React.Children.map(children, child =>
- React.cloneElement(child, { onChange })
+ React.cloneElement(child, { onChange }),
);
return (
diff --git a/app/soapbox/features/getting_started/index.js b/app/soapbox/features/getting_started/index.js
index 7f2c9c0c3..34b1cbc65 100644
--- a/app/soapbox/features/getting_started/index.js
+++ b/app/soapbox/features/getting_started/index.js
@@ -102,7 +102,7 @@ class GettingStarted extends ImmutablePureComponent {
height += 34 + 48*2;
navItems.push(
-
+
,
);
height += 34;
@@ -111,7 +111,7 @@ class GettingStarted extends ImmutablePureComponent {
navItems.push(
,
,
-
+
,
);
height += 48*3;
diff --git a/app/soapbox/features/landing_page/components/registration_form.js b/app/soapbox/features/landing_page/components/registration_form.js
index 0d6a9db71..3490e8a50 100644
--- a/app/soapbox/features/landing_page/components/registration_form.js
+++ b/app/soapbox/features/landing_page/components/registration_form.js
@@ -20,6 +20,7 @@ import { getSettings } from 'soapbox/actions/settings';
const messages = defineMessages({
username: { id: 'registration.fields.username_placeholder', defaultMessage: 'Username' },
+ username_hint: { id: 'registration.fields.username_hint', defaultMessage: 'Only letters, numbers, and underscores are allowed.' },
email: { id: 'registration.fields.email_placeholder', defaultMessage: 'E-Mail address' },
password: { id: 'registration.fields.password_placeholder', defaultMessage: 'Password' },
confirm: { id: 'registration.fields.confirm_placeholder', defaultMessage: 'Password (again)' },
@@ -92,11 +93,32 @@ class RegistrationForm extends ImmutablePureComponent {
render() {
const { instance, intl } = this.props;
+ const isOpen = instance.get('registrations');
const isLoading = this.state.captchaLoading || this.state.submissionLoading;
+ if (isOpen === false) {
+ return (
+
+
+
+
+
+ {instance.get('title')} }}
+ />
+
+
+ );
+ }
+
return (
-