[Glitch] Upgrade to React 18

Port 8d6aea3326 to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
pull/62/head
Renaud Chaput 2023-05-22 15:48:01 +02:00 committed by Claire
parent 45d7358100
commit 3b375ee395
12 changed files with 52 additions and 44 deletions

View File

@ -3,6 +3,8 @@ import PropTypes from 'prop-types';
import { supportsPassiveEvents } from 'detect-passive-events'; import { supportsPassiveEvents } from 'detect-passive-events';
import { scrollTop } from '../scroll'; import { scrollTop } from '../scroll';
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
export default class Column extends React.PureComponent { export default class Column extends React.PureComponent {
static propTypes = { static propTypes = {
@ -37,17 +39,17 @@ export default class Column extends React.PureComponent {
componentDidMount () { componentDidMount () {
if (this.props.bindToDocument) { if (this.props.bindToDocument) {
document.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false); document.addEventListener('wheel', this.handleWheel, listenerOptions);
} else { } else {
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false); this.node.addEventListener('wheel', this.handleWheel, listenerOptions);
} }
} }
componentWillUnmount () { componentWillUnmount () {
if (this.props.bindToDocument) { if (this.props.bindToDocument) {
document.removeEventListener('wheel', this.handleWheel); document.removeEventListener('wheel', this.handleWheel, listenerOptions);
} else { } else {
this.node.removeEventListener('wheel', this.handleWheel); this.node.removeEventListener('wheel', this.handleWheel, listenerOptions);
} }
} }

View File

@ -7,7 +7,7 @@ import { supportsPassiveEvents } from 'detect-passive-events';
import classNames from 'classnames'; import classNames from 'classnames';
import { CircularProgress } from 'flavours/glitch/components/loading_indicator'; import { CircularProgress } from 'flavours/glitch/components/loading_indicator';
const listenerOptions = supportsPassiveEvents ? { passive: true } : false; const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
let id = 0; let id = 0;
class DropdownMenu extends React.PureComponent { class DropdownMenu extends React.PureComponent {
@ -35,12 +35,13 @@ class DropdownMenu extends React.PureComponent {
handleDocumentClick = e => { handleDocumentClick = e => {
if (this.node && !this.node.contains(e.target)) { if (this.node && !this.node.contains(e.target)) {
this.props.onClose(); this.props.onClose();
e.stopPropagation();
} }
}; };
componentDidMount () { componentDidMount () {
document.addEventListener('click', this.handleDocumentClick, false); document.addEventListener('click', this.handleDocumentClick, { capture: true });
document.addEventListener('keydown', this.handleKeyDown, false); document.addEventListener('keydown', this.handleKeyDown, { capture: true });
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
if (this.focusedItem && this.props.openedViaKeyboard) { if (this.focusedItem && this.props.openedViaKeyboard) {
@ -49,8 +50,8 @@ class DropdownMenu extends React.PureComponent {
} }
componentWillUnmount () { componentWillUnmount () {
document.removeEventListener('click', this.handleDocumentClick, false); document.removeEventListener('click', this.handleDocumentClick, { capture: true });
document.removeEventListener('keydown', this.handleKeyDown, false); document.removeEventListener('keydown', this.handleKeyDown, { capture: true });
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions); document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
} }

View File

@ -15,6 +15,8 @@ import { connect } from 'react-redux';
const MOUSE_IDLE_DELAY = 300; const MOUSE_IDLE_DELAY = 300;
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
const mapStateToProps = (state, { scrollKey }) => { const mapStateToProps = (state, { scrollKey }) => {
return { return {
preventScroll: scrollKey === state.getIn(['dropdown_menu', 'scroll_key']), preventScroll: scrollKey === state.getIn(['dropdown_menu', 'scroll_key']),
@ -237,20 +239,20 @@ class ScrollableList extends PureComponent {
attachScrollListener () { attachScrollListener () {
if (this.props.bindToDocument) { if (this.props.bindToDocument) {
document.addEventListener('scroll', this.handleScroll); document.addEventListener('scroll', this.handleScroll);
document.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : undefined); document.addEventListener('wheel', this.handleWheel, listenerOptions);
} else { } else {
this.node.addEventListener('scroll', this.handleScroll); this.node.addEventListener('scroll', this.handleScroll);
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : undefined); this.node.addEventListener('wheel', this.handleWheel, listenerOptions);
} }
} }
detachScrollListener () { detachScrollListener () {
if (this.props.bindToDocument) { if (this.props.bindToDocument) {
document.removeEventListener('scroll', this.handleScroll); document.removeEventListener('scroll', this.handleScroll);
document.removeEventListener('wheel', this.handleWheel); document.removeEventListener('wheel', this.handleWheel, listenerOptions);
} else { } else {
this.node.removeEventListener('scroll', this.handleScroll); this.node.removeEventListener('scroll', this.handleScroll);
this.node.removeEventListener('wheel', this.handleWheel); this.node.removeEventListener('wheel', this.handleWheel, listenerOptions);
} }
} }

View File

@ -1,5 +1,5 @@
import React, { PureComponent, Fragment } from 'react'; import React, { PureComponent, Fragment } from 'react';
import ReactDOM from 'react-dom'; import { createPortal } from 'react-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { IntlProvider, addLocaleData } from 'react-intl'; import { IntlProvider, addLocaleData } from 'react-intl';
import { fromJS } from 'immutable'; import { fromJS } from 'immutable';
@ -95,7 +95,7 @@ export default class MediaContainer extends PureComponent {
}), }),
}); });
return ReactDOM.createPortal( return createPortal(
<Component {...props} key={`media-${i}`} />, <Component {...props} key={`media-${i}`} />,
component, component,
); );

View File

@ -2,12 +2,12 @@
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import React from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { supportsPassiveEvents } from 'detect-passive-events';
// Components. // Components.
import { Icon } from 'flavours/glitch/components/icon'; import { Icon } from 'flavours/glitch/components/icon';
// Utils. const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
import { withPassive } from 'flavours/glitch/utils/dom_helpers';
// The component. // The component.
export default class ComposerOptionsDropdownContent extends React.PureComponent { export default class ComposerOptionsDropdownContent extends React.PureComponent {
@ -41,6 +41,7 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
handleDocumentClick = (e) => { handleDocumentClick = (e) => {
if (this.node && !this.node.contains(e.target)) { if (this.node && !this.node.contains(e.target)) {
this.props.onClose(); this.props.onClose();
e.stopPropagation();
} }
}; };
@ -51,8 +52,8 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
// On mounting, we add our listeners. // On mounting, we add our listeners.
componentDidMount () { componentDidMount () {
document.addEventListener('click', this.handleDocumentClick, false); document.addEventListener('click', this.handleDocumentClick, { capture: true });
document.addEventListener('touchend', this.handleDocumentClick, withPassive); document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
if (this.focusedItem) { if (this.focusedItem) {
this.focusedItem.focus({ preventScroll: true }); this.focusedItem.focus({ preventScroll: true });
} else { } else {
@ -62,8 +63,8 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
// On unmounting, we remove our listeners. // On unmounting, we remove our listeners.
componentWillUnmount () { componentWillUnmount () {
document.removeEventListener('click', this.handleDocumentClick, false); document.removeEventListener('click', this.handleDocumentClick, { capture: true });
document.removeEventListener('touchend', this.handleDocumentClick, withPassive); document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
} }
handleClick = (e) => { handleClick = (e) => {

View File

@ -28,7 +28,7 @@ const messages = defineMessages({
let EmojiPicker, Emoji; // load asynchronously let EmojiPicker, Emoji; // load asynchronously
const listenerOptions = supportsPassiveEvents ? { passive: true } : false; const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
const backgroundImageFn = () => `${assetHost}/emoji/sheet_13.png`; const backgroundImageFn = () => `${assetHost}/emoji/sheet_13.png`;
@ -79,12 +79,12 @@ class ModifierPickerMenu extends React.PureComponent {
}; };
attachListeners () { attachListeners () {
document.addEventListener('click', this.handleDocumentClick, false); document.addEventListener('click', this.handleDocumentClick, { capture: true });
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
} }
removeListeners () { removeListeners () {
document.removeEventListener('click', this.handleDocumentClick, false); document.removeEventListener('click', this.handleDocumentClick, { capture: true });
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions); document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
} }
@ -177,7 +177,7 @@ class EmojiPickerMenuImpl extends React.PureComponent {
}; };
componentDidMount () { componentDidMount () {
document.addEventListener('click', this.handleDocumentClick, false); document.addEventListener('click', this.handleDocumentClick, { capture: true });
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
// Because of https://github.com/react-bootstrap/react-bootstrap/issues/2614 we need // Because of https://github.com/react-bootstrap/react-bootstrap/issues/2614 we need
@ -192,7 +192,7 @@ class EmojiPickerMenuImpl extends React.PureComponent {
} }
componentWillUnmount () { componentWillUnmount () {
document.removeEventListener('click', this.handleDocumentClick, false); document.removeEventListener('click', this.handleDocumentClick, { capture: true });
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions); document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
} }

View File

@ -15,7 +15,7 @@ const messages = defineMessages({
clear: { id: 'emoji_button.clear', defaultMessage: 'Clear' }, clear: { id: 'emoji_button.clear', defaultMessage: 'Clear' },
}); });
const listenerOptions = supportsPassiveEvents ? { passive: true } : false; const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
class LanguageDropdownMenu extends React.PureComponent { class LanguageDropdownMenu extends React.PureComponent {
@ -39,11 +39,12 @@ class LanguageDropdownMenu extends React.PureComponent {
handleDocumentClick = e => { handleDocumentClick = e => {
if (this.node && !this.node.contains(e.target)) { if (this.node && !this.node.contains(e.target)) {
this.props.onClose(); this.props.onClose();
e.stopPropagation();
} }
}; };
componentDidMount () { componentDidMount () {
document.addEventListener('click', this.handleDocumentClick, false); document.addEventListener('click', this.handleDocumentClick, { capture: true });
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions); document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
// Because of https://github.com/react-bootstrap/react-bootstrap/issues/2614 we need // Because of https://github.com/react-bootstrap/react-bootstrap/issues/2614 we need
@ -57,7 +58,7 @@ class LanguageDropdownMenu extends React.PureComponent {
} }
componentWillUnmount () { componentWillUnmount () {
document.removeEventListener('click', this.handleDocumentClick, false); document.removeEventListener('click', this.handleDocumentClick, { capture: true });
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions); document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
} }

View File

@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import { createRoot } from 'react-dom/client';
import { setupBrowserNotifications } from 'flavours/glitch/actions/notifications'; import { setupBrowserNotifications } from 'flavours/glitch/actions/notifications';
import Mastodon from 'flavours/glitch/containers/mastodon'; import Mastodon from 'flavours/glitch/containers/mastodon';
import { store } from 'flavours/glitch/store'; import { store } from 'flavours/glitch/store';
@ -18,7 +18,8 @@ function main() {
const mountNode = document.getElementById('mastodon'); const mountNode = document.getElementById('mastodon');
const props = JSON.parse(mountNode.getAttribute('data-props')); const props = JSON.parse(mountNode.getAttribute('data-props'));
ReactDOM.render(<Mastodon {...props} />, mountNode); const root = createRoot(mountNode);
root.render(<Mastodon {...props} />);
store.dispatch(setupBrowserNotifications()); store.dispatch(setupBrowserNotifications());
if (process.env.NODE_ENV === 'production' && me && 'serviceWorker' in navigator) { if (process.env.NODE_ENV === 'production' && me && 'serviceWorker' in navigator) {

View File

@ -1,7 +1,7 @@
import 'packs/public-path'; import 'packs/public-path';
import ready from 'flavours/glitch/ready'; import ready from 'flavours/glitch/ready';
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import { createRoot } from 'react-dom/client';
ready(() => { ready(() => {
[].forEach.call(document.querySelectorAll('[data-admin-component]'), element => { [].forEach.call(document.querySelectorAll('[data-admin-component]'), element => {
@ -10,11 +10,13 @@ ready(() => {
import('flavours/glitch/containers/admin_component').then(({ default: AdminComponent }) => { import('flavours/glitch/containers/admin_component').then(({ default: AdminComponent }) => {
return import('flavours/glitch/components/admin/' + componentName).then(({ default: Component }) => { return import('flavours/glitch/components/admin/' + componentName).then(({ default: Component }) => {
ReactDOM.render(( const root = createRoot(element);
root.render (
<AdminComponent locale={locale}> <AdminComponent locale={locale}>
<Component {...componentProps} /> <Component {...componentProps} />
</AdminComponent> </AdminComponent>,
), element); );
}); });
}).catch(error => { }).catch(error => {
console.error(error); console.error(error);

View File

@ -11,7 +11,7 @@ import { delegate } from '@rails/ujs';
import emojify from 'flavours/glitch/features/emoji/emoji'; import emojify from 'flavours/glitch/features/emoji/emoji';
import { getLocale } from 'locales'; import { getLocale } from 'locales';
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import { createRoot } from 'react-dom/client';
import { createBrowserHistory } from 'history'; import { createBrowserHistory } from 'history';
const messages = defineMessages({ const messages = defineMessages({
@ -130,7 +130,8 @@ function main() {
const content = document.createElement('div'); const content = document.createElement('div');
ReactDOM.render(<MediaContainer locale={locale} components={reactComponents} />, content); const root = createRoot(content);
root.render(<MediaContainer locale={locale} components={reactComponents} />);
document.body.appendChild(content); document.body.appendChild(content);
scrollToDetailedStatus(); scrollToDetailedStatus();
}) })

View File

@ -1,9 +1,9 @@
import 'packs/public-path'; import 'packs/public-path';
import { loadPolyfills } from 'flavours/glitch/polyfills'; import { loadPolyfills } from 'flavours/glitch/polyfills';
import ready from 'flavours/glitch/ready';
import ComposeContainer from 'flavours/glitch/containers/compose_container'; import ComposeContainer from 'flavours/glitch/containers/compose_container';
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import { createRoot } from 'react-dom/client';
import ready from 'flavours/glitch/ready';
function loaded() { function loaded() {
const mountNode = document.getElementById('mastodon-compose'); const mountNode = document.getElementById('mastodon-compose');
@ -13,7 +13,8 @@ function loaded() {
if(!attr) return; if(!attr) return;
const props = JSON.parse(attr); const props = JSON.parse(attr);
ReactDOM.render(<ComposeContainer {...props} />, mountNode); const root = createRoot(mountNode);
root.render(<ComposeContainer {...props} />);
} }
} }

View File

@ -1,10 +1,6 @@
// Package imports. // Package imports.
import { supportsPassiveEvents } from 'detect-passive-events'; import { supportsPassiveEvents } from 'detect-passive-events';
// This will either be a passive lister options object (if passive
// events are supported), or `false`.
export const withPassive = supportsPassiveEvents ? { passive: true } : false;
// Focuses the root element. // Focuses the root element.
export function focusRoot () { export function focusRoot () {
let e; let e;