From a65d2d10458fcb6c1c36fa6dd52b8f64d12ce50d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=9F=E3=81=84=E3=81=A1=20=E3=81=B2?=
Date: Mon, 8 May 2023 18:12:44 +0900
Subject: [PATCH 4/9] Rewrite Image component as function component (#24893)
---
app/javascript/mastodon/components/image.jsx | 33 --------------------
app/javascript/mastodon/components/image.tsx | 27 ++++++++++++++++
2 files changed, 27 insertions(+), 33 deletions(-)
delete mode 100644 app/javascript/mastodon/components/image.jsx
create mode 100644 app/javascript/mastodon/components/image.tsx
diff --git a/app/javascript/mastodon/components/image.jsx b/app/javascript/mastodon/components/image.jsx
deleted file mode 100644
index 6e81ddf082..0000000000
--- a/app/javascript/mastodon/components/image.jsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import Blurhash from './blurhash';
-import classNames from 'classnames';
-
-export default class Image extends React.PureComponent {
-
- static propTypes = {
- src: PropTypes.string,
- srcSet: PropTypes.string,
- blurhash: PropTypes.string,
- className: PropTypes.string,
- };
-
- state = {
- loaded: false,
- };
-
- handleLoad = () => this.setState({ loaded: true });
-
- render () {
- const { src, srcSet, blurhash, className } = this.props;
- const { loaded } = this.state;
-
- return (
-
- {blurhash &&
}
-
-
- );
- }
-
-}
diff --git a/app/javascript/mastodon/components/image.tsx b/app/javascript/mastodon/components/image.tsx
new file mode 100644
index 0000000000..9b4d602255
--- /dev/null
+++ b/app/javascript/mastodon/components/image.tsx
@@ -0,0 +1,27 @@
+import React, { useCallback, useState } from 'react';
+import Blurhash from './blurhash';
+import classNames from 'classnames';
+
+type Props = {
+ src: string;
+ srcSet?: string;
+ blurhash?: string;
+ className?: string;
+}
+
+export const Image: React.FC = ({ src, srcSet, blurhash, className }) => {
+ const [loaded, setLoaded] = useState(false);
+
+ const handleLoad = useCallback(() => {
+ setLoaded(true);
+ }, [setLoaded]);
+
+ return (
+
+ {blurhash &&
}
+
+
+ );
+};
+
+export default Image;
From 76264e3fe86d1ac3c9f6d91290e77db8d9272d1a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=9F=E3=81=84=E3=81=A1=20=E3=81=B2?=
Date: Mon, 8 May 2023 18:12:53 +0900
Subject: [PATCH 5/9] Rewrite RadioButton component as FC (#24897)
---
.../mastodon/components/radio_button.jsx | 35 -------------------
.../mastodon/components/radio_button.tsx | 30 ++++++++++++++++
2 files changed, 30 insertions(+), 35 deletions(-)
delete mode 100644 app/javascript/mastodon/components/radio_button.jsx
create mode 100644 app/javascript/mastodon/components/radio_button.tsx
diff --git a/app/javascript/mastodon/components/radio_button.jsx b/app/javascript/mastodon/components/radio_button.jsx
deleted file mode 100644
index 0496fa2868..0000000000
--- a/app/javascript/mastodon/components/radio_button.jsx
+++ /dev/null
@@ -1,35 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import classNames from 'classnames';
-
-export default class RadioButton extends React.PureComponent {
-
- static propTypes = {
- value: PropTypes.string.isRequired,
- checked: PropTypes.bool,
- name: PropTypes.string.isRequired,
- onChange: PropTypes.func.isRequired,
- label: PropTypes.node.isRequired,
- };
-
- render () {
- const { name, value, checked, onChange, label } = this.props;
-
- return (
-
- );
- }
-
-}
diff --git a/app/javascript/mastodon/components/radio_button.tsx b/app/javascript/mastodon/components/radio_button.tsx
new file mode 100644
index 0000000000..9ba098f78d
--- /dev/null
+++ b/app/javascript/mastodon/components/radio_button.tsx
@@ -0,0 +1,30 @@
+import React from 'react';
+import classNames from 'classnames';
+
+type Props = {
+ value: string;
+ checked: boolean;
+ name: string;
+ onChange: (event: React.ChangeEvent) => void;
+ label: React.ReactNode;
+};
+
+export const RadioButton: React.FC = ({ name, value, checked, onChange, label }) => {
+ return (
+
+ );
+};
+
+export default RadioButton;
From 7c1305b3a4ce0ee39aa923a1f1ac604794265b0b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E3=81=9F=E3=81=84=E3=81=A1=20=E3=81=B2?=
Date: Mon, 8 May 2023 18:28:36 +0900
Subject: [PATCH 6/9] Add TypeScript support for `mastodon` alias and image
imports (#24895)
---
.../mastodon/components/hashtag.jsx | 2 --
app/javascript/types/image.d.ts | 34 +++++++++++++++++++
tsconfig.json | 13 +++++--
3 files changed, 45 insertions(+), 4 deletions(-)
create mode 100644 app/javascript/types/image.d.ts
diff --git a/app/javascript/mastodon/components/hashtag.jsx b/app/javascript/mastodon/components/hashtag.jsx
index 254fae2fe0..d03b1a45a7 100644
--- a/app/javascript/mastodon/components/hashtag.jsx
+++ b/app/javascript/mastodon/components/hashtag.jsx
@@ -5,9 +5,7 @@ import { FormattedMessage } from 'react-intl';
import PropTypes from 'prop-types';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { Link } from 'react-router-dom';
-// @ts-expect-error
import ShortNumber from 'mastodon/components/short_number';
-// @ts-expect-error
import Skeleton from 'mastodon/components/skeleton';
import classNames from 'classnames';
diff --git a/app/javascript/types/image.d.ts b/app/javascript/types/image.d.ts
new file mode 100644
index 0000000000..8bd6ab0286
--- /dev/null
+++ b/app/javascript/types/image.d.ts
@@ -0,0 +1,34 @@
+declare module '*.avif' {
+ const path: string;
+ export default path;
+}
+
+declare module '*.gif' {
+ const path: string;
+ export default path;
+}
+
+declare module '*.jpg' {
+ const path: string;
+ export default path;
+}
+
+declare module '*.jpg' {
+ const path: string;
+ export default path;
+}
+
+declare module '*.png' {
+ const path: string;
+ export default path;
+}
+
+declare module '*.svg' {
+ const path: string;
+ export default path;
+}
+
+declare module '*.webp' {
+ const path: string;
+ export default path;
+}
diff --git a/tsconfig.json b/tsconfig.json
index 505b19d89b..09cea2a75f 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -7,7 +7,16 @@
"noEmit": true,
"strict": true,
"esModuleInterop": true,
- "skipLibCheck": true
+ "skipLibCheck": true,
+ "baseUrl": "./",
+ "paths": {
+ "mastodon": ["app/javascript/mastodon"],
+ "mastodon/*": ["app/javascript/mastodon/*"]
+ }
},
- "include": ["app/javascript/mastodon", "app/javascript/packs"]
+ "include": [
+ "app/javascript/mastodon",
+ "app/javascript/packs",
+ "app/javascript/types"
+ ]
}
From 5bc8e2d1fdc3f1b1a0b9af5aed762d44e048250c Mon Sep 17 00:00:00 2001
From: fusagiko / takayamaki <24884114+takayamaki@users.noreply.github.com>
Date: Mon, 8 May 2023 22:10:21 +0900
Subject: [PATCH 7/9] Use LayoutType from is_mobile in actions/app (#24863)
---
app/javascript/mastodon/actions/app.ts | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/app/javascript/mastodon/actions/app.ts b/app/javascript/mastodon/actions/app.ts
index 0acfbfae7a..50fd317a65 100644
--- a/app/javascript/mastodon/actions/app.ts
+++ b/app/javascript/mastodon/actions/app.ts
@@ -1,10 +1,11 @@
import { createAction } from '@reduxjs/toolkit';
+import type { LayoutType } from '../is_mobile';
export const focusApp = createAction('APP_FOCUS');
export const unfocusApp = createAction('APP_UNFOCUS');
type ChangeLayoutPayload = {
- layout: 'mobile' | 'single-column' | 'multi-column';
+ layout: LayoutType;
};
export const changeLayout =
createAction('APP_LAYOUT_CHANGE');
From 9818f342735d1765baa281aaeeab2f60b8d049fe Mon Sep 17 00:00:00 2001
From: fusagiko / takayamaki <24884114+takayamaki@users.noreply.github.com>
Date: Mon, 8 May 2023 22:12:12 +0900
Subject: [PATCH 8/9] Rewrite Domain component as function component (#24896)
---
app/javascript/mastodon/components/domain.jsx | 43 -------------------
app/javascript/mastodon/components/domain.tsx | 42 ++++++++++++++++++
.../mastodon/containers/domain_container.jsx | 2 +-
3 files changed, 43 insertions(+), 44 deletions(-)
delete mode 100644 app/javascript/mastodon/components/domain.jsx
create mode 100644 app/javascript/mastodon/components/domain.tsx
diff --git a/app/javascript/mastodon/components/domain.jsx b/app/javascript/mastodon/components/domain.jsx
deleted file mode 100644
index 85ebdbde93..0000000000
--- a/app/javascript/mastodon/components/domain.jsx
+++ /dev/null
@@ -1,43 +0,0 @@
-import React from 'react';
-import PropTypes from 'prop-types';
-import IconButton from './icon_button';
-import { defineMessages, injectIntl } from 'react-intl';
-import ImmutablePureComponent from 'react-immutable-pure-component';
-
-const messages = defineMessages({
- unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unblock domain {domain}' },
-});
-
-class Account extends ImmutablePureComponent {
-
- static propTypes = {
- domain: PropTypes.string,
- onUnblockDomain: PropTypes.func.isRequired,
- intl: PropTypes.object.isRequired,
- };
-
- handleDomainUnblock = () => {
- this.props.onUnblockDomain(this.props.domain);
- };
-
- render () {
- const { domain, intl } = this.props;
-
- return (
-
- );
- }
-
-}
-
-export default injectIntl(Account);
diff --git a/app/javascript/mastodon/components/domain.tsx b/app/javascript/mastodon/components/domain.tsx
new file mode 100644
index 0000000000..6cb8f7b8ff
--- /dev/null
+++ b/app/javascript/mastodon/components/domain.tsx
@@ -0,0 +1,42 @@
+import React, { useCallback } from 'react';
+import IconButton from './icon_button';
+import { InjectedIntl, defineMessages, injectIntl } from 'react-intl';
+
+const messages = defineMessages({
+ unblockDomain: {
+ id: 'account.unblock_domain',
+ defaultMessage: 'Unblock domain {domain}',
+ },
+});
+
+type Props = {
+ domain: string;
+ onUnblockDomain: (domain: string) => void;
+ intl: InjectedIntl;
+};
+const _Domain: React.FC = ({ domain, onUnblockDomain, intl }) => {
+ const handleDomainUnblock = useCallback(() => {
+ onUnblockDomain(domain);
+ }, [domain, onUnblockDomain]);
+
+ return (
+
+ );
+};
+
+export const Domain = injectIntl(_Domain);
diff --git a/app/javascript/mastodon/containers/domain_container.jsx b/app/javascript/mastodon/containers/domain_container.jsx
index 8a8ba1df12..419d5d29f5 100644
--- a/app/javascript/mastodon/containers/domain_container.jsx
+++ b/app/javascript/mastodon/containers/domain_container.jsx
@@ -2,7 +2,7 @@ import React from 'react';
import { connect } from 'react-redux';
import { blockDomain, unblockDomain } from '../actions/domain_blocks';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
-import Domain from '../components/domain';
+import { Domain } from '../components/domain';
import { openModal } from '../actions/modal';
const messages = defineMessages({
From 89269e4b713e3291a5c8c29b8d2e7b950b60eb35 Mon Sep 17 00:00:00 2001
From: Renaud Chaput
Date: Tue, 9 May 2023 03:07:13 +0200
Subject: [PATCH 9/9] Mark `wheel` events on scrollable list as passive
(#24914)
---
app/javascript/mastodon/components/scrollable_list.jsx | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/app/javascript/mastodon/components/scrollable_list.jsx b/app/javascript/mastodon/components/scrollable_list.jsx
index 57bc881218..3f4e4a59c6 100644
--- a/app/javascript/mastodon/components/scrollable_list.jsx
+++ b/app/javascript/mastodon/components/scrollable_list.jsx
@@ -8,6 +8,7 @@ import IntersectionObserverWrapper from '../features/ui/util/intersection_observ
import { throttle } from 'lodash';
import { List as ImmutableList } from 'immutable';
import classNames from 'classnames';
+import { supportsPassiveEvents } from 'detect-passive-events';
import { attachFullscreenListener, detachFullscreenListener, isFullscreen } from '../features/ui/util/fullscreen';
import LoadingIndicator from './loading_indicator';
import { connect } from 'react-redux';
@@ -236,10 +237,10 @@ class ScrollableList extends PureComponent {
attachScrollListener () {
if (this.props.bindToDocument) {
document.addEventListener('scroll', this.handleScroll);
- document.addEventListener('wheel', this.handleWheel);
+ document.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : undefined);
} else {
this.node.addEventListener('scroll', this.handleScroll);
- this.node.addEventListener('wheel', this.handleWheel);
+ this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : undefined);
}
}