diff options
author | Starfall <us@starfall.systems> | 2023-04-14 19:22:47 -0500 |
---|---|---|
committer | Starfall <us@starfall.systems> | 2023-04-14 19:22:47 -0500 |
commit | 4fe1689de43f4404eb9530fcfbcbfb26d6c1c13a (patch) | |
tree | 6811b845bb7f4966b10dcefa3dea404246f161c7 /app/javascript/flavours/glitch/components | |
parent | 65c1e53a32cabcdbb7bca57002bb0f6acdebe07e (diff) | |
parent | bed63f6dae0879ac840066b031229e0d139089cd (diff) |
Diffstat (limited to 'app/javascript/flavours/glitch/components')
-rw-r--r-- | app/javascript/flavours/glitch/components/account.jsx (renamed from app/javascript/flavours/glitch/components/account.js) | 15 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/admin/Counter.jsx (renamed from app/javascript/flavours/glitch/components/admin/Counter.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/admin/Dimension.jsx (renamed from app/javascript/flavours/glitch/components/admin/Dimension.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/admin/ReportReasonSelector.jsx (renamed from app/javascript/flavours/glitch/components/admin/ReportReasonSelector.js) | 7 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/admin/Retention.jsx (renamed from app/javascript/flavours/glitch/components/admin/Retention.js) | 2 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/admin/Trends.jsx (renamed from app/javascript/flavours/glitch/components/admin/Trends.js) | 2 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/animated_number.jsx (renamed from app/javascript/flavours/glitch/components/animated_number.js) | 4 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/attachment_list.jsx (renamed from app/javascript/flavours/glitch/components/attachment_list.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/autosuggest_emoji.jsx (renamed from app/javascript/flavours/glitch/components/autosuggest_emoji.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/autosuggest_hashtag.jsx (renamed from app/javascript/flavours/glitch/components/autosuggest_hashtag.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/autosuggest_input.jsx (renamed from app/javascript/flavours/glitch/components/autosuggest_input.js) | 22 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/autosuggest_textarea.jsx (renamed from app/javascript/flavours/glitch/components/autosuggest_textarea.js) | 22 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/avatar.jsx (renamed from app/javascript/flavours/glitch/components/avatar.js) | 4 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/avatar_composite.jsx (renamed from app/javascript/flavours/glitch/components/avatar_composite.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/avatar_overlay.jsx (renamed from app/javascript/flavours/glitch/components/avatar_overlay.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/blurhash.jsx (renamed from app/javascript/flavours/glitch/components/blurhash.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/button.jsx (renamed from app/javascript/flavours/glitch/components/button.js) | 4 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/check.jsx (renamed from app/javascript/flavours/glitch/components/check.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/column.jsx (renamed from app/javascript/flavours/glitch/components/column.js) | 4 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/column_back_button.jsx (renamed from app/javascript/flavours/glitch/components/column_back_button.js) | 2 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/column_back_button_slim.jsx (renamed from app/javascript/flavours/glitch/components/column_back_button_slim.js) | 4 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/column_header.jsx (renamed from app/javascript/flavours/glitch/components/column_header.js) | 19 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/common_counter.jsx (renamed from app/javascript/flavours/glitch/components/common_counter.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/dismissable_banner.jsx (renamed from app/javascript/flavours/glitch/components/dismissable_banner.js) | 5 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/display_name.jsx (renamed from app/javascript/flavours/glitch/components/display_name.js) | 6 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/domain.jsx (renamed from app/javascript/flavours/glitch/components/domain.js) | 5 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/dropdown_menu.jsx (renamed from app/javascript/flavours/glitch/components/dropdown_menu.js) | 36 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/edited_timestamp/index.jsx (renamed from app/javascript/flavours/glitch/components/edited_timestamp/index.js) | 8 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/error_boundary.jsx (renamed from app/javascript/flavours/glitch/components/error_boundary.js) | 4 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/gifv.jsx (renamed from app/javascript/flavours/glitch/components/gifv.js) | 13 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/hashtag.jsx (renamed from app/javascript/flavours/glitch/components/hashtag.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/icon.jsx (renamed from app/javascript/flavours/glitch/components/icon.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/icon_button.jsx (renamed from app/javascript/flavours/glitch/components/icon_button.js) | 10 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/icon_with_badge.jsx (renamed from app/javascript/flavours/glitch/components/icon_with_badge.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/image.jsx (renamed from app/javascript/flavours/glitch/components/image.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/inline_account.jsx (renamed from app/javascript/flavours/glitch/components/inline_account.js) | 3 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/intersection_observer_article.jsx (renamed from app/javascript/flavours/glitch/components/intersection_observer_article.js) | 19 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/link.jsx (renamed from app/javascript/flavours/glitch/components/link.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/load_gap.jsx (renamed from app/javascript/flavours/glitch/components/load_gap.js) | 5 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/load_more.jsx (renamed from app/javascript/flavours/glitch/components/load_more.js) | 4 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/load_pending.jsx (renamed from app/javascript/flavours/glitch/components/load_pending.js) | 2 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/loading_indicator.jsx (renamed from app/javascript/flavours/glitch/components/loading_indicator.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/logo.jsx (renamed from app/javascript/flavours/glitch/components/logo.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/media_attachments.jsx (renamed from app/javascript/flavours/glitch/components/media_attachments.js) | 12 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/media_gallery.jsx (renamed from app/javascript/flavours/glitch/components/media_gallery.js) | 35 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/missing_indicator.jsx (renamed from app/javascript/flavours/glitch/components/missing_indicator.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/modal_root.jsx (renamed from app/javascript/flavours/glitch/components/modal_root.js) | 9 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/navigation_portal.jsx (renamed from app/javascript/flavours/glitch/components/navigation_portal.js) | 3 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/not_signed_in_indicator.jsx (renamed from app/javascript/flavours/glitch/components/not_signed_in_indicator.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/notification_purge_buttons.jsx (renamed from app/javascript/flavours/glitch/components/notification_purge_buttons.js) | 3 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/permalink.jsx (renamed from app/javascript/flavours/glitch/components/permalink.js) | 4 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/picture_in_picture_placeholder.jsx (renamed from app/javascript/flavours/glitch/components/picture_in_picture_placeholder.js) | 9 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/poll.jsx (renamed from app/javascript/flavours/glitch/components/poll.js) | 14 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/radio_button.jsx (renamed from app/javascript/flavours/glitch/components/radio_button.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/regeneration_indicator.jsx (renamed from app/javascript/flavours/glitch/components/regeneration_indicator.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/relative_timestamp.jsx (renamed from app/javascript/flavours/glitch/components/relative_timestamp.js) | 3 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/scrollable_list.jsx (renamed from app/javascript/flavours/glitch/components/scrollable_list.js) | 25 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/server_banner.jsx (renamed from app/javascript/flavours/glitch/components/server_banner.js) | 4 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/setting_text.jsx (renamed from app/javascript/flavours/glitch/components/setting_text.js) | 2 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/short_number.jsx (renamed from app/javascript/flavours/glitch/components/short_number.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/skeleton.jsx (renamed from app/javascript/flavours/glitch/components/skeleton.js) | 0 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/spoilers.jsx (renamed from app/javascript/flavours/glitch/components/spoilers.js) | 32 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/status.jsx (renamed from app/javascript/flavours/glitch/components/status.js) | 87 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/status_action_bar.jsx (renamed from app/javascript/flavours/glitch/components/status_action_bar.js) | 47 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/status_content.jsx (renamed from app/javascript/flavours/glitch/components/status_content.js) | 51 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/status_header.jsx (renamed from app/javascript/flavours/glitch/components/status_header.js) | 4 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/status_icons.jsx (renamed from app/javascript/flavours/glitch/components/status_icons.js) | 25 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/status_list.jsx (renamed from app/javascript/flavours/glitch/components/status_list.js) | 12 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/status_prepend.jsx (renamed from app/javascript/flavours/glitch/components/status_prepend.js) | 6 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/status_visibility_icon.jsx (renamed from app/javascript/flavours/glitch/components/status_visibility_icon.js) | 3 | ||||
-rw-r--r-- | app/javascript/flavours/glitch/components/timeline_hint.jsx (renamed from app/javascript/flavours/glitch/components/timeline_hint.js) | 0 |
71 files changed, 341 insertions, 280 deletions
diff --git a/app/javascript/flavours/glitch/components/account.js b/app/javascript/flavours/glitch/components/account.jsx index 8e810ce5f..7b66d5a6e 100644 --- a/app/javascript/flavours/glitch/components/account.js +++ b/app/javascript/flavours/glitch/components/account.jsx @@ -23,7 +23,6 @@ const messages = defineMessages({ block: { id: 'account.block', defaultMessage: 'Block @{name}' }, }); -export default @injectIntl class Account extends ImmutablePureComponent { static propTypes = { @@ -48,27 +47,27 @@ class Account extends ImmutablePureComponent { handleFollow = () => { this.props.onFollow(this.props.account); - } + }; handleBlock = () => { this.props.onBlock(this.props.account); - } + }; handleMute = () => { this.props.onMute(this.props.account); - } + }; handleMuteNotifications = () => { this.props.onMuteNotifications(this.props.account, true); - } + }; handleUnmuteNotifications = () => { this.props.onMuteNotifications(this.props.account, false); - } + }; handleAction = () => { this.props.onActionClick(this.props.account); - } + }; render () { const { @@ -184,3 +183,5 @@ class Account extends ImmutablePureComponent { } } + +export default injectIntl(Account); diff --git a/app/javascript/flavours/glitch/components/admin/Counter.js b/app/javascript/flavours/glitch/components/admin/Counter.jsx index 5b6a19f8d..5b6a19f8d 100644 --- a/app/javascript/flavours/glitch/components/admin/Counter.js +++ b/app/javascript/flavours/glitch/components/admin/Counter.jsx diff --git a/app/javascript/flavours/glitch/components/admin/Dimension.js b/app/javascript/flavours/glitch/components/admin/Dimension.jsx index 3dac8c6c2..3dac8c6c2 100644 --- a/app/javascript/flavours/glitch/components/admin/Dimension.js +++ b/app/javascript/flavours/glitch/components/admin/Dimension.jsx diff --git a/app/javascript/flavours/glitch/components/admin/ReportReasonSelector.js b/app/javascript/flavours/glitch/components/admin/ReportReasonSelector.jsx index 771dbb452..ecefe7a84 100644 --- a/app/javascript/flavours/glitch/components/admin/ReportReasonSelector.js +++ b/app/javascript/flavours/glitch/components/admin/ReportReasonSelector.jsx @@ -33,7 +33,7 @@ class Category extends React.PureComponent { const { id, text, disabled, selected, children } = this.props; return ( - <div tabIndex='0' role='button' className={classNames('report-reason-selector__category', { selected, disabled })} onClick={this.handleClick}> + <div tabIndex={0} role='button' className={classNames('report-reason-selector__category', { selected, disabled })} onClick={this.handleClick}> {selected && <input type='hidden' name='report[category]' value={id} />} <div className='report-reason-selector__category__label'> @@ -74,7 +74,7 @@ class Rule extends React.PureComponent { const { id, text, disabled, selected } = this.props; return ( - <div tabIndex='0' role='button' className={classNames('report-reason-selector__rule', { selected, disabled })} onClick={this.handleClick}> + <div tabIndex={0} role='button' className={classNames('report-reason-selector__rule', { selected, disabled })} onClick={this.handleClick}> <span className={classNames('poll__input', { checkbox: true, active: selected, disabled })} /> {selected && <input type='hidden' name='report[rule_ids][]' value={id} />} {text} @@ -84,7 +84,6 @@ class Rule extends React.PureComponent { } -export default @injectIntl class ReportReasonSelector extends React.PureComponent { static propTypes = { @@ -157,3 +156,5 @@ class ReportReasonSelector extends React.PureComponent { } } + +export default injectIntl(ReportReasonSelector); diff --git a/app/javascript/flavours/glitch/components/admin/Retention.js b/app/javascript/flavours/glitch/components/admin/Retention.jsx index 9cc39040b..e1ba3f6c9 100644 --- a/app/javascript/flavours/glitch/components/admin/Retention.js +++ b/app/javascript/flavours/glitch/components/admin/Retention.jsx @@ -137,7 +137,7 @@ export default class Retention extends React.PureComponent { break; default: title = <FormattedMessage id='admin.dashboard.monthly_retention' defaultMessage='User retention rate by month after sign-up' />; - }; + } return ( <div className='retention'> diff --git a/app/javascript/flavours/glitch/components/admin/Trends.js b/app/javascript/flavours/glitch/components/admin/Trends.jsx index 4c17b69a0..774bf36e6 100644 --- a/app/javascript/flavours/glitch/components/admin/Trends.js +++ b/app/javascript/flavours/glitch/components/admin/Trends.jsx @@ -50,7 +50,7 @@ export default class Trends extends React.PureComponent { <Hashtag key={hashtag.name} name={hashtag.name} - href={`/admin/tags/${hashtag.id}`} + href={hashtag.id === undefined ? undefined : `/admin/tags/${hashtag.id}`} people={hashtag.history[0].accounts * 1 + hashtag.history[1].accounts * 1} uses={hashtag.history[0].uses * 1 + hashtag.history[1].uses * 1} history={hashtag.history.reverse().map(day => day.uses)} diff --git a/app/javascript/flavours/glitch/components/animated_number.js b/app/javascript/flavours/glitch/components/animated_number.jsx index 9431c96f7..dd21d97f0 100644 --- a/app/javascript/flavours/glitch/components/animated_number.js +++ b/app/javascript/flavours/glitch/components/animated_number.jsx @@ -38,13 +38,13 @@ export default class AnimatedNumber extends React.PureComponent { const { direction } = this.state; return { y: -1 * direction }; - } + }; willLeave = () => { const { direction } = this.state; return { y: spring(1 * direction, { damping: 35, stiffness: 400 }) }; - } + }; render () { const { value, obfuscate } = this.props; diff --git a/app/javascript/flavours/glitch/components/attachment_list.js b/app/javascript/flavours/glitch/components/attachment_list.jsx index 68b80b19f..68b80b19f 100644 --- a/app/javascript/flavours/glitch/components/attachment_list.js +++ b/app/javascript/flavours/glitch/components/attachment_list.jsx diff --git a/app/javascript/flavours/glitch/components/autosuggest_emoji.js b/app/javascript/flavours/glitch/components/autosuggest_emoji.jsx index 83fafbd10..83fafbd10 100644 --- a/app/javascript/flavours/glitch/components/autosuggest_emoji.js +++ b/app/javascript/flavours/glitch/components/autosuggest_emoji.jsx diff --git a/app/javascript/flavours/glitch/components/autosuggest_hashtag.js b/app/javascript/flavours/glitch/components/autosuggest_hashtag.jsx index d787ed07a..d787ed07a 100644 --- a/app/javascript/flavours/glitch/components/autosuggest_hashtag.js +++ b/app/javascript/flavours/glitch/components/autosuggest_hashtag.jsx diff --git a/app/javascript/flavours/glitch/components/autosuggest_input.js b/app/javascript/flavours/glitch/components/autosuggest_input.jsx index b40a2ff35..ea9fd0828 100644 --- a/app/javascript/flavours/glitch/components/autosuggest_input.js +++ b/app/javascript/flavours/glitch/components/autosuggest_input.jsx @@ -50,6 +50,8 @@ export default class AutosuggestInput extends ImmutablePureComponent { id: PropTypes.string, searchTokens: PropTypes.arrayOf(PropTypes.string), maxLength: PropTypes.number, + lang: PropTypes.string, + spellCheck: PropTypes.bool, }; static defaultProps = { @@ -77,7 +79,7 @@ export default class AutosuggestInput extends ImmutablePureComponent { } this.props.onChange(e); - } + }; onKeyDown = (e) => { const { suggestions, disabled } = this.props; @@ -135,22 +137,22 @@ export default class AutosuggestInput extends ImmutablePureComponent { } this.props.onKeyDown(e); - } + }; onBlur = () => { this.setState({ suggestionsHidden: true, focused: false }); - } + }; onFocus = () => { this.setState({ focused: true }); - } + }; onSuggestionClick = (e) => { const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute('data-index')); e.preventDefault(); this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion); this.input.focus(); - } + }; componentWillReceiveProps (nextProps) { if (nextProps.suggestions !== this.props.suggestions && nextProps.suggestions.size > 0 && this.state.suggestionsHidden && this.state.focused) { @@ -160,7 +162,7 @@ export default class AutosuggestInput extends ImmutablePureComponent { setInput = (c) => { this.input = c; - } + }; renderSuggestion = (suggestion, i) => { const { selectedSuggestion } = this.state; @@ -178,14 +180,14 @@ export default class AutosuggestInput extends ImmutablePureComponent { } return ( - <div role='button' tabIndex='0' key={key} data-index={i} className={classNames('autosuggest-textarea__suggestions__item', { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}> + <div role='button' tabIndex={0} key={key} data-index={i} className={classNames('autosuggest-textarea__suggestions__item', { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}> {inner} </div> ); - } + }; render () { - const { value, suggestions, disabled, placeholder, onKeyUp, autoFocus, className, id, maxLength } = this.props; + const { value, suggestions, disabled, placeholder, onKeyUp, autoFocus, className, id, maxLength, lang, spellCheck } = this.props; const { suggestionsHidden } = this.state; return ( @@ -210,6 +212,8 @@ export default class AutosuggestInput extends ImmutablePureComponent { id={id} className={className} maxLength={maxLength} + lang={lang} + spellCheck={spellCheck} /> </label> diff --git a/app/javascript/flavours/glitch/components/autosuggest_textarea.js b/app/javascript/flavours/glitch/components/autosuggest_textarea.jsx index 967c593af..a016e44b7 100644 --- a/app/javascript/flavours/glitch/components/autosuggest_textarea.js +++ b/app/javascript/flavours/glitch/components/autosuggest_textarea.jsx @@ -48,6 +48,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { onKeyDown: PropTypes.func, onPaste: PropTypes.func.isRequired, autoFocus: PropTypes.bool, + lang: PropTypes.string, }; static defaultProps = { @@ -74,7 +75,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { } this.props.onChange(e); - } + }; onKeyDown = (e) => { const { suggestions, disabled } = this.props; @@ -132,25 +133,25 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { } this.props.onKeyDown(e); - } + }; onBlur = () => { this.setState({ suggestionsHidden: true, focused: false }); - } + }; onFocus = (e) => { this.setState({ focused: true }); if (this.props.onFocus) { this.props.onFocus(e); } - } + }; onSuggestionClick = (e) => { const suggestion = this.props.suggestions.get(e.currentTarget.getAttribute('data-index')); e.preventDefault(); this.props.onSuggestionSelected(this.state.tokenStart, this.state.lastToken, suggestion); this.textarea.focus(); - } + }; componentWillReceiveProps (nextProps) { if (nextProps.suggestions !== this.props.suggestions && nextProps.suggestions.size > 0 && this.state.suggestionsHidden && this.state.focused) { @@ -160,14 +161,14 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { setTextarea = (c) => { this.textarea = c; - } + }; onPaste = (e) => { if (e.clipboardData && e.clipboardData.files.length === 1) { this.props.onPaste(e.clipboardData.files); e.preventDefault(); } - } + }; renderSuggestion = (suggestion, i) => { const { selectedSuggestion } = this.state; @@ -185,14 +186,14 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { } return ( - <div role='button' tabIndex='0' key={key} data-index={i} className={classNames('autosuggest-textarea__suggestions__item', { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}> + <div role='button' tabIndex={0} key={key} data-index={i} className={classNames('autosuggest-textarea__suggestions__item', { selected: i === selectedSuggestion })} onMouseDown={this.onSuggestionClick}> {inner} </div> ); - } + }; render () { - const { value, suggestions, disabled, placeholder, onKeyUp, autoFocus, children } = this.props; + const { value, suggestions, disabled, placeholder, onKeyUp, autoFocus, lang, children } = this.props; const { suggestionsHidden } = this.state; return [ @@ -216,6 +217,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { onPaste={this.onPaste} dir='auto' aria-autocomplete='list' + lang={lang} /> </label> </div> diff --git a/app/javascript/flavours/glitch/components/avatar.js b/app/javascript/flavours/glitch/components/avatar.jsx index 38fd99af5..f30b33e70 100644 --- a/app/javascript/flavours/glitch/components/avatar.js +++ b/app/javascript/flavours/glitch/components/avatar.jsx @@ -28,12 +28,12 @@ export default class Avatar extends React.PureComponent { handleMouseEnter = () => { if (this.props.animate) return; this.setState({ hovering: true }); - } + }; handleMouseLeave = () => { if (this.props.animate) return; this.setState({ hovering: false }); - } + }; render () { const { diff --git a/app/javascript/flavours/glitch/components/avatar_composite.js b/app/javascript/flavours/glitch/components/avatar_composite.jsx index c0ce7761d..c0ce7761d 100644 --- a/app/javascript/flavours/glitch/components/avatar_composite.js +++ b/app/javascript/flavours/glitch/components/avatar_composite.jsx diff --git a/app/javascript/flavours/glitch/components/avatar_overlay.js b/app/javascript/flavours/glitch/components/avatar_overlay.jsx index 01dec587a..01dec587a 100644 --- a/app/javascript/flavours/glitch/components/avatar_overlay.js +++ b/app/javascript/flavours/glitch/components/avatar_overlay.jsx diff --git a/app/javascript/flavours/glitch/components/blurhash.js b/app/javascript/flavours/glitch/components/blurhash.jsx index 2af5cfc56..2af5cfc56 100644 --- a/app/javascript/flavours/glitch/components/blurhash.js +++ b/app/javascript/flavours/glitch/components/blurhash.jsx diff --git a/app/javascript/flavours/glitch/components/button.js b/app/javascript/flavours/glitch/components/button.jsx index b1815c3e1..40b8f5a15 100644 --- a/app/javascript/flavours/glitch/components/button.js +++ b/app/javascript/flavours/glitch/components/button.jsx @@ -19,11 +19,11 @@ export default class Button extends React.PureComponent { if (!this.props.disabled) { this.props.onClick(e); } - } + }; setRef = (c) => { this.node = c; - } + }; focus() { this.node.focus(); diff --git a/app/javascript/flavours/glitch/components/check.js b/app/javascript/flavours/glitch/components/check.jsx index ee2ef1595..ee2ef1595 100644 --- a/app/javascript/flavours/glitch/components/check.js +++ b/app/javascript/flavours/glitch/components/check.jsx diff --git a/app/javascript/flavours/glitch/components/column.js b/app/javascript/flavours/glitch/components/column.jsx index cf0e6d5e4..47293ef18 100644 --- a/app/javascript/flavours/glitch/components/column.js +++ b/app/javascript/flavours/glitch/components/column.jsx @@ -29,11 +29,11 @@ export default class Column extends React.PureComponent { } this._interruptScrollAnimation(); - } + }; setRef = c => { this.node = c; - } + }; componentDidMount () { if (this.props.bindToDocument) { diff --git a/app/javascript/flavours/glitch/components/column_back_button.js b/app/javascript/flavours/glitch/components/column_back_button.jsx index 05688f867..e9e2615cb 100644 --- a/app/javascript/flavours/glitch/components/column_back_button.js +++ b/app/javascript/flavours/glitch/components/column_back_button.jsx @@ -26,7 +26,7 @@ export default class ColumnBackButton extends React.PureComponent { } else { this.context.router.history.push('/'); } - } + }; render () { const { multiColumn } = this.props; diff --git a/app/javascript/flavours/glitch/components/column_back_button_slim.js b/app/javascript/flavours/glitch/components/column_back_button_slim.jsx index faa0c23a8..4df045b5f 100644 --- a/app/javascript/flavours/glitch/components/column_back_button_slim.js +++ b/app/javascript/flavours/glitch/components/column_back_button_slim.jsx @@ -21,12 +21,12 @@ export default class ColumnBackButtonSlim extends React.PureComponent { } else { this.context.router.history.push('/'); } - } + }; render () { return ( <div className='column-back-button--slim'> - <div role='button' tabIndex='0' onClick={this.handleClick} className='column-back-button column-back-button--slim-button'> + <div role='button' tabIndex={0} onClick={this.handleClick} className='column-back-button column-back-button--slim-button'> <Icon id='chevron-left' className='column-back-button__icon' fixedWidth /> <FormattedMessage id='column_back_button.label' defaultMessage='Back' /> </div> diff --git a/app/javascript/flavours/glitch/components/column_header.js b/app/javascript/flavours/glitch/components/column_header.jsx index 0f89b3a97..6fbe2955d 100644 --- a/app/javascript/flavours/glitch/components/column_header.js +++ b/app/javascript/flavours/glitch/components/column_header.jsx @@ -12,7 +12,6 @@ const messages = defineMessages({ moveRight: { id: 'column_header.moveRight_settings', defaultMessage: 'Move column to the right' }, }); -export default @injectIntl class ColumnHeader extends React.PureComponent { static contextTypes = { @@ -55,39 +54,39 @@ class ColumnHeader extends React.PureComponent { } else { this.context.router.history.push('/'); } - } + }; handleToggleClick = (e) => { e.stopPropagation(); this.setState({ collapsed: !this.state.collapsed, animating: true }); - } + }; handleTitleClick = () => { this.props.onClick?.(); - } + }; handleMoveLeft = () => { this.props.onMove(-1); - } + }; handleMoveRight = () => { this.props.onMove(1); - } + }; handleBackClick = (event) => { this.historyBack(event.shiftKey); - } + }; handleTransitionEnd = () => { this.setState({ animating: false }); - } + }; handlePin = () => { if (!this.props.pinned) { this.historyBack(); } this.props.onPin(); - } + }; render () { const { title, icon, active, children, pinned, multiColumn, extraButton, showBackButton, intl: { formatMessage }, placeholder, appendContent, collapseIssues } = this.props; @@ -218,3 +217,5 @@ class ColumnHeader extends React.PureComponent { } } + +export default injectIntl(ColumnHeader); diff --git a/app/javascript/flavours/glitch/components/common_counter.js b/app/javascript/flavours/glitch/components/common_counter.jsx index dd9b62de9..dd9b62de9 100644 --- a/app/javascript/flavours/glitch/components/common_counter.js +++ b/app/javascript/flavours/glitch/components/common_counter.jsx diff --git a/app/javascript/flavours/glitch/components/dismissable_banner.js b/app/javascript/flavours/glitch/components/dismissable_banner.jsx index ff52a619d..9b3faf6f2 100644 --- a/app/javascript/flavours/glitch/components/dismissable_banner.js +++ b/app/javascript/flavours/glitch/components/dismissable_banner.jsx @@ -8,7 +8,6 @@ const messages = defineMessages({ dismiss: { id: 'dismissable_banner.dismiss', defaultMessage: 'Dismiss' }, }); -export default @injectIntl class DismissableBanner extends React.PureComponent { static propTypes = { @@ -24,7 +23,7 @@ class DismissableBanner extends React.PureComponent { handleDismiss = () => { const { id } = this.props; this.setState({ visible: false }, () => bannerSettings.set(id, true)); - } + }; render () { const { visible } = this.state; @@ -49,3 +48,5 @@ class DismissableBanner extends React.PureComponent { } } + +export default injectIntl(DismissableBanner); diff --git a/app/javascript/flavours/glitch/components/display_name.js b/app/javascript/flavours/glitch/components/display_name.jsx index 1c2297578..19f63ec60 100644 --- a/app/javascript/flavours/glitch/components/display_name.js +++ b/app/javascript/flavours/glitch/components/display_name.jsx @@ -27,7 +27,7 @@ export default class DisplayName extends React.PureComponent { let emoji = emojis[i]; emoji.src = emoji.getAttribute('data-original'); } - } + }; handleMouseLeave = ({ currentTarget }) => { if (autoPlayGif) { @@ -40,7 +40,7 @@ export default class DisplayName extends React.PureComponent { let emoji = emojis[i]; emoji.src = emoji.getAttribute('data-static'); } - } + }; render() { const { account, className, inline, localDomain, others, onAccountClick } = this.props; @@ -74,7 +74,7 @@ export default class DisplayName extends React.PureComponent { )).reduce((prev, cur) => [prev, ', ', cur]); if (others.size - 2 > 0) { - displayName.push(` +${others.size - 2}`); + displayName.push(` +${others.size - 2}`); } suffix = ( diff --git a/app/javascript/flavours/glitch/components/domain.js b/app/javascript/flavours/glitch/components/domain.jsx index 697065d87..85ebdbde9 100644 --- a/app/javascript/flavours/glitch/components/domain.js +++ b/app/javascript/flavours/glitch/components/domain.jsx @@ -8,7 +8,6 @@ const messages = defineMessages({ unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' }, }); -export default @injectIntl class Account extends ImmutablePureComponent { static propTypes = { @@ -19,7 +18,7 @@ class Account extends ImmutablePureComponent { handleDomainUnblock = () => { this.props.onUnblockDomain(this.props.domain); - } + }; render () { const { domain, intl } = this.props; @@ -40,3 +39,5 @@ class Account extends ImmutablePureComponent { } } + +export default injectIntl(Account); diff --git a/app/javascript/flavours/glitch/components/dropdown_menu.js b/app/javascript/flavours/glitch/components/dropdown_menu.jsx index 7c70f750f..7fb75b59e 100644 --- a/app/javascript/flavours/glitch/components/dropdown_menu.js +++ b/app/javascript/flavours/glitch/components/dropdown_menu.jsx @@ -36,7 +36,7 @@ class DropdownMenu extends React.PureComponent { if (this.node && !this.node.contains(e.target)) { this.props.onClose(); } - } + }; componentDidMount () { document.addEventListener('click', this.handleDocumentClick, false); @@ -56,11 +56,11 @@ class DropdownMenu extends React.PureComponent { setRef = c => { this.node = c; - } + }; setFocusRef = c => { this.focusedItem = c; - } + }; handleKeyDown = e => { const items = Array.from(this.node.querySelectorAll('a, button')); @@ -97,18 +97,18 @@ class DropdownMenu extends React.PureComponent { e.preventDefault(); e.stopPropagation(); } - } + }; handleItemKeyPress = e => { if (e.key === 'Enter' || e.key === ' ') { this.handleClick(e); } - } + }; handleClick = e => { const { onItemClick } = this.props; onItemClick(e); - } + }; renderItem = (option, i) => { if (option === null) { @@ -119,12 +119,12 @@ class DropdownMenu extends React.PureComponent { return ( <li className='dropdown-menu__item' key={`${text}-${i}`}> - <a href={href} target={target} data-method={method} rel='noopener noreferrer' role='button' tabIndex='0' ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}> + <a href={href} target={target} data-method={method} rel='noopener noreferrer' role='button' tabIndex={0} ref={i === 0 ? this.setFocusRef : null} onClick={this.handleClick} onKeyPress={this.handleItemKeyPress} data-index={i}> {text} </a> </li> ); - } + }; render () { const { items, scrollable, renderHeader, loading } = this.props; @@ -194,7 +194,7 @@ export default class Dropdown extends React.PureComponent { } else { this.props.onOpen(this.state.id, this.handleItemClick, type !== 'click'); } - } + }; handleClose = () => { if (this.activeElement) { @@ -202,13 +202,13 @@ export default class Dropdown extends React.PureComponent { this.activeElement = null; } this.props.onClose(this.state.id); - } + }; handleMouseDown = () => { if (!this.state.open) { this.activeElement = document.activeElement; } - } + }; handleButtonKeyDown = (e) => { switch(e.key) { @@ -217,7 +217,7 @@ export default class Dropdown extends React.PureComponent { this.handleMouseDown(); break; } - } + }; handleKeyPress = (e) => { switch(e.key) { @@ -228,7 +228,7 @@ export default class Dropdown extends React.PureComponent { e.preventDefault(); break; } - } + }; handleItemClick = e => { const { onItemClick } = this.props; @@ -247,25 +247,25 @@ export default class Dropdown extends React.PureComponent { e.preventDefault(); this.context.router.history.push(item.to); } - } + }; setTargetRef = c => { this.target = c; - } + }; findTarget = () => { return this.target; - } + }; componentWillUnmount = () => { if (this.state.id === this.props.openDropdownId) { this.handleClose(); } - } + }; close = () => { this.handleClose(); - } + }; render () { const { diff --git a/app/javascript/flavours/glitch/components/edited_timestamp/index.js b/app/javascript/flavours/glitch/components/edited_timestamp/index.jsx index 9648133af..6d73fa68c 100644 --- a/app/javascript/flavours/glitch/components/edited_timestamp/index.js +++ b/app/javascript/flavours/glitch/components/edited_timestamp/index.jsx @@ -16,8 +16,6 @@ const mapDispatchToProps = (dispatch, { statusId }) => ({ }); -export default @connect(null, mapDispatchToProps) -@injectIntl class EditedTimestamp extends React.PureComponent { static propTypes = { @@ -36,7 +34,7 @@ class EditedTimestamp extends React.PureComponent { return ( <FormattedMessage id='status.edited_x_times' defaultMessage='Edited {count, plural, one {{count} time} other {{count} times}}' values={{ count: items.size - 1 }} /> ); - } + }; renderItem = (item, index, { onClick, onKeyPress }) => { const formattedDate = <RelativeTimestamp timestamp={item.get('created_at')} short={false} />; @@ -53,7 +51,7 @@ class EditedTimestamp extends React.PureComponent { <button data-index={index} onClick={onClick} onKeyPress={onKeyPress}>{label}</button> </li> ); - } + }; render () { const { timestamp, intl, statusId } = this.props; @@ -68,3 +66,5 @@ class EditedTimestamp extends React.PureComponent { } } + +export default connect(null, mapDispatchToProps)(injectIntl(EditedTimestamp)); diff --git a/app/javascript/flavours/glitch/components/error_boundary.js b/app/javascript/flavours/glitch/components/error_boundary.jsx index e0ca3e2b0..234a53417 100644 --- a/app/javascript/flavours/glitch/components/error_boundary.js +++ b/app/javascript/flavours/glitch/components/error_boundary.jsx @@ -18,7 +18,7 @@ export default class ErrorBoundary extends React.PureComponent { stackTrace: undefined, mappedStackTrace: undefined, componentStack: undefined, - } + }; componentDidCatch(error, info) { this.setState({ @@ -72,7 +72,7 @@ export default class ErrorBoundary extends React.PureComponent { } return ( - <div tabIndex='-1'> + <div tabIndex={-1}> <div className='error-boundary'> <h1><FormattedMessage id='web_app_crash.title' defaultMessage="We're sorry, but something went wrong with the Mastodon app." /></h1> <p> diff --git a/app/javascript/flavours/glitch/components/gifv.js b/app/javascript/flavours/glitch/components/gifv.jsx index b775e5200..1ce7e7c29 100644 --- a/app/javascript/flavours/glitch/components/gifv.js +++ b/app/javascript/flavours/glitch/components/gifv.jsx @@ -6,6 +6,7 @@ export default class GIFV extends React.PureComponent { static propTypes = { src: PropTypes.string.isRequired, alt: PropTypes.string, + lang: PropTypes.string, width: PropTypes.number, height: PropTypes.number, onClick: PropTypes.func, @@ -17,7 +18,7 @@ export default class GIFV extends React.PureComponent { handleLoadedData = () => { this.setState({ loading: false }); - } + }; componentWillReceiveProps (nextProps) { if (nextProps.src !== this.props.src) { @@ -32,10 +33,10 @@ export default class GIFV extends React.PureComponent { e.stopPropagation(); onClick(); } - } + }; render () { - const { src, width, height, alt } = this.props; + const { src, width, height, alt, lang } = this.props; const { loading } = this.state; return ( @@ -45,9 +46,10 @@ export default class GIFV extends React.PureComponent { width={width} height={height} role='button' - tabIndex='0' + tabIndex={0} aria-label={alt} title={alt} + lang={lang} onClick={this.handleClick} /> )} @@ -55,9 +57,10 @@ export default class GIFV extends React.PureComponent { <video src={src} role='button' - tabIndex='0' + tabIndex={0} aria-label={alt} title={alt} + lang={lang} muted loop autoPlay diff --git a/app/javascript/flavours/glitch/components/hashtag.js b/app/javascript/flavours/glitch/components/hashtag.jsx index 422b9a8fa..422b9a8fa 100644 --- a/app/javascript/flavours/glitch/components/hashtag.js +++ b/app/javascript/flavours/glitch/components/hashtag.jsx diff --git a/app/javascript/flavours/glitch/components/icon.js b/app/javascript/flavours/glitch/components/icon.jsx index d8a17722f..d8a17722f 100644 --- a/app/javascript/flavours/glitch/components/icon.js +++ b/app/javascript/flavours/glitch/components/icon.jsx diff --git a/app/javascript/flavours/glitch/components/icon_button.js b/app/javascript/flavours/glitch/components/icon_button.jsx index 2485f0f48..10d7926be 100644 --- a/app/javascript/flavours/glitch/components/icon_button.js +++ b/app/javascript/flavours/glitch/components/icon_button.jsx @@ -46,7 +46,7 @@ export default class IconButton extends React.PureComponent { state = { activate: false, deactivate: false, - } + }; componentWillReceiveProps (nextProps) { if (!nextProps.animate) return; @@ -64,25 +64,25 @@ export default class IconButton extends React.PureComponent { if (!this.props.disabled) { this.props.onClick(e); } - } + }; handleKeyPress = (e) => { if (this.props.onKeyPress && !this.props.disabled) { this.props.onKeyPress(e); } - } + }; handleMouseDown = (e) => { if (!this.props.disabled && this.props.onMouseDown) { this.props.onMouseDown(e); } - } + }; handleKeyDown = (e) => { if (!this.props.disabled && this.props.onKeyDown) { this.props.onKeyDown(e); } - } + }; render () { // Hack required for some icons which have an overriden size diff --git a/app/javascript/flavours/glitch/components/icon_with_badge.js b/app/javascript/flavours/glitch/components/icon_with_badge.jsx index a42ba4589..a42ba4589 100644 --- a/app/javascript/flavours/glitch/components/icon_with_badge.js +++ b/app/javascript/flavours/glitch/components/icon_with_badge.jsx diff --git a/app/javascript/flavours/glitch/components/image.js b/app/javascript/flavours/glitch/components/image.jsx index 6e81ddf08..6e81ddf08 100644 --- a/app/javascript/flavours/glitch/components/image.js +++ b/app/javascript/flavours/glitch/components/image.jsx diff --git a/app/javascript/flavours/glitch/components/inline_account.js b/app/javascript/flavours/glitch/components/inline_account.jsx index 2ef1f52cc..c04618d66 100644 --- a/app/javascript/flavours/glitch/components/inline_account.js +++ b/app/javascript/flavours/glitch/components/inline_account.jsx @@ -14,7 +14,6 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export default @connect(makeMapStateToProps) class InlineAccount extends React.PureComponent { static propTypes = { @@ -32,3 +31,5 @@ class InlineAccount extends React.PureComponent { } } + +export default connect(makeMapStateToProps)(InlineAccount); diff --git a/app/javascript/flavours/glitch/components/intersection_observer_article.js b/app/javascript/flavours/glitch/components/intersection_observer_article.jsx index b28e44e4c..6c00e557d 100644 --- a/app/javascript/flavours/glitch/components/intersection_observer_article.js +++ b/app/javascript/flavours/glitch/components/intersection_observer_article.jsx @@ -21,7 +21,7 @@ export default class IntersectionObserverArticle extends React.Component { state = { isHidden: false, // set to true in requestIdleCallback to trigger un-render - } + }; shouldComponentUpdate (nextProps, nextState) { const isUnrendered = !this.state.isIntersecting && (this.state.isHidden || this.props.cachedHeight); @@ -63,7 +63,7 @@ export default class IntersectionObserverArticle extends React.Component { scheduleIdleTask(this.calculateHeight); this.setState(this.updateStateAfterIntersection); - } + }; updateStateAfterIntersection = (prevState) => { if (prevState.isIntersecting !== false && !this.entry.isIntersecting) { @@ -73,7 +73,7 @@ export default class IntersectionObserverArticle extends React.Component { isIntersecting: this.entry.isIntersecting, isHidden: false, }; - } + }; calculateHeight = () => { const { onHeightChange, saveHeightKey, id } = this.props; @@ -84,7 +84,7 @@ export default class IntersectionObserverArticle extends React.Component { if (onHeightChange && saveHeightKey) { onHeightChange(saveHeightKey, id, this.height); } - } + }; hideIfNotIntersecting = () => { if (!this.componentMounted) { @@ -96,11 +96,11 @@ export default class IntersectionObserverArticle extends React.Component { // this is to save DOM nodes and avoid using up too much memory. // See: https://github.com/mastodon/mastodon/issues/2900 this.setState((prevState) => ({ isHidden: !prevState.isIntersecting })); - } + }; handleRef = (node) => { this.node = node; - } + }; render () { const { children, id, index, listLength, cachedHeight } = this.props; @@ -120,9 +120,10 @@ export default class IntersectionObserverArticle extends React.Component { aria-posinset={index + 1} aria-setsize={listLength} data-id={id} - tabIndex='0' - style={style}> - {children && React.cloneElement(children, { hidden: !isIntersecting && (isHidden || !!cachedHeight) })} + tabIndex={0} + style={style} + > + {children && React.cloneElement(children, { hidden: !isIntersecting && (isHidden || !!cachedHeight) })} </article> ); } diff --git a/app/javascript/flavours/glitch/components/link.js b/app/javascript/flavours/glitch/components/link.jsx index bbec121a8..bbec121a8 100644 --- a/app/javascript/flavours/glitch/components/link.js +++ b/app/javascript/flavours/glitch/components/link.jsx diff --git a/app/javascript/flavours/glitch/components/load_gap.js b/app/javascript/flavours/glitch/components/load_gap.jsx index fe3f60a58..e70365d9e 100644 --- a/app/javascript/flavours/glitch/components/load_gap.js +++ b/app/javascript/flavours/glitch/components/load_gap.jsx @@ -7,7 +7,6 @@ const messages = defineMessages({ load_more: { id: 'status.load_more', defaultMessage: 'Load more' }, }); -export default @injectIntl class LoadGap extends React.PureComponent { static propTypes = { @@ -19,7 +18,7 @@ class LoadGap extends React.PureComponent { handleClick = () => { this.props.onClick(this.props.maxId); - } + }; render () { const { disabled, intl } = this.props; @@ -32,3 +31,5 @@ class LoadGap extends React.PureComponent { } } + +export default injectIntl(LoadGap); diff --git a/app/javascript/flavours/glitch/components/load_more.js b/app/javascript/flavours/glitch/components/load_more.jsx index 389c3e1e1..ab9428e35 100644 --- a/app/javascript/flavours/glitch/components/load_more.js +++ b/app/javascript/flavours/glitch/components/load_more.jsx @@ -8,11 +8,11 @@ export default class LoadMore extends React.PureComponent { onClick: PropTypes.func, disabled: PropTypes.bool, visible: PropTypes.bool, - } + }; static defaultProps = { visible: true, - } + }; render() { const { disabled, visible } = this.props; diff --git a/app/javascript/flavours/glitch/components/load_pending.js b/app/javascript/flavours/glitch/components/load_pending.jsx index 7e2702403..a75259146 100644 --- a/app/javascript/flavours/glitch/components/load_pending.js +++ b/app/javascript/flavours/glitch/components/load_pending.jsx @@ -7,7 +7,7 @@ export default class LoadPending extends React.PureComponent { static propTypes = { onClick: PropTypes.func, count: PropTypes.number, - } + }; render() { const { count } = this.props; diff --git a/app/javascript/flavours/glitch/components/loading_indicator.js b/app/javascript/flavours/glitch/components/loading_indicator.jsx index 59f721c50..59f721c50 100644 --- a/app/javascript/flavours/glitch/components/loading_indicator.js +++ b/app/javascript/flavours/glitch/components/loading_indicator.jsx diff --git a/app/javascript/flavours/glitch/components/logo.js b/app/javascript/flavours/glitch/components/logo.jsx index ee5c22496..ee5c22496 100644 --- a/app/javascript/flavours/glitch/components/logo.js +++ b/app/javascript/flavours/glitch/components/logo.jsx diff --git a/app/javascript/flavours/glitch/components/media_attachments.js b/app/javascript/flavours/glitch/components/media_attachments.jsx index a517fcf30..b11d3526f 100644 --- a/app/javascript/flavours/glitch/components/media_attachments.js +++ b/app/javascript/flavours/glitch/components/media_attachments.jsx @@ -10,6 +10,7 @@ export default class MediaAttachments extends ImmutablePureComponent { static propTypes = { status: ImmutablePropTypes.map.isRequired, + lang: PropTypes.string, height: PropTypes.number, width: PropTypes.number, revealed: PropTypes.bool, @@ -30,7 +31,7 @@ export default class MediaAttachments extends ImmutablePureComponent { return ( <div className='media-gallery' style={{ height, width }} /> ); - } + }; renderLoadingVideoPlayer = () => { const { height, width } = this.props; @@ -38,7 +39,7 @@ export default class MediaAttachments extends ImmutablePureComponent { return ( <div className='video-player' style={{ height, width }} /> ); - } + }; renderLoadingAudioPlayer = () => { const { height, width } = this.props; @@ -46,10 +47,10 @@ export default class MediaAttachments extends ImmutablePureComponent { return ( <div className='audio-player' style={{ height, width }} /> ); - } + }; render () { - const { status, width, height, revealed } = this.props; + const { status, lang, width, height, revealed } = this.props; const mediaAttachments = status.get('media_attachments'); if (mediaAttachments.size === 0) { @@ -65,6 +66,7 @@ export default class MediaAttachments extends ImmutablePureComponent { <Component src={audio.get('url')} alt={audio.get('description')} + lang={lang || status.get('language')} width={width} height={height} poster={audio.get('preview_url') || status.getIn(['account', 'avatar_static'])} @@ -88,6 +90,7 @@ export default class MediaAttachments extends ImmutablePureComponent { blurhash={video.get('blurhash')} src={video.get('url')} alt={video.get('description')} + lang={lang || status.get('language')} width={width} height={height} inline @@ -104,6 +107,7 @@ export default class MediaAttachments extends ImmutablePureComponent { {Component => ( <Component media={mediaAttachments} + lang={lang || status.get('language')} sensitive={status.get('sensitive')} defaultWidth={width} revealed={revealed} diff --git a/app/javascript/flavours/glitch/components/media_gallery.js b/app/javascript/flavours/glitch/components/media_gallery.jsx index 23e279589..b38f732f1 100644 --- a/app/javascript/flavours/glitch/components/media_gallery.js +++ b/app/javascript/flavours/glitch/components/media_gallery.jsx @@ -36,6 +36,7 @@ class Item extends React.PureComponent { static propTypes = { attachment: ImmutablePropTypes.map.isRequired, + lang: PropTypes.string, standalone: PropTypes.bool, index: PropTypes.number.isRequired, size: PropTypes.number.isRequired, @@ -60,14 +61,14 @@ class Item extends React.PureComponent { if (this.hoverToPlay()) { e.target.play(); } - } + }; handleMouseLeave = (e) => { if (this.hoverToPlay()) { e.target.pause(); e.target.currentTime = 0; } - } + }; getAutoPlay() { return this.props.autoplay || autoPlayGif; @@ -91,14 +92,14 @@ class Item extends React.PureComponent { } e.stopPropagation(); - } + }; handleImageLoad = () => { this.setState({ loaded: true }); - } + }; render () { - const { attachment, index, size, standalone, letterbox, displayWidth, visible } = this.props; + const { attachment, lang, index, size, standalone, letterbox, displayWidth, visible } = this.props; let width = 50; let height = 100; @@ -154,7 +155,7 @@ class Item extends React.PureComponent { if (attachment.get('type') === 'unknown') { return ( <div className={classNames('media-gallery__item', { standalone })} key={attachment.get('id')} style={{ left: left, top: top, right: right, bottom: bottom, width: `${width}%`, height: `${height}%` }}> - <a className='media-gallery__item-thumbnail' href={attachment.get('remote_url') || attachment.get('url')} style={{ cursor: 'pointer' }} title={attachment.get('description')} target='_blank' rel='noopener noreferrer'> + <a className='media-gallery__item-thumbnail' href={attachment.get('remote_url') || attachment.get('url')} style={{ cursor: 'pointer' }} title={attachment.get('description')} lang={lang} target='_blank' rel='noopener noreferrer'> <Blurhash hash={attachment.get('blurhash')} className='media-gallery__preview' @@ -195,6 +196,7 @@ class Item extends React.PureComponent { sizes={sizes} alt={attachment.get('description')} title={attachment.get('description')} + lang={lang} style={{ objectPosition: letterbox ? null : `${x}% ${y}%` }} onLoad={this.handleImageLoad} /> @@ -209,6 +211,7 @@ class Item extends React.PureComponent { className={`media-gallery__item-gifv-thumbnail${letterbox ? ' letterbox' : ''}`} aria-label={attachment.get('description')} title={attachment.get('description')} + lang={lang} role='application' src={attachment.get('url')} onClick={this.handleClick} @@ -241,7 +244,6 @@ class Item extends React.PureComponent { } -export default @injectIntl class MediaGallery extends React.PureComponent { static propTypes = { @@ -251,6 +253,7 @@ class MediaGallery extends React.PureComponent { fullwidth: PropTypes.bool, hidden: PropTypes.bool, media: ImmutablePropTypes.list.isRequired, + lang: PropTypes.string, size: PropTypes.object, onOpenMedia: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, @@ -307,11 +310,11 @@ class MediaGallery extends React.PureComponent { } else { this.setState({ visible: !this.state.visible }); } - } + }; handleClick = (index) => { this.props.onOpenMedia(this.props.media, index); - } + }; handleRef = (node) => { this.node = node; @@ -319,11 +322,11 @@ class MediaGallery extends React.PureComponent { if (this.node) { this._setDimensions(); } - } + }; _setDimensions () { const width = this.node.offsetWidth; - + if (width && width != this.state.width) { // offsetWidth triggers a layout, so only calculate when we need to if (this.props.cacheWidth) { @@ -342,7 +345,7 @@ class MediaGallery extends React.PureComponent { } render () { - const { media, intl, sensitive, letterbox, fullwidth, defaultWidth, autoplay } = this.props; + const { media, lang, intl, sensitive, letterbox, fullwidth, defaultWidth, autoplay } = this.props; const { visible } = this.state; const size = media.take(4).size; const uncached = media.every(attachment => attachment.get('type') === 'unknown'); @@ -360,13 +363,13 @@ class MediaGallery extends React.PureComponent { } else if (width) { style.height = width / (16/9); } else { - return (<div className={computedClass} ref={this.handleRef}></div>); + return (<div className={computedClass} ref={this.handleRef} />); } if (this.isStandaloneEligible()) { - children = <Item standalone autoplay={autoplay} onClick={this.handleClick} attachment={media.get(0)} displayWidth={width} visible={visible} />; + children = <Item standalone autoplay={autoplay} onClick={this.handleClick} attachment={media.get(0)} lang={lang} displayWidth={width} visible={visible} />; } else { - children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} autoplay={autoplay} onClick={this.handleClick} attachment={attachment} index={i} size={size} letterbox={letterbox} displayWidth={width} visible={visible || uncached} />); + children = media.take(4).map((attachment, i) => <Item key={attachment.get('id')} autoplay={autoplay} onClick={this.handleClick} attachment={attachment} index={i} lang={lang} size={size} letterbox={letterbox} displayWidth={width} visible={visible || uncached} />); } if (uncached) { @@ -402,3 +405,5 @@ class MediaGallery extends React.PureComponent { } } + +export default injectIntl(MediaGallery); diff --git a/app/javascript/flavours/glitch/components/missing_indicator.js b/app/javascript/flavours/glitch/components/missing_indicator.jsx index 08e39c236..08e39c236 100644 --- a/app/javascript/flavours/glitch/components/missing_indicator.js +++ b/app/javascript/flavours/glitch/components/missing_indicator.jsx diff --git a/app/javascript/flavours/glitch/components/modal_root.js b/app/javascript/flavours/glitch/components/modal_root.jsx index 056277447..5a5563e87 100644 --- a/app/javascript/flavours/glitch/components/modal_root.js +++ b/app/javascript/flavours/glitch/components/modal_root.jsx @@ -5,6 +5,7 @@ import { createBrowserHistory } from 'history'; import { multiply } from 'color-blend'; export default class ModalRoot extends React.PureComponent { + static contextTypes = { router: PropTypes.object, }; @@ -28,7 +29,7 @@ export default class ModalRoot extends React.PureComponent { && !!this.props.children && !this.props.noEsc) { this.props.onClose(); } - } + }; handleKeyDown = (e) => { if (e.key === 'Tab') { @@ -49,7 +50,7 @@ export default class ModalRoot extends React.PureComponent { e.preventDefault(); } } - } + }; componentDidMount () { window.addEventListener('keyup', this.handleKeyUp, false); @@ -125,11 +126,11 @@ export default class ModalRoot extends React.PureComponent { getSiblings = () => { return Array(...this.node.parentElement.childNodes).filter(node => node !== this.node); - } + }; setRef = ref => { this.node = ref; - } + }; render () { const { children, onClose } = this.props; diff --git a/app/javascript/flavours/glitch/components/navigation_portal.js b/app/javascript/flavours/glitch/components/navigation_portal.jsx index 90afa1da0..9e8494179 100644 --- a/app/javascript/flavours/glitch/components/navigation_portal.js +++ b/app/javascript/flavours/glitch/components/navigation_portal.jsx @@ -15,7 +15,6 @@ const DefaultNavigation = () => ( </> ); -export default @withRouter class NavigationPortal extends React.PureComponent { render () { @@ -33,3 +32,5 @@ class NavigationPortal extends React.PureComponent { } } + +export default withRouter(NavigationPortal); diff --git a/app/javascript/flavours/glitch/components/not_signed_in_indicator.js b/app/javascript/flavours/glitch/components/not_signed_in_indicator.jsx index b440c6be2..b440c6be2 100644 --- a/app/javascript/flavours/glitch/components/not_signed_in_indicator.js +++ b/app/javascript/flavours/glitch/components/not_signed_in_indicator.jsx diff --git a/app/javascript/flavours/glitch/components/notification_purge_buttons.js b/app/javascript/flavours/glitch/components/notification_purge_buttons.jsx index 3c7d67109..1d807bc23 100644 --- a/app/javascript/flavours/glitch/components/notification_purge_buttons.js +++ b/app/javascript/flavours/glitch/components/notification_purge_buttons.jsx @@ -19,7 +19,6 @@ const messages = defineMessages({ btnApply : { id: 'notification_purge.btn_apply', defaultMessage: 'Clear\nselected' }, }); -export default @injectIntl class NotificationPurgeButtons extends ImmutablePureComponent { static propTypes = { @@ -57,3 +56,5 @@ class NotificationPurgeButtons extends ImmutablePureComponent { } } + +export default injectIntl(NotificationPurgeButtons); diff --git a/app/javascript/flavours/glitch/components/permalink.js b/app/javascript/flavours/glitch/components/permalink.jsx index 718b02115..b09b17eeb 100644 --- a/app/javascript/flavours/glitch/components/permalink.js +++ b/app/javascript/flavours/glitch/components/permalink.jsx @@ -24,12 +24,12 @@ export default class Permalink extends React.PureComponent { if (this.context.router) { e.preventDefault(); - let state = {...this.context.router.history.location.state}; + let state = { ...this.context.router.history.location.state }; state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1; this.context.router.history.push(this.props.to, state); } } - } + }; render () { const { diff --git a/app/javascript/flavours/glitch/components/picture_in_picture_placeholder.js b/app/javascript/flavours/glitch/components/picture_in_picture_placeholder.jsx index 01dce0a38..9d1b7f55a 100644 --- a/app/javascript/flavours/glitch/components/picture_in_picture_placeholder.js +++ b/app/javascript/flavours/glitch/components/picture_in_picture_placeholder.jsx @@ -6,7 +6,6 @@ import { connect } from 'react-redux'; import { debounce } from 'lodash'; import { FormattedMessage } from 'react-intl'; -export default @connect() class PictureInPicturePlaceholder extends React.PureComponent { static propTypes = { @@ -22,7 +21,7 @@ class PictureInPicturePlaceholder extends React.PureComponent { handleClick = () => { const { dispatch } = this.props; dispatch(removePictureInPicture()); - } + }; setRef = c => { this.node = c; @@ -30,7 +29,7 @@ class PictureInPicturePlaceholder extends React.PureComponent { if (this.node) { this._setDimensions(); } - } + }; _setDimensions () { const width = this.node.offsetWidth; @@ -59,7 +58,7 @@ class PictureInPicturePlaceholder extends React.PureComponent { const { height } = this.state; return ( - <div ref={this.setRef} className='picture-in-picture-placeholder' style={{ height }} role='button' tabIndex='0' onClick={this.handleClick}> + <div ref={this.setRef} className='picture-in-picture-placeholder' style={{ height }} role='button' tabIndex={0} onClick={this.handleClick}> <Icon id='window-restore' /> <FormattedMessage id='picture_in_picture.restore' defaultMessage='Put it back' /> </div> @@ -67,3 +66,5 @@ class PictureInPicturePlaceholder extends React.PureComponent { } } + +export default connect()(PictureInPicturePlaceholder); diff --git a/app/javascript/flavours/glitch/components/poll.js b/app/javascript/flavours/glitch/components/poll.jsx index da65cd241..fb37612d9 100644 --- a/app/javascript/flavours/glitch/components/poll.js +++ b/app/javascript/flavours/glitch/components/poll.jsx @@ -31,7 +31,6 @@ const makeEmojiMap = record => record.get('emojis').reduce((obj, emoji) => { return obj; }, {}); -export default @injectIntl class Poll extends ImmutablePureComponent { static contextTypes = { @@ -40,6 +39,7 @@ class Poll extends ImmutablePureComponent { static propTypes = { poll: ImmutablePropTypes.map, + lang: PropTypes.string, intl: PropTypes.object.isRequired, disabled: PropTypes.bool, refresh: PropTypes.func, @@ -95,7 +95,7 @@ class Poll extends ImmutablePureComponent { tmp[value] = true; this.setState({ selected: tmp }); } - } + }; handleOptionChange = ({ target: { value } }) => { this._toggleOption(value); @@ -107,7 +107,7 @@ class Poll extends ImmutablePureComponent { e.stopPropagation(); e.preventDefault(); } - } + }; handleVote = () => { if (this.props.disabled) { @@ -126,7 +126,7 @@ class Poll extends ImmutablePureComponent { }; renderOption (option, optionIndex, showResults) { - const { poll, disabled, intl } = this.props; + const { poll, lang, disabled, intl } = this.props; const pollVotesCount = poll.get('voters_count') || poll.get('votes_count'); const percent = pollVotesCount === 0 ? 0 : (option.get('votes_count') / pollVotesCount) * 100; const leading = poll.get('options').filterNot(other => other.get('title') === option.get('title')).every(other => option.get('votes_count') >= other.get('votes_count')); @@ -154,11 +154,12 @@ class Poll extends ImmutablePureComponent { {!showResults && ( <span className={classNames('poll__input', { checkbox: poll.get('multiple'), active })} - tabIndex='0' + tabIndex={0} role={poll.get('multiple') ? 'checkbox' : 'radio'} onKeyPress={this.handleOptionKeyPress} aria-checked={active} aria-label={option.get('title')} + lang={lang} data-index={optionIndex} /> )} @@ -175,6 +176,7 @@ class Poll extends ImmutablePureComponent { <span className='poll__option__text translate' + lang={lang} dangerouslySetInnerHTML={{ __html: titleEmojified }} /> @@ -231,3 +233,5 @@ class Poll extends ImmutablePureComponent { } } + +export default injectIntl(Poll); diff --git a/app/javascript/flavours/glitch/components/radio_button.js b/app/javascript/flavours/glitch/components/radio_button.jsx index 0496fa286..0496fa286 100644 --- a/app/javascript/flavours/glitch/components/radio_button.js +++ b/app/javascript/flavours/glitch/components/radio_button.jsx diff --git a/app/javascript/flavours/glitch/components/regeneration_indicator.js b/app/javascript/flavours/glitch/components/regeneration_indicator.jsx index 68ce09df9..68ce09df9 100644 --- a/app/javascript/flavours/glitch/components/regeneration_indicator.js +++ b/app/javascript/flavours/glitch/components/regeneration_indicator.jsx diff --git a/app/javascript/flavours/glitch/components/relative_timestamp.js b/app/javascript/flavours/glitch/components/relative_timestamp.jsx index 512480339..e6c3e0880 100644 --- a/app/javascript/flavours/glitch/components/relative_timestamp.js +++ b/app/javascript/flavours/glitch/components/relative_timestamp.jsx @@ -121,7 +121,6 @@ const timeRemainingString = (intl, date, now, timeGiven = true) => { return relativeTime; }; -export default @injectIntl class RelativeTimestamp extends React.Component { static propTypes = { @@ -197,3 +196,5 @@ class RelativeTimestamp extends React.Component { } } + +export default injectIntl(RelativeTimestamp); diff --git a/app/javascript/flavours/glitch/components/scrollable_list.js b/app/javascript/flavours/glitch/components/scrollable_list.jsx index 8eb2b66d4..fc7dc989d 100644 --- a/app/javascript/flavours/glitch/components/scrollable_list.js +++ b/app/javascript/flavours/glitch/components/scrollable_list.jsx @@ -20,7 +20,6 @@ const mapStateToProps = (state, { scrollKey }) => { }; }; -export default @connect(mapStateToProps, null, null, { forwardRef: true }) class ScrollableList extends PureComponent { static contextTypes = { @@ -137,7 +136,7 @@ class ScrollableList extends PureComponent { } this.mouseMovedRecently = false; this.scrollToTopOnMouseIdle = false; - } + }; componentDidMount () { this.attachScrollListener(); @@ -154,29 +153,29 @@ class ScrollableList extends PureComponent { } else { return null; } - } + }; getScrollTop = () => { return this.props.bindToDocument ? document.scrollingElement.scrollTop : this.node.scrollTop; - } + }; getScrollHeight = () => { return this.props.bindToDocument ? document.scrollingElement.scrollHeight : this.node.scrollHeight; - } + }; getClientHeight = () => { return this.props.bindToDocument ? document.scrollingElement.clientHeight : this.node.clientHeight; - } + }; updateScrollBottom = (snapshot) => { const newScrollTop = this.getScrollHeight() - snapshot; this.setScrollTop(newScrollTop); - } + }; cacheMediaWidth = (width) => { if (width && this.state.cachedMediaWidth != width) this.setState({ cachedMediaWidth: width }); - } + }; getSnapshotBeforeUpdate (prevProps, prevState) { const someItemInserted = React.Children.count(prevProps.children) > 0 && @@ -208,7 +207,7 @@ class ScrollableList extends PureComponent { onFullScreenChange = () => { this.setState({ fullscreen: isFullscreen() }); - } + }; attachIntersectionObserver () { this.intersectionObserverWrapper.connect({ @@ -256,12 +255,12 @@ class ScrollableList extends PureComponent { setRef = (c) => { this.node = c; - } + }; handleLoadMore = e => { e.preventDefault(); this.props.onLoadMore(); - } + }; handleLoadPending = e => { e.preventDefault(); @@ -273,7 +272,7 @@ class ScrollableList extends PureComponent { this.clearMouseIdleTimer(); this.mouseIdleTimer = setTimeout(this.handleMouseIdle, MOUSE_IDLE_DELAY); this.mouseMovedRecently = true; - } + }; render () { const { children, scrollKey, trackScroll, showLoading, isLoading, hasMore, numPending, prepend, alwaysPrepend, append, emptyMessage, onLoadMore } = this.props; @@ -352,3 +351,5 @@ class ScrollableList extends PureComponent { } } + +export default connect(mapStateToProps, null, null, { forwardRef: true })(ScrollableList); diff --git a/app/javascript/flavours/glitch/components/server_banner.js b/app/javascript/flavours/glitch/components/server_banner.jsx index 36e0ff238..ba84064a8 100644 --- a/app/javascript/flavours/glitch/components/server_banner.js +++ b/app/javascript/flavours/glitch/components/server_banner.jsx @@ -18,8 +18,6 @@ const mapStateToProps = state => ({ server: state.getIn(['server', 'server']), }); -export default @connect(mapStateToProps) -@injectIntl class ServerBanner extends React.PureComponent { static propTypes = { @@ -91,3 +89,5 @@ class ServerBanner extends React.PureComponent { } } + +export default connect(mapStateToProps)(injectIntl(ServerBanner)); diff --git a/app/javascript/flavours/glitch/components/setting_text.js b/app/javascript/flavours/glitch/components/setting_text.jsx index 2c1b70bc3..3a21a0601 100644 --- a/app/javascript/flavours/glitch/components/setting_text.js +++ b/app/javascript/flavours/glitch/components/setting_text.jsx @@ -13,7 +13,7 @@ export default class SettingText extends React.PureComponent { handleChange = (e) => { this.props.onChange(this.props.settingPath, e.target.value); - } + }; render () { const { settings, settingPath, label } = this.props; diff --git a/app/javascript/flavours/glitch/components/short_number.js b/app/javascript/flavours/glitch/components/short_number.jsx index 535c17727..535c17727 100644 --- a/app/javascript/flavours/glitch/components/short_number.js +++ b/app/javascript/flavours/glitch/components/short_number.jsx diff --git a/app/javascript/flavours/glitch/components/skeleton.js b/app/javascript/flavours/glitch/components/skeleton.jsx index 6a17ffb26..6a17ffb26 100644 --- a/app/javascript/flavours/glitch/components/skeleton.js +++ b/app/javascript/flavours/glitch/components/skeleton.jsx diff --git a/app/javascript/flavours/glitch/components/spoilers.js b/app/javascript/flavours/glitch/components/spoilers.jsx index 8527403c1..d1d875807 100644 --- a/app/javascript/flavours/glitch/components/spoilers.js +++ b/app/javascript/flavours/glitch/components/spoilers.jsx @@ -4,6 +4,7 @@ import { FormattedMessage } from 'react-intl'; export default class Spoilers extends React.PureComponent { + static propTypes = { spoilerText: PropTypes.string, children: PropTypes.node, @@ -11,40 +12,41 @@ class Spoilers extends React.PureComponent { state = { hidden: true, - } + }; handleSpoilerClick = () => { this.setState({ hidden: !this.state.hidden }); - } + }; render () { const { spoilerText, children } = this.props; const { hidden } = this.state; - const toggleText = hidden ? - <FormattedMessage - id='status.show_more' - defaultMessage='Show more' - key='0' - /> : - <FormattedMessage - id='status.show_less' - defaultMessage='Show less' - key='0' - />; + const toggleText = hidden ? + (<FormattedMessage + id='status.show_more' + defaultMessage='Show more' + key='0' + />) : + (<FormattedMessage + id='status.show_less' + defaultMessage='Show less' + key='0' + />); return ([ <p className='spoiler__text'> {spoilerText} {' '} - <button tabIndex='0' className='status__content__spoiler-link' onClick={this.handleSpoilerClick}> + <button tabIndex={0} className='status__content__spoiler-link' onClick={this.handleSpoilerClick}> {toggleText} </button> </p>, <div className={`status__content__spoiler ${!hidden ? 'status__content__spoiler--visible' : ''}`}> {children} - </div> + </div>, ]); } + } diff --git a/app/javascript/flavours/glitch/components/status.js b/app/javascript/flavours/glitch/components/status.jsx index 409ec0adc..fbb610823 100644 --- a/app/javascript/flavours/glitch/components/status.js +++ b/app/javascript/flavours/glitch/components/status.jsx @@ -54,9 +54,8 @@ export const defaultMediaVisibility = (status, settings) => { } return (displayMedia !== 'hide_all' && !status.get('sensitive') || displayMedia === 'show_all'); -} +}; -export default @injectIntl class Status extends ImmutablePureComponent { static contextTypes = { @@ -117,7 +116,7 @@ class Status extends ImmutablePureComponent { revealBehindCW: undefined, showCard: false, forceFilter: undefined, - } + }; // Avoid checking props that are functions (and whose equality will always // evaluate to false. See react-immutable-pure-component for usage. @@ -132,14 +131,14 @@ class Status extends ImmutablePureComponent { 'expanded', 'unread', 'pictureInPicture', - ] + ]; updateOnStates = [ 'isExpanded', 'isCollapsed', 'showMedia', 'forceFilter', - ] + ]; // If our settings have changed to disable collapsed statuses, then we // need to make sure that we uncollapse every one. We do that by watching @@ -224,7 +223,7 @@ class Status extends ImmutablePureComponent { // - The user has decided to collapse all notifications ('muted' // statuses). // - The user has decided to collapse long statuses and the status is - // over 400px (without media, or 650px with). + // over the user set value (default 400 without media, or 610px with). // - The status is a reply and the user has decided to collapse all // replies. // - The status contains media and the user has decided to collapse all @@ -251,10 +250,15 @@ class Status extends ImmutablePureComponent { // as it could cause surprising changes when receiving notifications if (settings.getIn(['content_warnings', 'shared_state']) && status.get('spoiler_text').length && !status.get('hidden')) return; + let autoCollapseHeight = parseInt(autoCollapseSettings.get('height')); + if (status.get('media_attachments').size && !muted) { + autoCollapseHeight += 210; + } + if (collapse || autoCollapseSettings.get('all') || (autoCollapseSettings.get('notifications') && muted) || - (autoCollapseSettings.get('lengthy') && node.clientHeight > ((status.get('media_attachments').size && !muted) ? 650 : 400)) || + (autoCollapseSettings.get('lengthy') && node.clientHeight > autoCollapseHeight) || (autoCollapseSettings.get('reblogs') && prepend === 'reblogged_by') || (autoCollapseSettings.get('replies') && status.get('in_reply_to_id', null) !== null) || (autoCollapseSettings.get('media') && !(status.get('spoiler_text').length) && status.get('media_attachments').size > 0) @@ -297,7 +301,9 @@ class Status extends ImmutablePureComponent { if (this.node && this.props.getScrollPosition) { const position = this.props.getScrollPosition(); if (position !== null && this.node.offsetTop < position.top) { - requestAnimationFrame(() => { this.props.updateScrollBottom(position.height - position.top); }); + requestAnimationFrame(() => { + this.props.updateScrollBottom(position.height - position.top); + }); } } } @@ -316,7 +322,7 @@ class Status extends ImmutablePureComponent { } else { this.setState({ isCollapsed: false }); } - } + }; setExpansion = (value) => { if (this.props.settings.getIn(['content_warnings', 'shared_state']) && this.props.status.get('hidden') === value) { @@ -327,7 +333,7 @@ class Status extends ImmutablePureComponent { if (value) { this.setCollapsed(false); } - } + }; // `parseClick()` takes a click event and responds appropriately. // If our status is collapsed, then clicking on it should uncollapse it. @@ -356,17 +362,17 @@ class Status extends ImmutablePureComponent { status.getIn(['reblog', 'id'], status.get('id')) }`; } - let state = {...router.history.location.state}; + let state = { ...router.history.location.state }; state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1; router.history.push(destination, state); } e.preventDefault(); } - } + }; handleToggleMediaVisibility = () => { this.setState({ showMedia: !this.state.showMedia }); - } + }; handleExpandedToggle = () => { if (this.props.settings.getIn(['content_warnings', 'shared_state'])) { @@ -379,11 +385,11 @@ class Status extends ImmutablePureComponent { handleOpenVideo = (options) => { const { status } = this.props; this.props.onOpenVideo(status.get('id'), status.getIn(['media_attachments', 0]), options); - } + }; handleOpenMedia = (media, index) => { this.props.onOpenMedia(this.props.status.get('id'), media, index); - } + }; handleHotkeyOpenMedia = e => { const { status, onOpenMedia, onOpenVideo } = this.props; @@ -398,84 +404,84 @@ class Status extends ImmutablePureComponent { onOpenMedia(statusId, status.get('media_attachments'), 0); } } - } + }; handleDeployPictureInPicture = (type, mediaProps) => { const { deployPictureInPicture, status } = this.props; deployPictureInPicture(status, type, mediaProps); - } + }; handleHotkeyReply = e => { e.preventDefault(); this.props.onReply(this.props.status, this.context.router.history); - } + }; handleHotkeyFavourite = (e) => { this.props.onFavourite(this.props.status, e); - } + }; handleHotkeyBoost = e => { this.props.onReblog(this.props.status, e); - } + }; handleHotkeyBookmark = e => { this.props.onBookmark(this.props.status, e); - } + }; handleHotkeyMention = e => { e.preventDefault(); this.props.onMention(this.props.status.get('account'), this.context.router.history); - } + }; handleHotkeyOpen = () => { - let state = {...this.context.router.history.location.state}; + let state = { ...this.context.router.history.location.state }; state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1; const status = this.props.status; this.context.router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`, state); - } + }; handleHotkeyOpenProfile = () => { - let state = {...this.context.router.history.location.state}; + let state = { ...this.context.router.history.location.state }; state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1; this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`, state); - } + }; handleHotkeyMoveUp = e => { this.props.onMoveUp(this.props.containerId || this.props.id, e.target.getAttribute('data-featured')); - } + }; handleHotkeyMoveDown = e => { this.props.onMoveDown(this.props.containerId || this.props.id, e.target.getAttribute('data-featured')); - } + }; handleHotkeyCollapse = e => { if (!this.props.settings.getIn(['collapsed', 'enabled'])) return; this.setCollapsed(!this.state.isCollapsed); - } + }; handleHotkeyToggleSensitive = () => { this.handleToggleMediaVisibility(); - } + }; handleUnfilterClick = e => { this.setState({ forceFilter: false }); e.preventDefault(); - } + }; handleFilterClick = () => { this.setState({ forceFilter: true }); - } + }; handleRef = c => { this.node = c; - } + }; handleTranslate = () => { this.props.onTranslate(this.props.status); - } + }; renderLoadingMediaGallery () { return <div className='media-gallery' style={{ height: '110px' }} />; @@ -558,7 +564,7 @@ class Status extends ImmutablePureComponent { if (hidden) { return ( <HotKeys handlers={handlers}> - <div ref={this.handleRef} className='status focusable' tabIndex='0'> + <div ref={this.handleRef} className='status focusable' tabIndex={0}> <span>{status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])}</span> <span>{status.get('content')}</span> </div> @@ -575,7 +581,7 @@ class Status extends ImmutablePureComponent { return ( <HotKeys handlers={minHandlers}> - <div className='status__wrapper status__wrapper--filtered focusable' tabIndex='0' ref={this.handleRef}> + <div className='status__wrapper status__wrapper--filtered focusable' tabIndex={0} ref={this.handleRef}> <FormattedMessage id='status.filtered' defaultMessage='Filtered' />: {matchedFilters.join(', ')}. {' '} <button className='status__wrapper--filtered__button' onClick={this.handleUnfilterClick}> @@ -623,6 +629,7 @@ class Status extends ImmutablePureComponent { <Component src={attachment.get('url')} alt={attachment.get('description')} + lang={status.get('language')} poster={attachment.get('preview_url') || status.getIn(['account', 'avatar_static'])} backgroundColor={attachment.getIn(['meta', 'colors', 'background'])} foregroundColor={attachment.getIn(['meta', 'colors', 'foreground'])} @@ -652,6 +659,7 @@ class Status extends ImmutablePureComponent { blurhash={attachment.get('blurhash')} src={attachment.get('url')} alt={attachment.get('description')} + lang={status.get('language')} inline sensitive={status.get('sensitive')} letterbox={settings.getIn(['media', 'letterbox'])} @@ -673,6 +681,7 @@ class Status extends ImmutablePureComponent { {Component => ( <Component media={attachments} + lang={status.get('language')} sensitive={status.get('sensitive')} letterbox={settings.getIn(['media', 'letterbox'])} fullwidth={settings.getIn(['media', 'fullwidth'])} @@ -707,7 +716,7 @@ class Status extends ImmutablePureComponent { } if (status.get('poll')) { - contentMedia.push(<PollContainer pollId={status.get('poll')} />); + contentMedia.push(<PollContainer pollId={status.get('poll')} lang={status.get('language')} />); contentMediaIcons.push('tasks'); } @@ -760,7 +769,7 @@ class Status extends ImmutablePureComponent { style={isCollapsed && background ? { backgroundImage: `url(${background})` } : null} {...selectorAttribs} ref={handleRef} - tabIndex='0' + tabIndex={0} data-featured={featured ? 'true' : null} aria-label={textForScreenReader(intl, status, rebloggedByText, !status.get('hidden'))} > @@ -820,3 +829,5 @@ class Status extends ImmutablePureComponent { } } + +export default injectIntl(Status); diff --git a/app/javascript/flavours/glitch/components/status_action_bar.js b/app/javascript/flavours/glitch/components/status_action_bar.jsx index baf61000a..091d0b24b 100644 --- a/app/javascript/flavours/glitch/components/status_action_bar.js +++ b/app/javascript/flavours/glitch/components/status_action_bar.jsx @@ -46,7 +46,6 @@ const messages = defineMessages({ openOriginalPage: { id: 'account.open_original_page', defaultMessage: 'Open original page' }, }); -export default @injectIntl class StatusActionBar extends ImmutablePureComponent { static contextTypes = { @@ -86,7 +85,7 @@ class StatusActionBar extends ImmutablePureComponent { 'showReplyCount', 'withCounters', 'withDismiss', - ] + ]; handleReplyClick = () => { const { signedIn } = this.context.identity; @@ -96,14 +95,14 @@ class StatusActionBar extends ImmutablePureComponent { } else { this.props.onInteractionModal('reply', this.props.status); } - } + }; handleShareClick = () => { navigator.share({ text: this.props.status.get('search_index'), url: this.props.status.get('url'), }); - } + }; handleFavouriteClick = (e) => { const { signedIn } = this.context.identity; @@ -113,7 +112,7 @@ class StatusActionBar extends ImmutablePureComponent { } else { this.props.onInteractionModal('favourite', this.props.status); } - } + }; handleReblogClick = e => { const { signedIn } = this.context.identity; @@ -123,78 +122,78 @@ class StatusActionBar extends ImmutablePureComponent { } else { this.props.onInteractionModal('reblog', this.props.status); } - } + }; handleBookmarkClick = (e) => { this.props.onBookmark(this.props.status, e); - } + }; handleDeleteClick = () => { this.props.onDelete(this.props.status, this.context.router.history); - } + }; handleRedraftClick = () => { this.props.onDelete(this.props.status, this.context.router.history, true); - } + }; handleEditClick = () => { this.props.onEdit(this.props.status, this.context.router.history); - } + }; handlePinClick = () => { this.props.onPin(this.props.status); - } + }; handleMentionClick = () => { this.props.onMention(this.props.status.get('account'), this.context.router.history); - } + }; handleDirectClick = () => { this.props.onDirect(this.props.status.get('account'), this.context.router.history); - } + }; handleMuteClick = () => { this.props.onMute(this.props.status.get('account')); - } + }; handleBlockClick = () => { this.props.onBlock(this.props.status); - } + }; handleOpen = () => { - let state = {...this.context.router.history.location.state}; + let state = { ...this.context.router.history.location.state }; if (state.mastodonModalKey) { this.context.router.history.replace(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`, { mastodonBackSteps: (state.mastodonBackSteps || 0) + 1 }); } else { state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1; this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`, state); } - } + }; handleEmbed = () => { this.props.onEmbed(this.props.status); - } + }; handleReport = () => { this.props.onReport(this.props.status); - } + }; handleConversationMuteClick = () => { this.props.onMuteConversation(this.props.status); - } + }; handleCopy = () => { const url = this.props.status.get('url'); navigator.clipboard.writeText(url); - } + }; handleHideClick = () => { this.props.onFilter(); - } + }; handleFilterClick = () => { this.props.onAddFilter(this.props.status); - } + }; render () { const { status, intl, withDismiss, withCounters, showReplyCount, scrollKey } = this.props; @@ -339,3 +338,5 @@ class StatusActionBar extends ImmutablePureComponent { } } + +export default injectIntl(StatusActionBar); diff --git a/app/javascript/flavours/glitch/components/status_content.js b/app/javascript/flavours/glitch/components/status_content.jsx index c59f42220..e66df588a 100644 --- a/app/javascript/flavours/glitch/components/status_content.js +++ b/app/javascript/flavours/glitch/components/status_content.jsx @@ -3,16 +3,17 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import PropTypes from 'prop-types'; import { FormattedMessage, injectIntl } from 'react-intl'; import Permalink from './permalink'; +import { connect } from 'react-redux'; import classnames from 'classnames'; import Icon from 'flavours/glitch/components/icon'; -import { autoPlayGif, languages as preloadedLanguages, translationEnabled } from 'flavours/glitch/initial_state'; +import { autoPlayGif, languages as preloadedLanguages } from 'flavours/glitch/initial_state'; import { decode as decodeIDNA } from 'flavours/glitch/utils/idna'; const textMatchesTarget = (text, origin, host) => { return (text === origin || text === host || text.startsWith(origin + '/') || text.startsWith(host + '/') || 'www.' + text === host || ('www.' + text).startsWith(host + '/')); -} +}; const isLinkMisleading = (link) => { let linkTextParts = []; @@ -99,7 +100,10 @@ class TranslateButton extends React.PureComponent { } -export default @injectIntl +const mapStateToProps = state => ({ + languages: state.getIn(['server', 'translationLanguages', 'items']), +}); + class StatusContent extends React.PureComponent { static contextTypes = { @@ -120,6 +124,7 @@ class StatusContent extends React.PureComponent { onUpdate: PropTypes.func, tagLinks: PropTypes.bool, rewriteMentions: PropTypes.string, + languages: ImmutablePropTypes.map, intl: PropTypes.object, }; @@ -168,8 +173,8 @@ class StatusContent extends React.PureComponent { link.setAttribute('title', link.href); link.classList.add('unhandled-link'); - link.setAttribute('target', '_blank'); - link.setAttribute('rel', 'noopener nofollow noreferrer'); + link.setAttribute('target', '_blank'); + link.setAttribute('rel', 'noopener nofollow noreferrer'); try { if (tagLinks && isLinkMisleading(link)) { @@ -210,7 +215,7 @@ class StatusContent extends React.PureComponent { let emoji = emojis[i]; emoji.src = emoji.getAttribute('data-original'); } - } + }; handleMouseLeave = ({ currentTarget }) => { if (autoPlayGif) { @@ -223,7 +228,7 @@ class StatusContent extends React.PureComponent { let emoji = emojis[i]; emoji.src = emoji.getAttribute('data-static'); } - } + }; componentDidMount () { this._updateStatusLinks(); @@ -238,13 +243,13 @@ class StatusContent extends React.PureComponent { if (this.props.collapsed) { if (this.props.parseClick) this.props.parseClick(e); } - } + }; onMentionClick = (mention, e) => { if (this.props.parseClick) { this.props.parseClick(e, `/@${mention.get('acct')}`); } - } + }; onHashtagClick = (hashtag, e) => { hashtag = hashtag.replace(/^#/, ''); @@ -252,11 +257,11 @@ class StatusContent extends React.PureComponent { if (this.props.parseClick) { this.props.parseClick(e, `/tags/${hashtag}`); } - } + }; handleMouseDown = (e) => { this.startXY = [e.clientX, e.clientY]; - } + }; handleMouseUp = (e) => { const { parseClick, disabled } = this.props; @@ -281,7 +286,7 @@ class StatusContent extends React.PureComponent { } this.startXY = null; - } + }; handleSpoilerClick = (e) => { e.preventDefault(); @@ -291,15 +296,15 @@ class StatusContent extends React.PureComponent { } else { this.setState({ hidden: !this.state.hidden }); } - } + }; handleTranslate = () => { this.props.onTranslate(); - } + }; setContentsRef = (c) => { this.contentsNode = c; - } + }; render () { const { @@ -315,7 +320,9 @@ class StatusContent extends React.PureComponent { } = this.props; const hidden = this.props.onExpandedToggle ? !this.props.expanded : this.state.hidden; - const renderTranslate = translationEnabled && this.context.identity.signedIn && this.props.onTranslate && ['public', 'unlisted'].includes(status.get('visibility')) && status.get('contentHtml').length > 0 && status.get('language') !== null && intl.locale !== status.get('language'); + const contentLocale = intl.locale.replace(/[_-].*/, ''); + const targetLanguages = this.props.languages?.get(status.get('language') || 'und'); + const renderTranslate = this.props.onTranslate && this.context.identity.signedIn && ['public', 'unlisted'].includes(status.get('visibility')) && status.get('contentHtml').length > 0 && targetLanguages?.includes(contentLocale); const content = { __html: status.get('translation') ? status.getIn(['translation', 'content']) : status.get('contentHtml') }; const spoilerContent = { __html: status.get('spoilerHtml') }; @@ -380,7 +387,7 @@ class StatusContent extends React.PureComponent { } return ( - <div className={classNames} tabIndex='0' onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp}> + <div className={classNames} tabIndex={0} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp}> <p style={{ marginBottom: hidden && status.get('mentions').isEmpty() ? '0px' : null }} > @@ -417,14 +424,14 @@ class StatusContent extends React.PureComponent { className={classNames} onMouseDown={this.handleMouseDown} onMouseUp={this.handleMouseUp} - tabIndex='0' + tabIndex={0} > <div ref={this.setContentsRef} key={`contents-${tagLinks}-${rewriteMentions}`} dangerouslySetInnerHTML={content} className='status__content__text translate' - tabIndex='0' + tabIndex={0} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} lang={lang} @@ -438,14 +445,14 @@ class StatusContent extends React.PureComponent { return ( <div className='status__content' - tabIndex='0' + tabIndex={0} > <div ref={this.setContentsRef} key={`contents-${tagLinks}`} className='status__content__text translate' dangerouslySetInnerHTML={content} - tabIndex='0' + tabIndex={0} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} lang={lang} @@ -459,3 +466,5 @@ class StatusContent extends React.PureComponent { } } + +export default connect(mapStateToProps)(injectIntl(StatusContent)); diff --git a/app/javascript/flavours/glitch/components/status_header.js b/app/javascript/flavours/glitch/components/status_header.jsx index 990dea536..21d8b4212 100644 --- a/app/javascript/flavours/glitch/components/status_header.js +++ b/app/javascript/flavours/glitch/components/status_header.jsx @@ -21,12 +21,12 @@ export default class StatusHeader extends React.PureComponent { handleClick = (acct, e) => { const { parseClick } = this.props; parseClick(e, `/@${acct}`); - } + }; handleAccountClick = (e) => { const { status } = this.props; this.handleClick(status.getIn(['account', 'acct']), e); - } + }; // Rendering. render () { diff --git a/app/javascript/flavours/glitch/components/status_icons.js b/app/javascript/flavours/glitch/components/status_icons.jsx index 71ffb2e56..3baff2206 100644 --- a/app/javascript/flavours/glitch/components/status_icons.js +++ b/app/javascript/flavours/glitch/components/status_icons.jsx @@ -40,7 +40,6 @@ LanguageIcon.propTypes = { language: PropTypes.string.isRequired, }; -export default @injectIntl class StatusIcons extends React.PureComponent { static propTypes = { @@ -60,22 +59,22 @@ class StatusIcons extends React.PureComponent { setCollapsed(!collapsed); e.preventDefault(); } - } + }; mediaIconTitleText (mediaIcon) { const { intl } = this.props; switch (mediaIcon) { - case 'link': - return intl.formatMessage(messages.previewCard); - case 'picture-o': - return intl.formatMessage(messages.pictures); - case 'tasks': - return intl.formatMessage(messages.poll); - case 'video-camera': - return intl.formatMessage(messages.video); - case 'music': - return intl.formatMessage(messages.audio); + case 'link': + return intl.formatMessage(messages.previewCard); + case 'picture-o': + return intl.formatMessage(messages.pictures); + case 'tasks': + return intl.formatMessage(messages.poll); + case 'video-camera': + return intl.formatMessage(messages.video); + case 'music': + return intl.formatMessage(messages.audio); } } @@ -143,3 +142,5 @@ class StatusIcons extends React.PureComponent { } } + +export default injectIntl(StatusIcons); diff --git a/app/javascript/flavours/glitch/components/status_list.js b/app/javascript/flavours/glitch/components/status_list.jsx index 0d843a27d..a9c06f693 100644 --- a/app/javascript/flavours/glitch/components/status_list.js +++ b/app/javascript/flavours/glitch/components/status_list.jsx @@ -35,7 +35,7 @@ export default class StatusList extends ImmutablePureComponent { getFeaturedStatusCount = () => { return this.props.featuredStatusIds ? this.props.featuredStatusIds.size : 0; - } + }; getCurrentStatusIndex = (id, featured) => { if (featured) { @@ -43,21 +43,21 @@ export default class StatusList extends ImmutablePureComponent { } else { return this.props.statusIds.indexOf(id) + this.getFeaturedStatusCount(); } - } + }; handleMoveUp = (id, featured) => { const elementIndex = this.getCurrentStatusIndex(id, featured) - 1; this._selectChild(elementIndex, true); - } + }; handleMoveDown = (id, featured) => { const elementIndex = this.getCurrentStatusIndex(id, featured) + 1; this._selectChild(elementIndex, false); - } + }; handleLoadOlder = debounce(() => { this.props.onLoadMore(this.props.statusIds.size > 0 ? this.props.statusIds.last() : undefined); - }, 300, { leading: true }) + }, 300, { leading: true }); _selectChild (index, align_top) { const container = this.node.node; @@ -75,7 +75,7 @@ export default class StatusList extends ImmutablePureComponent { setRef = c => { this.node = c; - } + }; render () { const { statusIds, featuredStatusIds, onLoadMore, timelineId, ...other } = this.props; diff --git a/app/javascript/flavours/glitch/components/status_prepend.js b/app/javascript/flavours/glitch/components/status_prepend.jsx index f82533062..8c4343b04 100644 --- a/app/javascript/flavours/glitch/components/status_prepend.js +++ b/app/javascript/flavours/glitch/components/status_prepend.jsx @@ -18,7 +18,7 @@ export default class StatusPrepend extends React.PureComponent { handleClick = (e) => { const { account, parseClick } = this.props; parseClick(e, `/@${account.get('acct')}`); - } + }; Message = () => { const { type, account } = this.props; @@ -98,7 +98,7 @@ export default class StatusPrepend extends React.PureComponent { ); } return null; - } + }; render () { const { Message } = this; @@ -126,7 +126,7 @@ export default class StatusPrepend extends React.PureComponent { case 'update': iconId = 'pencil'; break; - }; + } return !type ? null : ( <aside className={type === 'reblogged_by' || type === 'featured' ? 'status__prepend' : 'notification__message'}> diff --git a/app/javascript/flavours/glitch/components/status_visibility_icon.js b/app/javascript/flavours/glitch/components/status_visibility_icon.jsx index 07d56c7a8..fcedfbfd6 100644 --- a/app/javascript/flavours/glitch/components/status_visibility_icon.js +++ b/app/javascript/flavours/glitch/components/status_visibility_icon.jsx @@ -12,7 +12,6 @@ const messages = defineMessages({ direct: { id: 'privacy.direct.short', defaultMessage: 'Mentioned people only' }, }); -export default @injectIntl class VisibilityIcon extends ImmutablePureComponent { static propTypes = { @@ -49,3 +48,5 @@ class VisibilityIcon extends ImmutablePureComponent { } } + +export default injectIntl(VisibilityIcon); diff --git a/app/javascript/flavours/glitch/components/timeline_hint.js b/app/javascript/flavours/glitch/components/timeline_hint.jsx index fb55a62cc..fb55a62cc 100644 --- a/app/javascript/flavours/glitch/components/timeline_hint.js +++ b/app/javascript/flavours/glitch/components/timeline_hint.jsx |