From 44a7d87cb1f5df953b6c14c16c59e2e4ead1bcb9 Mon Sep 17 00:00:00 2001 From: Renaud Chaput Date: Mon, 20 Feb 2023 03:20:59 +0100 Subject: Rename JSX files with proper `.jsx` extension (#23733) --- .../components/intersection_observer_article.jsx | 130 +++++++++++++++++++++ 1 file changed, 130 insertions(+) create mode 100644 app/javascript/mastodon/components/intersection_observer_article.jsx (limited to 'app/javascript/mastodon/components/intersection_observer_article.jsx') diff --git a/app/javascript/mastodon/components/intersection_observer_article.jsx b/app/javascript/mastodon/components/intersection_observer_article.jsx new file mode 100644 index 000000000..c2feb003a --- /dev/null +++ b/app/javascript/mastodon/components/intersection_observer_article.jsx @@ -0,0 +1,130 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import scheduleIdleTask from '../features/ui/util/schedule_idle_task'; +import getRectFromEntry from '../features/ui/util/get_rect_from_entry'; + +// Diff these props in the "unrendered" state +const updateOnPropsForUnrendered = ['id', 'index', 'listLength', 'cachedHeight']; + +export default class IntersectionObserverArticle extends React.Component { + + static propTypes = { + intersectionObserverWrapper: PropTypes.object.isRequired, + id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + index: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + listLength: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), + saveHeightKey: PropTypes.string, + cachedHeight: PropTypes.number, + onHeightChange: PropTypes.func, + children: PropTypes.node, + }; + + 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); + const willBeUnrendered = !nextState.isIntersecting && (nextState.isHidden || nextProps.cachedHeight); + if (!!isUnrendered !== !!willBeUnrendered) { + // If we're going from rendered to unrendered (or vice versa) then update + return true; + } + // If we are and remain hidden, diff based on props + if (isUnrendered) { + return !updateOnPropsForUnrendered.every(prop => nextProps[prop] === this.props[prop]); + } + // Else, assume the children have changed + return true; + } + + componentDidMount () { + const { intersectionObserverWrapper, id } = this.props; + + intersectionObserverWrapper.observe( + id, + this.node, + this.handleIntersection, + ); + + this.componentMounted = true; + } + + componentWillUnmount () { + const { intersectionObserverWrapper, id } = this.props; + intersectionObserverWrapper.unobserve(id, this.node); + + this.componentMounted = false; + } + + handleIntersection = (entry) => { + this.entry = entry; + + scheduleIdleTask(this.calculateHeight); + this.setState(this.updateStateAfterIntersection); + }; + + updateStateAfterIntersection = (prevState) => { + if (prevState.isIntersecting !== false && !this.entry.isIntersecting) { + scheduleIdleTask(this.hideIfNotIntersecting); + } + return { + isIntersecting: this.entry.isIntersecting, + isHidden: false, + }; + }; + + calculateHeight = () => { + const { onHeightChange, saveHeightKey, id } = this.props; + // save the height of the fully-rendered element (this is expensive + // on Chrome, where we need to fall back to getBoundingClientRect) + this.height = getRectFromEntry(this.entry).height; + + if (onHeightChange && saveHeightKey) { + onHeightChange(saveHeightKey, id, this.height); + } + }; + + hideIfNotIntersecting = () => { + if (!this.componentMounted) { + return; + } + + // When the browser gets a chance, test if we're still not intersecting, + // and if so, set our isHidden to true to trigger an unrender. The point of + // 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; + const { isIntersecting, isHidden } = this.state; + + if (!isIntersecting && (isHidden || cachedHeight)) { + return ( +
+ {children && React.cloneElement(children, { hidden: true })} +
+ ); + } + + return ( +
+ {children && React.cloneElement(children, { hidden: false })} +
+ ); + } + +} -- cgit From ec0c104bf25f2689c31bb79f9f447be1a9b3da7f Mon Sep 17 00:00:00 2001 From: Nick Schonning Date: Tue, 4 Apr 2023 10:33:44 -0400 Subject: Ensure tabIndex is number instead of string (#24409) --- .../mastodon/components/admin/ReportReasonSelector.jsx | 4 ++-- .../mastodon/components/autosuggest_input.jsx | 2 +- .../mastodon/components/autosuggest_textarea.jsx | 2 +- .../mastodon/components/column_back_button_slim.jsx | 2 +- app/javascript/mastodon/components/dropdown_menu.jsx | 2 +- app/javascript/mastodon/components/gifv.jsx | 4 ++-- app/javascript/mastodon/components/icon_button.jsx | 4 ++-- .../components/intersection_observer_article.jsx | 4 ++-- .../components/picture_in_picture_placeholder.jsx | 2 +- app/javascript/mastodon/components/poll.jsx | 2 +- app/javascript/mastodon/components/status.jsx | 4 ++-- app/javascript/mastodon/components/status_content.jsx | 6 +++--- app/javascript/mastodon/features/about/index.jsx | 2 +- app/javascript/mastodon/features/audio/index.jsx | 8 ++++---- .../features/compose/components/language_dropdown.jsx | 2 +- .../mastodon/features/compose/components/poll_form.jsx | 2 +- .../features/compose/components/privacy_dropdown.jsx | 2 +- .../mastodon/features/compose/components/search.jsx | 2 +- .../mastodon/features/compose/components/upload.jsx | 2 +- .../direct_timeline/components/conversation.jsx | 2 +- .../mastodon/features/filters/select_filter.jsx | 4 ++-- .../features/list_editor/components/search.jsx | 2 +- app/javascript/mastodon/features/list_editor/index.jsx | 2 +- .../mastodon/features/list_timeline/index.jsx | 4 ++-- .../notifications/components/clear_column_button.jsx | 2 +- .../components/grant_permission_button.jsx | 2 +- .../features/notifications/components/notification.jsx | 18 +++++++++--------- .../mastodon/features/report/components/option.jsx | 2 +- app/javascript/mastodon/features/status/index.jsx | 2 +- .../mastodon/features/ui/components/actions_modal.jsx | 2 +- .../mastodon/features/ui/components/media_modal.jsx | 4 ++-- app/javascript/mastodon/features/video/index.jsx | 6 +++--- 32 files changed, 55 insertions(+), 55 deletions(-) (limited to 'app/javascript/mastodon/components/intersection_observer_article.jsx') diff --git a/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx b/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx index 58a861fde..cd14dac4e 100644 --- a/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx +++ b/app/javascript/mastodon/components/admin/ReportReasonSelector.jsx @@ -33,7 +33,7 @@ class Category extends React.PureComponent { const { id, text, disabled, selected, children } = this.props; return ( -
+
{selected && }
@@ -74,7 +74,7 @@ class Rule extends React.PureComponent { const { id, text, disabled, selected } = this.props; return ( -
+
{selected && } {text} diff --git a/app/javascript/mastodon/components/autosuggest_input.jsx b/app/javascript/mastodon/components/autosuggest_input.jsx index f9616c581..a68e2a01b 100644 --- a/app/javascript/mastodon/components/autosuggest_input.jsx +++ b/app/javascript/mastodon/components/autosuggest_input.jsx @@ -180,7 +180,7 @@ export default class AutosuggestInput extends ImmutablePureComponent { } return ( -
+
{inner}
); diff --git a/app/javascript/mastodon/components/autosuggest_textarea.jsx b/app/javascript/mastodon/components/autosuggest_textarea.jsx index c04491298..a627bc1ec 100644 --- a/app/javascript/mastodon/components/autosuggest_textarea.jsx +++ b/app/javascript/mastodon/components/autosuggest_textarea.jsx @@ -186,7 +186,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent { } return ( -
+
{inner}
); diff --git a/app/javascript/mastodon/components/column_back_button_slim.jsx b/app/javascript/mastodon/components/column_back_button_slim.jsx index cc8bfb151..46ac23736 100644 --- a/app/javascript/mastodon/components/column_back_button_slim.jsx +++ b/app/javascript/mastodon/components/column_back_button_slim.jsx @@ -8,7 +8,7 @@ export default class ColumnBackButtonSlim extends ColumnBackButton { render () { return (
-
+
diff --git a/app/javascript/mastodon/components/dropdown_menu.jsx b/app/javascript/mastodon/components/dropdown_menu.jsx index c04c513fb..eaaa72fd8 100644 --- a/app/javascript/mastodon/components/dropdown_menu.jsx +++ b/app/javascript/mastodon/components/dropdown_menu.jsx @@ -119,7 +119,7 @@ class DropdownMenu extends React.PureComponent { return (
  • - + {text}
  • diff --git a/app/javascript/mastodon/components/gifv.jsx b/app/javascript/mastodon/components/gifv.jsx index 9ec201c6c..1ce7e7c29 100644 --- a/app/javascript/mastodon/components/gifv.jsx +++ b/app/javascript/mastodon/components/gifv.jsx @@ -46,7 +46,7 @@ export default class GIFV extends React.PureComponent { width={width} height={height} role='button' - tabIndex='0' + tabIndex={0} aria-label={alt} title={alt} lang={lang} @@ -57,7 +57,7 @@ export default class GIFV extends React.PureComponent {