diff --git a/.rubocop.yml b/.rubocop.yml
index bedd8f7850..a06621d660 100644
--- a/.rubocop.yml
+++ b/.rubocop.yml
@@ -103,6 +103,12 @@ Rails/Exit:
- 'config/boot.rb'
- 'lib/mastodon/cli/*.rb'
+# Reason: Conflicts with `Lint/UselessMethodDefinition` for inherited controller actions
+# https://docs.rubocop.org/rubocop-rails/cops_rails.html#railslexicallyscopedactionfilter
+Rails/LexicallyScopedActionFilter:
+ Exclude:
+ - 'app/controllers/auth/*'
+
Rails/SkipsModelValidations:
Exclude:
- 'db/*migrate/**/*'
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 98943d9c92..b9874e1202 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -64,13 +64,6 @@ Rails/HasAndBelongsToMany:
- 'app/models/status.rb'
- 'app/models/tag.rb'
-# Configuration parameters: Include.
-# Include: app/controllers/**/*.rb, app/mailers/**/*.rb
-Rails/LexicallyScopedActionFilter:
- Exclude:
- - 'app/controllers/auth/passwords_controller.rb'
- - 'app/controllers/auth/registrations_controller.rb'
-
Rails/OutputSafety:
Exclude:
- 'config/initializers/simple_form.rb'
diff --git a/app/javascript/__mocks__/svg.js b/app/javascript/__mocks__/svg.js
index e725dc2da6..762bc165d0 100644
--- a/app/javascript/__mocks__/svg.js
+++ b/app/javascript/__mocks__/svg.js
@@ -1,3 +1,3 @@
-// eslint-disable-next-line import/no-anonymous-default-export
-export default 'SvgrURL';
-export const ReactComponent = 'div';
+const ReactComponent = 'div';
+
+export default ReactComponent;
diff --git a/app/javascript/mastodon/components/attachment_list.jsx b/app/javascript/mastodon/components/attachment_list.jsx
index ebf092b83d..e912d515cd 100644
--- a/app/javascript/mastodon/components/attachment_list.jsx
+++ b/app/javascript/mastodon/components/attachment_list.jsx
@@ -7,7 +7,7 @@ import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as LinkIcon } from '@material-symbols/svg-600/outlined/link.svg';
+import LinkIcon from '@material-symbols/svg-600/outlined/link.svg?react';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/components/badge.jsx b/app/javascript/mastodon/components/badge.jsx
index 2f762fed5f..e716421710 100644
--- a/app/javascript/mastodon/components/badge.jsx
+++ b/app/javascript/mastodon/components/badge.jsx
@@ -2,9 +2,9 @@ import PropTypes from 'prop-types';
import { FormattedMessage } from 'react-intl';
-import { ReactComponent as GroupsIcon } from '@material-symbols/svg-600/outlined/group.svg';
-import { ReactComponent as PersonIcon } from '@material-symbols/svg-600/outlined/person.svg';
-import { ReactComponent as SmartToyIcon } from '@material-symbols/svg-600/outlined/smart_toy.svg';
+import GroupsIcon from '@material-symbols/svg-600/outlined/group.svg?react';
+import PersonIcon from '@material-symbols/svg-600/outlined/person.svg?react';
+import SmartToyIcon from '@material-symbols/svg-600/outlined/smart_toy.svg?react';
export const Badge = ({ icon, label, domain }) => (
@@ -31,4 +31,4 @@ export const GroupBadge = () => (
export const AutomatedBadge = () => (
} label={} />
-);
\ No newline at end of file
+);
diff --git a/app/javascript/mastodon/components/column_back_button.tsx b/app/javascript/mastodon/components/column_back_button.tsx
index b835e9e6ad..7a23c4e108 100644
--- a/app/javascript/mastodon/components/column_back_button.tsx
+++ b/app/javascript/mastodon/components/column_back_button.tsx
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
import { FormattedMessage } from 'react-intl';
-import { ReactComponent as ArrowBackIcon } from '@material-symbols/svg-600/outlined/arrow_back.svg';
+import ArrowBackIcon from '@material-symbols/svg-600/outlined/arrow_back.svg?react';
import { Icon } from 'mastodon/components/icon';
import { ButtonInTabsBar } from 'mastodon/features/ui/util/columns_context';
diff --git a/app/javascript/mastodon/components/column_header.jsx b/app/javascript/mastodon/components/column_header.jsx
index b78bd9a8ef..a0ce10bf17 100644
--- a/app/javascript/mastodon/components/column_header.jsx
+++ b/app/javascript/mastodon/components/column_header.jsx
@@ -6,12 +6,12 @@ import { FormattedMessage, injectIntl, defineMessages } from 'react-intl';
import classNames from 'classnames';
import { withRouter } from 'react-router-dom';
-import { ReactComponent as AddIcon } from '@material-symbols/svg-600/outlined/add.svg';
-import { ReactComponent as ArrowBackIcon } from '@material-symbols/svg-600/outlined/arrow_back.svg';
-import { ReactComponent as ChevronLeftIcon } from '@material-symbols/svg-600/outlined/chevron_left.svg';
-import { ReactComponent as ChevronRightIcon } from '@material-symbols/svg-600/outlined/chevron_right.svg';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
-import { ReactComponent as TuneIcon } from '@material-symbols/svg-600/outlined/tune.svg';
+import AddIcon from '@material-symbols/svg-600/outlined/add.svg?react';
+import ArrowBackIcon from '@material-symbols/svg-600/outlined/arrow_back.svg?react';
+import ChevronLeftIcon from '@material-symbols/svg-600/outlined/chevron_left.svg?react';
+import ChevronRightIcon from '@material-symbols/svg-600/outlined/chevron_right.svg?react';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
+import TuneIcon from '@material-symbols/svg-600/outlined/tune.svg?react';
import { Icon } from 'mastodon/components/icon';
import { ButtonInTabsBar, useColumnsContext } from 'mastodon/features/ui/util/columns_context';
diff --git a/app/javascript/mastodon/components/copy_icon_button.jsx b/app/javascript/mastodon/components/copy_icon_button.jsx
index 9b1a36d83a..0c250a7632 100644
--- a/app/javascript/mastodon/components/copy_icon_button.jsx
+++ b/app/javascript/mastodon/components/copy_icon_button.jsx
@@ -7,7 +7,7 @@ import classNames from 'classnames';
import { useDispatch } from 'react-redux';
-import { ReactComponent as ContentCopyIcon } from '@material-symbols/svg-600/outlined/content_copy.svg';
+import ContentCopyIcon from '@material-symbols/svg-600/outlined/content_copy.svg?react';
import { showAlert } from 'mastodon/actions/alerts';
import { IconButton } from 'mastodon/components/icon_button';
diff --git a/app/javascript/mastodon/components/dismissable_banner.tsx b/app/javascript/mastodon/components/dismissable_banner.tsx
index 4e6d3bb9a7..c35fec983d 100644
--- a/app/javascript/mastodon/components/dismissable_banner.tsx
+++ b/app/javascript/mastodon/components/dismissable_banner.tsx
@@ -8,7 +8,7 @@ import { useCallback, useState, useEffect } from 'react';
import { defineMessages, useIntl } from 'react-intl';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import { changeSetting } from 'mastodon/actions/settings';
import { bannerSettings } from 'mastodon/settings';
diff --git a/app/javascript/mastodon/components/domain.tsx b/app/javascript/mastodon/components/domain.tsx
index 34c376f530..26cc77604e 100644
--- a/app/javascript/mastodon/components/domain.tsx
+++ b/app/javascript/mastodon/components/domain.tsx
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
import { defineMessages, useIntl } from 'react-intl';
-import { ReactComponent as LockOpenIcon } from '@material-symbols/svg-600/outlined/lock_open.svg';
+import LockOpenIcon from '@material-symbols/svg-600/outlined/lock_open.svg?react';
import { IconButton } from './icon_button';
diff --git a/app/javascript/mastodon/components/dropdown_menu.jsx b/app/javascript/mastodon/components/dropdown_menu.jsx
index d9cbcc32e5..1cb5c03150 100644
--- a/app/javascript/mastodon/components/dropdown_menu.jsx
+++ b/app/javascript/mastodon/components/dropdown_menu.jsx
@@ -6,7 +6,7 @@ import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import { supportsPassiveEvents } from 'detect-passive-events';
import Overlay from 'react-overlays/Overlay';
diff --git a/app/javascript/mastodon/components/edited_timestamp/index.jsx b/app/javascript/mastodon/components/edited_timestamp/index.jsx
index 4375166bcd..de4c641cfb 100644
--- a/app/javascript/mastodon/components/edited_timestamp/index.jsx
+++ b/app/javascript/mastodon/components/edited_timestamp/index.jsx
@@ -5,7 +5,7 @@ import { FormattedMessage, injectIntl } from 'react-intl';
import { connect } from 'react-redux';
-import { ReactComponent as ArrowDropDownIcon } from '@material-symbols/svg-600/outlined/arrow_drop_down.svg';
+import ArrowDropDownIcon from '@material-symbols/svg-600/outlined/arrow_drop_down.svg?react';
import { openModal } from 'mastodon/actions/modal';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/components/icon.tsx b/app/javascript/mastodon/components/icon.tsx
index f0af11f7f6..4b17f063b9 100644
--- a/app/javascript/mastodon/components/icon.tsx
+++ b/app/javascript/mastodon/components/icon.tsx
@@ -1,6 +1,6 @@
import classNames from 'classnames';
-import { ReactComponent as CheckBoxOutlineBlankIcon } from '@material-symbols/svg-600/outlined/check_box_outline_blank.svg';
+import CheckBoxOutlineBlankIcon from '@material-symbols/svg-600/outlined/check_box_outline_blank.svg?react';
import { isProduction } from 'mastodon/utils/environment';
diff --git a/app/javascript/mastodon/components/load_gap.tsx b/app/javascript/mastodon/components/load_gap.tsx
index 27ca6648c3..ea97c3eb57 100644
--- a/app/javascript/mastodon/components/load_gap.tsx
+++ b/app/javascript/mastodon/components/load_gap.tsx
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
import { useIntl, defineMessages } from 'react-intl';
-import { ReactComponent as MoreHorizIcon } from '@material-symbols/svg-600/outlined/more_horiz.svg';
+import MoreHorizIcon from '@material-symbols/svg-600/outlined/more_horiz.svg?react';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/components/media_gallery.jsx b/app/javascript/mastodon/components/media_gallery.jsx
index 668c2a2a8a..72daeea5a0 100644
--- a/app/javascript/mastodon/components/media_gallery.jsx
+++ b/app/javascript/mastodon/components/media_gallery.jsx
@@ -8,7 +8,7 @@ import classNames from 'classnames';
import { is } from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
-import { ReactComponent as VisibilityOffIcon } from '@material-symbols/svg-600/outlined/visibility_off.svg';
+import VisibilityOffIcon from '@material-symbols/svg-600/outlined/visibility_off.svg?react';
import { debounce } from 'lodash';
import { Blurhash } from 'mastodon/components/blurhash';
diff --git a/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx b/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx
index 08a599cd42..3ce5ea5a74 100644
--- a/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx
+++ b/app/javascript/mastodon/components/picture_in_picture_placeholder.jsx
@@ -5,7 +5,7 @@ import { FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
-import { ReactComponent as CancelPresentationIcon } from '@material-symbols/svg-600/outlined/cancel_presentation.svg';
+import CancelPresentationIcon from '@material-symbols/svg-600/outlined/cancel_presentation.svg?react';
import { removePictureInPicture } from 'mastodon/actions/picture_in_picture';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/components/poll.jsx b/app/javascript/mastodon/components/poll.jsx
index 7cf2c57b78..b8f6446409 100644
--- a/app/javascript/mastodon/components/poll.jsx
+++ b/app/javascript/mastodon/components/poll.jsx
@@ -7,7 +7,7 @@ import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as CheckIcon } from '@material-symbols/svg-600/outlined/check.svg';
+import CheckIcon from '@material-symbols/svg-600/outlined/check.svg?react';
import escapeTextContentForBrowser from 'escape-html';
import spring from 'react-motion/lib/spring';
diff --git a/app/javascript/mastodon/components/status.jsx b/app/javascript/mastodon/components/status.jsx
index c141ee2da3..f1ea369610 100644
--- a/app/javascript/mastodon/components/status.jsx
+++ b/app/javascript/mastodon/components/status.jsx
@@ -7,10 +7,10 @@ import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as AlternateEmailIcon } from '@material-symbols/svg-600/outlined/alternate_email.svg';
-import { ReactComponent as PushPinIcon } from '@material-symbols/svg-600/outlined/push_pin.svg';
-import { ReactComponent as RepeatIcon } from '@material-symbols/svg-600/outlined/repeat.svg';
-import { ReactComponent as ReplyIcon } from '@material-symbols/svg-600/outlined/reply.svg';
+import AlternateEmailIcon from '@material-symbols/svg-600/outlined/alternate_email.svg?react';
+import PushPinIcon from '@material-symbols/svg-600/outlined/push_pin.svg?react';
+import RepeatIcon from '@material-symbols/svg-600/outlined/repeat.svg?react';
+import ReplyIcon from '@material-symbols/svg-600/outlined/reply.svg?react';
import { HotKeys } from 'react-hotkeys';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/components/status_action_bar.jsx b/app/javascript/mastodon/components/status_action_bar.jsx
index 25eab91fe3..536ea350ae 100644
--- a/app/javascript/mastodon/components/status_action_bar.jsx
+++ b/app/javascript/mastodon/components/status_action_bar.jsx
@@ -9,18 +9,18 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as BookmarkIcon } from '@material-symbols/svg-600/outlined/bookmark-fill.svg';
-import { ReactComponent as BookmarkBorderIcon } from '@material-symbols/svg-600/outlined/bookmark.svg';
-import { ReactComponent as MoreHorizIcon } from '@material-symbols/svg-600/outlined/more_horiz.svg';
-import { ReactComponent as RepeatIcon } from '@material-symbols/svg-600/outlined/repeat.svg';
-import { ReactComponent as ReplyIcon } from '@material-symbols/svg-600/outlined/reply.svg';
-import { ReactComponent as ReplyAllIcon } from '@material-symbols/svg-600/outlined/reply_all.svg';
-import { ReactComponent as StarIcon } from '@material-symbols/svg-600/outlined/star-fill.svg';
-import { ReactComponent as StarBorderIcon } from '@material-symbols/svg-600/outlined/star.svg';
-import { ReactComponent as VisibilityIcon } from '@material-symbols/svg-600/outlined/visibility.svg';
+import BookmarkIcon from '@material-symbols/svg-600/outlined/bookmark-fill.svg';
+import BookmarkBorderIcon from '@material-symbols/svg-600/outlined/bookmark.svg?react';
+import MoreHorizIcon from '@material-symbols/svg-600/outlined/more_horiz.svg?react';
+import RepeatIcon from '@material-symbols/svg-600/outlined/repeat.svg?react';
+import ReplyIcon from '@material-symbols/svg-600/outlined/reply.svg?react';
+import ReplyAllIcon from '@material-symbols/svg-600/outlined/reply_all.svg?react';
+import StarIcon from '@material-symbols/svg-600/outlined/star-fill.svg?react';
+import StarBorderIcon from '@material-symbols/svg-600/outlined/star.svg?react';
+import VisibilityIcon from '@material-symbols/svg-600/outlined/visibility.svg?react';
-import { ReactComponent as RepeatDisabledIcon } from 'mastodon/../svg-icons/repeat_disabled.svg';
-import { ReactComponent as RepeatPrivateIcon } from 'mastodon/../svg-icons/repeat_private.svg';
+import RepeatDisabledIcon from 'mastodon/../svg-icons/repeat_disabled.svg?react';
+import RepeatPrivateIcon from 'mastodon/../svg-icons/repeat_private.svg?react';
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
diff --git a/app/javascript/mastodon/components/status_content.jsx b/app/javascript/mastodon/components/status_content.jsx
index d1f50fc8d7..f8ca0b3043 100644
--- a/app/javascript/mastodon/components/status_content.jsx
+++ b/app/javascript/mastodon/components/status_content.jsx
@@ -9,7 +9,7 @@ import { Link, withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
-import { ReactComponent as ChevronRightIcon } from '@material-symbols/svg-600/outlined/chevron_right.svg';
+import ChevronRightIcon from '@material-symbols/svg-600/outlined/chevron_right.svg?react';
import { Icon } from 'mastodon/components/icon';
import PollContainer from 'mastodon/containers/poll_container';
diff --git a/app/javascript/mastodon/components/verified_badge.tsx b/app/javascript/mastodon/components/verified_badge.tsx
index e96bf82563..add7c7acdf 100644
--- a/app/javascript/mastodon/components/verified_badge.tsx
+++ b/app/javascript/mastodon/components/verified_badge.tsx
@@ -1,4 +1,4 @@
-import { ReactComponent as CheckIcon } from '@material-symbols/svg-600/outlined/check.svg';
+import CheckIcon from '@material-symbols/svg-600/outlined/check.svg?react';
import { Icon } from './icon';
diff --git a/app/javascript/mastodon/components/visibility_icon.tsx b/app/javascript/mastodon/components/visibility_icon.tsx
index 3e9f36dc70..e0ef1372f1 100644
--- a/app/javascript/mastodon/components/visibility_icon.tsx
+++ b/app/javascript/mastodon/components/visibility_icon.tsx
@@ -1,9 +1,9 @@
import { defineMessages, useIntl } from 'react-intl';
-import { ReactComponent as AlternateEmailIcon } from '@material-symbols/svg-600/outlined/alternate_email.svg';
-import { ReactComponent as LockIcon } from '@material-symbols/svg-600/outlined/lock.svg';
-import { ReactComponent as LockOpenIcon } from '@material-symbols/svg-600/outlined/lock_open.svg';
-import { ReactComponent as PublicIcon } from '@material-symbols/svg-600/outlined/public.svg';
+import AlternateEmailIcon from '@material-symbols/svg-600/outlined/alternate_email.svg?react';
+import LockIcon from '@material-symbols/svg-600/outlined/lock.svg?react';
+import LockOpenIcon from '@material-symbols/svg-600/outlined/lock_open.svg?react';
+import PublicIcon from '@material-symbols/svg-600/outlined/public.svg?react';
import { Icon } from './icon';
diff --git a/app/javascript/mastodon/features/about/index.jsx b/app/javascript/mastodon/features/about/index.jsx
index 380942b8ee..1e43aaea7b 100644
--- a/app/javascript/mastodon/features/about/index.jsx
+++ b/app/javascript/mastodon/features/about/index.jsx
@@ -10,8 +10,8 @@ import { List as ImmutableList } from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
-import { ReactComponent as ChevronRightIcon } from '@material-symbols/svg-600/outlined/chevron_right.svg';
-import { ReactComponent as ExpandMoreIcon } from '@material-symbols/svg-600/outlined/expand_more.svg';
+import ChevronRightIcon from '@material-symbols/svg-600/outlined/chevron_right.svg?react';
+import ExpandMoreIcon from '@material-symbols/svg-600/outlined/expand_more.svg?react';
import { fetchServer, fetchExtendedDescription, fetchDomainBlocks } from 'mastodon/actions/server';
import Column from 'mastodon/components/column';
diff --git a/app/javascript/mastodon/features/account/components/follow_request_note.jsx b/app/javascript/mastodon/features/account/components/follow_request_note.jsx
index 685c282df2..da775248ce 100644
--- a/app/javascript/mastodon/features/account/components/follow_request_note.jsx
+++ b/app/javascript/mastodon/features/account/components/follow_request_note.jsx
@@ -3,8 +3,8 @@ import { FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as CheckIcon } from '@material-symbols/svg-600/outlined/check.svg';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CheckIcon from '@material-symbols/svg-600/outlined/check.svg?react';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/account/components/header.jsx b/app/javascript/mastodon/features/account/components/header.jsx
index 97f68c2217..e8b5e72145 100644
--- a/app/javascript/mastodon/features/account/components/header.jsx
+++ b/app/javascript/mastodon/features/account/components/header.jsx
@@ -9,12 +9,12 @@ import { NavLink, withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as CheckIcon } from '@material-symbols/svg-600/outlined/check.svg';
-import { ReactComponent as LockIcon } from '@material-symbols/svg-600/outlined/lock.svg';
-import { ReactComponent as MoreHorizIcon } from '@material-symbols/svg-600/outlined/more_horiz.svg';
-import { ReactComponent as NotificationsIcon } from '@material-symbols/svg-600/outlined/notifications.svg';
-import { ReactComponent as NotificationsActiveIcon } from '@material-symbols/svg-600/outlined/notifications_active-fill.svg';
-import { ReactComponent as ShareIcon } from '@material-symbols/svg-600/outlined/share.svg';
+import CheckIcon from '@material-symbols/svg-600/outlined/check.svg?react';
+import LockIcon from '@material-symbols/svg-600/outlined/lock.svg?react';
+import MoreHorizIcon from '@material-symbols/svg-600/outlined/more_horiz.svg?react';
+import NotificationsIcon from '@material-symbols/svg-600/outlined/notifications.svg?react';
+import NotificationsActiveIcon from '@material-symbols/svg-600/outlined/notifications_active-fill.svg?react';
+import ShareIcon from '@material-symbols/svg-600/outlined/share.svg?react';
import { Avatar } from 'mastodon/components/avatar';
import { Badge, AutomatedBadge, GroupBadge } from 'mastodon/components/badge';
diff --git a/app/javascript/mastodon/features/account_gallery/components/media_item.jsx b/app/javascript/mastodon/features/account_gallery/components/media_item.jsx
index 657b17d43d..e4495601f5 100644
--- a/app/javascript/mastodon/features/account_gallery/components/media_item.jsx
+++ b/app/javascript/mastodon/features/account_gallery/components/media_item.jsx
@@ -5,9 +5,9 @@ import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as AudiotrackIcon } from '@material-symbols/svg-600/outlined/music_note.svg';
-import { ReactComponent as PlayArrowIcon } from '@material-symbols/svg-600/outlined/play_arrow.svg';
-import { ReactComponent as VisibilityOffIcon } from '@material-symbols/svg-600/outlined/visibility_off.svg';
+import AudiotrackIcon from '@material-symbols/svg-600/outlined/music_note.svg?react';
+import PlayArrowIcon from '@material-symbols/svg-600/outlined/play_arrow.svg?react';
+import VisibilityOffIcon from '@material-symbols/svg-600/outlined/visibility_off.svg?react';
import { Blurhash } from 'mastodon/components/blurhash';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/audio/index.jsx b/app/javascript/mastodon/features/audio/index.jsx
index 7a7d0910fa..881e5cef1b 100644
--- a/app/javascript/mastodon/features/audio/index.jsx
+++ b/app/javascript/mastodon/features/audio/index.jsx
@@ -7,12 +7,12 @@ import classNames from 'classnames';
import { is } from 'immutable';
-import { ReactComponent as DownloadIcon } from '@material-symbols/svg-600/outlined/download.svg';
-import { ReactComponent as PauseIcon } from '@material-symbols/svg-600/outlined/pause.svg';
-import { ReactComponent as PlayArrowIcon } from '@material-symbols/svg-600/outlined/play_arrow-fill.svg';
-import { ReactComponent as VisibilityOffIcon } from '@material-symbols/svg-600/outlined/visibility_off.svg';
-import { ReactComponent as VolumeOffIcon } from '@material-symbols/svg-600/outlined/volume_off-fill.svg';
-import { ReactComponent as VolumeUpIcon } from '@material-symbols/svg-600/outlined/volume_up-fill.svg';
+import DownloadIcon from '@material-symbols/svg-600/outlined/download.svg?react';
+import PauseIcon from '@material-symbols/svg-600/outlined/pause.svg?react';
+import PlayArrowIcon from '@material-symbols/svg-600/outlined/play_arrow-fill.svg?react';
+import VisibilityOffIcon from '@material-symbols/svg-600/outlined/visibility_off.svg?react';
+import VolumeOffIcon from '@material-symbols/svg-600/outlined/volume_off-fill.svg?react';
+import VolumeUpIcon from '@material-symbols/svg-600/outlined/volume_up-fill.svg?react';
import { throttle, debounce } from 'lodash';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/blocks/index.jsx b/app/javascript/mastodon/features/blocks/index.jsx
index 615e4c8be2..7e1eda8aca 100644
--- a/app/javascript/mastodon/features/blocks/index.jsx
+++ b/app/javascript/mastodon/features/blocks/index.jsx
@@ -6,7 +6,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as BlockIcon } from '@material-symbols/svg-600/outlined/block-fill.svg';
+import BlockIcon from '@material-symbols/svg-600/outlined/block-fill.svg?react';
import { debounce } from 'lodash';
import { fetchBlocks, expandBlocks } from '../../actions/blocks';
diff --git a/app/javascript/mastodon/features/bookmarked_statuses/index.jsx b/app/javascript/mastodon/features/bookmarked_statuses/index.jsx
index be6110b0da..767707755b 100644
--- a/app/javascript/mastodon/features/bookmarked_statuses/index.jsx
+++ b/app/javascript/mastodon/features/bookmarked_statuses/index.jsx
@@ -8,7 +8,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as BookmarksIcon } from '@material-symbols/svg-600/outlined/bookmarks-fill.svg';
+import BookmarksIcon from '@material-symbols/svg-600/outlined/bookmarks-fill.svg?react';
import { debounce } from 'lodash';
import { fetchBookmarkedStatuses, expandBookmarkedStatuses } from 'mastodon/actions/bookmarks';
diff --git a/app/javascript/mastodon/features/community_timeline/index.jsx b/app/javascript/mastodon/features/community_timeline/index.jsx
index 60f036a628..1862cdf902 100644
--- a/app/javascript/mastodon/features/community_timeline/index.jsx
+++ b/app/javascript/mastodon/features/community_timeline/index.jsx
@@ -7,7 +7,7 @@ import { Helmet } from 'react-helmet';
import { connect } from 'react-redux';
-import { ReactComponent as PeopleIcon } from '@material-symbols/svg-600/outlined/group.svg';
+import PeopleIcon from '@material-symbols/svg-600/outlined/group.svg?react';
import { DismissableBanner } from 'mastodon/components/dismissable_banner';
import { domain } from 'mastodon/initial_state';
diff --git a/app/javascript/mastodon/features/compose/components/action_bar.jsx b/app/javascript/mastodon/features/compose/components/action_bar.jsx
index 3e21090925..42ed78578a 100644
--- a/app/javascript/mastodon/features/compose/components/action_bar.jsx
+++ b/app/javascript/mastodon/features/compose/components/action_bar.jsx
@@ -5,7 +5,7 @@ import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
-import { ReactComponent as MenuIcon } from '@material-symbols/svg-600/outlined/menu.svg';
+import MenuIcon from '@material-symbols/svg-600/outlined/menu.svg?react';
import DropdownMenuContainer from '../../../containers/dropdown_menu_container';
diff --git a/app/javascript/mastodon/features/compose/components/compose_form.jsx b/app/javascript/mastodon/features/compose/components/compose_form.jsx
index 3b752f252d..3f203ed0c2 100644
--- a/app/javascript/mastodon/features/compose/components/compose_form.jsx
+++ b/app/javascript/mastodon/features/compose/components/compose_form.jsx
@@ -8,7 +8,7 @@ import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as LockIcon } from '@material-symbols/svg-600/outlined/lock.svg';
+import LockIcon from '@material-symbols/svg-600/outlined/lock.svg?react';
import { length } from 'stringz';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/compose/components/poll_button.jsx b/app/javascript/mastodon/features/compose/components/poll_button.jsx
index f722815b51..a5025a0f40 100644
--- a/app/javascript/mastodon/features/compose/components/poll_button.jsx
+++ b/app/javascript/mastodon/features/compose/components/poll_button.jsx
@@ -3,7 +3,7 @@ import { PureComponent } from 'react';
import { defineMessages, injectIntl } from 'react-intl';
-import { ReactComponent as InsertChartIcon } from '@material-symbols/svg-600/outlined/insert_chart.svg';
+import InsertChartIcon from '@material-symbols/svg-600/outlined/insert_chart.svg?react';
import { IconButton } from '../../../components/icon_button';
diff --git a/app/javascript/mastodon/features/compose/components/poll_form.jsx b/app/javascript/mastodon/features/compose/components/poll_form.jsx
index a7f933ff7c..04512da356 100644
--- a/app/javascript/mastodon/features/compose/components/poll_form.jsx
+++ b/app/javascript/mastodon/features/compose/components/poll_form.jsx
@@ -8,8 +8,8 @@ import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as AddIcon } from '@material-symbols/svg-600/outlined/add.svg';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import AddIcon from '@material-symbols/svg-600/outlined/add.svg?react';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import AutosuggestInput from 'mastodon/components/autosuggest_input';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx b/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx
index 060eb6767c..0dbbcbc256 100644
--- a/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx
+++ b/app/javascript/mastodon/features/compose/components/privacy_dropdown.jsx
@@ -6,10 +6,10 @@ import { injectIntl, defineMessages } from 'react-intl';
import classNames from 'classnames';
-import { ReactComponent as AlternateEmailIcon } from '@material-symbols/svg-600/outlined/alternate_email.svg';
-import { ReactComponent as LockIcon } from '@material-symbols/svg-600/outlined/lock.svg';
-import { ReactComponent as LockOpenIcon } from '@material-symbols/svg-600/outlined/lock_open.svg';
-import { ReactComponent as PublicIcon } from '@material-symbols/svg-600/outlined/public.svg';
+import AlternateEmailIcon from '@material-symbols/svg-600/outlined/alternate_email.svg?react';
+import LockIcon from '@material-symbols/svg-600/outlined/lock.svg?react';
+import LockOpenIcon from '@material-symbols/svg-600/outlined/lock_open.svg?react';
+import PublicIcon from '@material-symbols/svg-600/outlined/public.svg?react';
import { supportsPassiveEvents } from 'detect-passive-events';
import Overlay from 'react-overlays/Overlay';
diff --git a/app/javascript/mastodon/features/compose/components/reply_indicator.jsx b/app/javascript/mastodon/features/compose/components/reply_indicator.jsx
index af7a9b6be5..40e79cafaa 100644
--- a/app/javascript/mastodon/features/compose/components/reply_indicator.jsx
+++ b/app/javascript/mastodon/features/compose/components/reply_indicator.jsx
@@ -5,7 +5,7 @@ import { defineMessages, injectIntl } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import AttachmentList from 'mastodon/components/attachment_list';
import { WithOptionalRouterPropTypes, withOptionalRouter } from 'mastodon/utils/react_router';
diff --git a/app/javascript/mastodon/features/compose/components/search.jsx b/app/javascript/mastodon/features/compose/components/search.jsx
index 5d55330dcb..8dbbb0383d 100644
--- a/app/javascript/mastodon/features/compose/components/search.jsx
+++ b/app/javascript/mastodon/features/compose/components/search.jsx
@@ -8,9 +8,9 @@ import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
-import { ReactComponent as CancelIcon } from '@material-symbols/svg-600/outlined/cancel-fill.svg';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
-import { ReactComponent as SearchIcon } from '@material-symbols/svg-600/outlined/search.svg';
+import CancelIcon from '@material-symbols/svg-600/outlined/cancel-fill.svg?react';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
+import SearchIcon from '@material-symbols/svg-600/outlined/search.svg?react';
import { Icon } from 'mastodon/components/icon';
import { domain, searchEnabled } from 'mastodon/initial_state';
diff --git a/app/javascript/mastodon/features/compose/components/search_results.jsx b/app/javascript/mastodon/features/compose/components/search_results.jsx
index 2667ed5437..00d4dc5329 100644
--- a/app/javascript/mastodon/features/compose/components/search_results.jsx
+++ b/app/javascript/mastodon/features/compose/components/search_results.jsx
@@ -5,10 +5,10 @@ import { FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as FindInPageIcon } from '@material-symbols/svg-600/outlined/find_in_page.svg';
-import { ReactComponent as PeopleIcon } from '@material-symbols/svg-600/outlined/group.svg';
-import { ReactComponent as SearchIcon } from '@material-symbols/svg-600/outlined/search.svg';
-import { ReactComponent as TagIcon } from '@material-symbols/svg-600/outlined/tag.svg';
+import FindInPageIcon from '@material-symbols/svg-600/outlined/find_in_page.svg?react';
+import PeopleIcon from '@material-symbols/svg-600/outlined/group.svg?react';
+import SearchIcon from '@material-symbols/svg-600/outlined/search.svg?react';
+import TagIcon from '@material-symbols/svg-600/outlined/tag.svg?react';
import { Icon } from 'mastodon/components/icon';
import { LoadMore } from 'mastodon/components/load_more';
diff --git a/app/javascript/mastodon/features/compose/components/upload.jsx b/app/javascript/mastodon/features/compose/components/upload.jsx
index a443741d5c..88d6f68b54 100644
--- a/app/javascript/mastodon/features/compose/components/upload.jsx
+++ b/app/javascript/mastodon/features/compose/components/upload.jsx
@@ -5,9 +5,9 @@ import { FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
-import { ReactComponent as EditIcon } from '@material-symbols/svg-600/outlined/edit.svg';
-import { ReactComponent as InfoIcon } from '@material-symbols/svg-600/outlined/info.svg';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
+import EditIcon from '@material-symbols/svg-600/outlined/edit.svg?react';
+import InfoIcon from '@material-symbols/svg-600/outlined/info.svg?react';
import spring from 'react-motion/lib/spring';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/compose/components/upload_button.jsx b/app/javascript/mastodon/features/compose/components/upload_button.jsx
index dda8a42ab0..201b1b8983 100644
--- a/app/javascript/mastodon/features/compose/components/upload_button.jsx
+++ b/app/javascript/mastodon/features/compose/components/upload_button.jsx
@@ -6,7 +6,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as AddPhotoAlternateIcon } from '@material-symbols/svg-600/outlined/add_photo_alternate.svg';
+import AddPhotoAlternateIcon from '@material-symbols/svg-600/outlined/add_photo_alternate.svg?react';
import { IconButton } from '../../../components/icon_button';
diff --git a/app/javascript/mastodon/features/compose/components/upload_progress.jsx b/app/javascript/mastodon/features/compose/components/upload_progress.jsx
index 90c5142e24..2c44ac6364 100644
--- a/app/javascript/mastodon/features/compose/components/upload_progress.jsx
+++ b/app/javascript/mastodon/features/compose/components/upload_progress.jsx
@@ -3,7 +3,7 @@ import { PureComponent } from 'react';
import { FormattedMessage } from 'react-intl';
-import { ReactComponent as UploadFileIcon } from '@material-symbols/svg-600/outlined/upload_file.svg';
+import UploadFileIcon from '@material-symbols/svg-600/outlined/upload_file.svg?react';
import spring from 'react-motion/lib/spring';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/compose/index.jsx b/app/javascript/mastodon/features/compose/index.jsx
index 65650ffe02..0b9fa65fe1 100644
--- a/app/javascript/mastodon/features/compose/index.jsx
+++ b/app/javascript/mastodon/features/compose/index.jsx
@@ -9,13 +9,13 @@ import { Link } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
-import { ReactComponent as PeopleIcon } from '@material-symbols/svg-600/outlined/group.svg';
-import { ReactComponent as HomeIcon } from '@material-symbols/svg-600/outlined/home-fill.svg';
-import { ReactComponent as LogoutIcon } from '@material-symbols/svg-600/outlined/logout.svg';
-import { ReactComponent as MenuIcon } from '@material-symbols/svg-600/outlined/menu.svg';
-import { ReactComponent as NotificationsIcon } from '@material-symbols/svg-600/outlined/notifications-fill.svg';
-import { ReactComponent as PublicIcon } from '@material-symbols/svg-600/outlined/public.svg';
-import { ReactComponent as SettingsIcon } from '@material-symbols/svg-600/outlined/settings-fill.svg';
+import PeopleIcon from '@material-symbols/svg-600/outlined/group.svg?react';
+import HomeIcon from '@material-symbols/svg-600/outlined/home-fill.svg?react';
+import LogoutIcon from '@material-symbols/svg-600/outlined/logout.svg?react';
+import MenuIcon from '@material-symbols/svg-600/outlined/menu.svg?react';
+import NotificationsIcon from '@material-symbols/svg-600/outlined/notifications-fill.svg?react';
+import PublicIcon from '@material-symbols/svg-600/outlined/public.svg?react';
+import SettingsIcon from '@material-symbols/svg-600/outlined/settings-fill.svg?react';
import spring from 'react-motion/lib/spring';
import { openModal } from 'mastodon/actions/modal';
diff --git a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
index 005edc5c2b..0aeec1e3b0 100644
--- a/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
+++ b/app/javascript/mastodon/features/direct_timeline/components/conversation.jsx
@@ -8,8 +8,8 @@ import { Link, withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as MoreHorizIcon } from '@material-symbols/svg-600/outlined/more_horiz.svg';
-import { ReactComponent as ReplyIcon } from '@material-symbols/svg-600/outlined/reply.svg';
+import MoreHorizIcon from '@material-symbols/svg-600/outlined/more_horiz.svg?react';
+import ReplyIcon from '@material-symbols/svg-600/outlined/reply.svg?react';
import { HotKeys } from 'react-hotkeys';
import AttachmentList from 'mastodon/components/attachment_list';
diff --git a/app/javascript/mastodon/features/direct_timeline/index.jsx b/app/javascript/mastodon/features/direct_timeline/index.jsx
index 4e6d0c3e72..1a11520c3b 100644
--- a/app/javascript/mastodon/features/direct_timeline/index.jsx
+++ b/app/javascript/mastodon/features/direct_timeline/index.jsx
@@ -7,7 +7,7 @@ import { Helmet } from 'react-helmet';
import { connect } from 'react-redux';
-import { ReactComponent as AlternateEmailIcon } from '@material-symbols/svg-600/outlined/alternate_email.svg';
+import AlternateEmailIcon from '@material-symbols/svg-600/outlined/alternate_email.svg?react';
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
import { mountConversations, unmountConversations, expandConversations } from 'mastodon/actions/conversations';
diff --git a/app/javascript/mastodon/features/directory/index.jsx b/app/javascript/mastodon/features/directory/index.jsx
index 20c84d4df0..0de77164f5 100644
--- a/app/javascript/mastodon/features/directory/index.jsx
+++ b/app/javascript/mastodon/features/directory/index.jsx
@@ -9,7 +9,7 @@ import { List as ImmutableList } from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
-import { ReactComponent as PeopleIcon } from '@material-symbols/svg-600/outlined/group.svg';
+import PeopleIcon from '@material-symbols/svg-600/outlined/group.svg?react';
import { addColumn, removeColumn, moveColumn, changeColumnParams } from 'mastodon/actions/columns';
import { fetchDirectory, expandDirectory } from 'mastodon/actions/directory';
diff --git a/app/javascript/mastodon/features/domain_blocks/index.jsx b/app/javascript/mastodon/features/domain_blocks/index.jsx
index 142f14bf71..7a57ea1262 100644
--- a/app/javascript/mastodon/features/domain_blocks/index.jsx
+++ b/app/javascript/mastodon/features/domain_blocks/index.jsx
@@ -8,7 +8,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as BlockIcon } from '@material-symbols/svg-600/outlined/block-fill.svg';
+import BlockIcon from '@material-symbols/svg-600/outlined/block-fill.svg?react';
import { debounce } from 'lodash';
import { fetchDomainBlocks, expandDomainBlocks } from '../../actions/domain_blocks';
diff --git a/app/javascript/mastodon/features/explore/index.jsx b/app/javascript/mastodon/features/explore/index.jsx
index 80825e4563..a59830fb82 100644
--- a/app/javascript/mastodon/features/explore/index.jsx
+++ b/app/javascript/mastodon/features/explore/index.jsx
@@ -8,8 +8,8 @@ import { NavLink, Switch, Route } from 'react-router-dom';
import { connect } from 'react-redux';
-import { ReactComponent as SearchIcon } from '@material-symbols/svg-600/outlined/search.svg';
-import { ReactComponent as TagIcon } from '@material-symbols/svg-600/outlined/tag.svg';
+import SearchIcon from '@material-symbols/svg-600/outlined/search.svg?react';
+import TagIcon from '@material-symbols/svg-600/outlined/tag.svg?react';
import Column from 'mastodon/components/column';
import ColumnHeader from 'mastodon/components/column_header';
diff --git a/app/javascript/mastodon/features/explore/results.jsx b/app/javascript/mastodon/features/explore/results.jsx
index 8c172c134a..665f97f8ff 100644
--- a/app/javascript/mastodon/features/explore/results.jsx
+++ b/app/javascript/mastodon/features/explore/results.jsx
@@ -9,9 +9,9 @@ import { List as ImmutableList } from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
-import { ReactComponent as FindInPageIcon } from '@material-symbols/svg-600/outlined/find_in_page.svg';
-import { ReactComponent as PeopleIcon } from '@material-symbols/svg-600/outlined/group.svg';
-import { ReactComponent as TagIcon } from '@material-symbols/svg-600/outlined/tag.svg';
+import FindInPageIcon from '@material-symbols/svg-600/outlined/find_in_page.svg?react';
+import PeopleIcon from '@material-symbols/svg-600/outlined/group.svg?react';
+import TagIcon from '@material-symbols/svg-600/outlined/tag.svg?react';
import { submitSearch, expandSearch } from 'mastodon/actions/search';
import { ImmutableHashtag as Hashtag } from 'mastodon/components/hashtag';
diff --git a/app/javascript/mastodon/features/favourited_statuses/index.jsx b/app/javascript/mastodon/features/favourited_statuses/index.jsx
index d3c3cc9f09..d4716580d8 100644
--- a/app/javascript/mastodon/features/favourited_statuses/index.jsx
+++ b/app/javascript/mastodon/features/favourited_statuses/index.jsx
@@ -8,7 +8,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as StarIcon } from '@material-symbols/svg-600/outlined/star-fill.svg';
+import StarIcon from '@material-symbols/svg-600/outlined/star-fill.svg?react';
import { debounce } from 'lodash';
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
diff --git a/app/javascript/mastodon/features/favourites/index.jsx b/app/javascript/mastodon/features/favourites/index.jsx
index 637a9d6994..a26afda892 100644
--- a/app/javascript/mastodon/features/favourites/index.jsx
+++ b/app/javascript/mastodon/features/favourites/index.jsx
@@ -8,7 +8,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as RefreshIcon } from '@material-symbols/svg-600/outlined/refresh.svg';
+import RefreshIcon from '@material-symbols/svg-600/outlined/refresh.svg?react';
import { debounce } from 'lodash';
import { fetchFavourites, expandFavourites } from 'mastodon/actions/interactions';
diff --git a/app/javascript/mastodon/features/filters/select_filter.jsx b/app/javascript/mastodon/features/filters/select_filter.jsx
index 9e8f87e005..55f2a8c09f 100644
--- a/app/javascript/mastodon/features/filters/select_filter.jsx
+++ b/app/javascript/mastodon/features/filters/select_filter.jsx
@@ -5,7 +5,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
-import { ReactComponent as AddIcon } from '@material-symbols/svg-600/outlined/add.svg';
+import AddIcon from '@material-symbols/svg-600/outlined/add.svg?react';
import fuzzysort from 'fuzzysort';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/firehose/index.jsx b/app/javascript/mastodon/features/firehose/index.jsx
index 0ed8aa11aa..337b9a65b2 100644
--- a/app/javascript/mastodon/features/firehose/index.jsx
+++ b/app/javascript/mastodon/features/firehose/index.jsx
@@ -6,7 +6,7 @@ import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
import { Helmet } from 'react-helmet';
import { NavLink } from 'react-router-dom';
-import { ReactComponent as PublicIcon } from '@material-symbols/svg-600/outlined/public.svg';
+import PublicIcon from '@material-symbols/svg-600/outlined/public.svg?react';
import { addColumn } from 'mastodon/actions/columns';
import { changeSetting } from 'mastodon/actions/settings';
diff --git a/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx b/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx
index ca2b454143..ed61f2d841 100644
--- a/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx
+++ b/app/javascript/mastodon/features/follow_requests/components/account_authorize.jsx
@@ -7,8 +7,8 @@ import { Link } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as CheckIcon } from '@material-symbols/svg-600/outlined/check.svg';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CheckIcon from '@material-symbols/svg-600/outlined/check.svg?react';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import { Avatar } from '../../../components/avatar';
import { DisplayName } from '../../../components/display_name';
diff --git a/app/javascript/mastodon/features/follow_requests/index.jsx b/app/javascript/mastodon/features/follow_requests/index.jsx
index 3b98791926..9f73d09252 100644
--- a/app/javascript/mastodon/features/follow_requests/index.jsx
+++ b/app/javascript/mastodon/features/follow_requests/index.jsx
@@ -8,7 +8,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as PersonAddIcon } from '@material-symbols/svg-600/outlined/person_add.svg';
+import PersonAddIcon from '@material-symbols/svg-600/outlined/person_add.svg?react';
import { debounce } from 'lodash';
import { fetchFollowRequests, expandFollowRequests } from '../../actions/accounts';
diff --git a/app/javascript/mastodon/features/followed_tags/index.jsx b/app/javascript/mastodon/features/followed_tags/index.jsx
index dec53f0121..d4b26356b3 100644
--- a/app/javascript/mastodon/features/followed_tags/index.jsx
+++ b/app/javascript/mastodon/features/followed_tags/index.jsx
@@ -8,7 +8,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as TagIcon } from '@material-symbols/svg-600/outlined/tag.svg';
+import TagIcon from '@material-symbols/svg-600/outlined/tag.svg?react';
import { debounce } from 'lodash';
import { expandFollowedHashtags, fetchFollowedHashtags } from 'mastodon/actions/tags';
diff --git a/app/javascript/mastodon/features/getting_started/components/announcements.jsx b/app/javascript/mastodon/features/getting_started/components/announcements.jsx
index 1999316a8e..0818da5519 100644
--- a/app/javascript/mastodon/features/getting_started/components/announcements.jsx
+++ b/app/javascript/mastodon/features/getting_started/components/announcements.jsx
@@ -9,9 +9,9 @@ import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as AddIcon } from '@material-symbols/svg-600/outlined/add.svg';
-import { ReactComponent as ChevronLeftIcon } from '@material-symbols/svg-600/outlined/chevron_left.svg';
-import { ReactComponent as ChevronRightIcon } from '@material-symbols/svg-600/outlined/chevron_right.svg';
+import AddIcon from '@material-symbols/svg-600/outlined/add.svg?react';
+import ChevronLeftIcon from '@material-symbols/svg-600/outlined/chevron_left.svg?react';
+import ChevronRightIcon from '@material-symbols/svg-600/outlined/chevron_right.svg?react';
import TransitionMotion from 'react-motion/lib/TransitionMotion';
import spring from 'react-motion/lib/spring';
import ReactSwipeableViews from 'react-swipeable-views';
diff --git a/app/javascript/mastodon/features/getting_started/index.jsx b/app/javascript/mastodon/features/getting_started/index.jsx
index 5994e88edf..29bbfd35f6 100644
--- a/app/javascript/mastodon/features/getting_started/index.jsx
+++ b/app/javascript/mastodon/features/getting_started/index.jsx
@@ -9,17 +9,17 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as AlternateEmailIcon } from '@material-symbols/svg-600/outlined/alternate_email.svg';
-import { ReactComponent as BookmarksIcon } from '@material-symbols/svg-600/outlined/bookmarks-fill.svg';
-import { ReactComponent as PeopleIcon } from '@material-symbols/svg-600/outlined/group.svg';
-import { ReactComponent as HomeIcon } from '@material-symbols/svg-600/outlined/home-fill.svg';
-import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg';
-import { ReactComponent as MenuIcon } from '@material-symbols/svg-600/outlined/menu.svg';
-import { ReactComponent as PersonAddIcon } from '@material-symbols/svg-600/outlined/person_add.svg';
-import { ReactComponent as PublicIcon } from '@material-symbols/svg-600/outlined/public.svg';
-import { ReactComponent as SettingsIcon } from '@material-symbols/svg-600/outlined/settings-fill.svg';
-import { ReactComponent as StarIcon } from '@material-symbols/svg-600/outlined/star.svg';
-import { ReactComponent as TagIcon } from '@material-symbols/svg-600/outlined/tag.svg';
+import AlternateEmailIcon from '@material-symbols/svg-600/outlined/alternate_email.svg?react';
+import BookmarksIcon from '@material-symbols/svg-600/outlined/bookmarks-fill.svg?react';
+import PeopleIcon from '@material-symbols/svg-600/outlined/group.svg?react';
+import HomeIcon from '@material-symbols/svg-600/outlined/home-fill.svg?react';
+import ListAltIcon from '@material-symbols/svg-600/outlined/list_alt.svg?react';
+import MenuIcon from '@material-symbols/svg-600/outlined/menu.svg?react';
+import PersonAddIcon from '@material-symbols/svg-600/outlined/person_add.svg?react';
+import PublicIcon from '@material-symbols/svg-600/outlined/public.svg?react';
+import SettingsIcon from '@material-symbols/svg-600/outlined/settings-fill.svg?react';
+import StarIcon from '@material-symbols/svg-600/outlined/star.svg?react';
+import TagIcon from '@material-symbols/svg-600/outlined/tag.svg?react';
import { fetchFollowRequests } from 'mastodon/actions/accounts';
import Column from 'mastodon/components/column';
diff --git a/app/javascript/mastodon/features/hashtag_timeline/index.jsx b/app/javascript/mastodon/features/hashtag_timeline/index.jsx
index d39d550a1b..bdb8da00a5 100644
--- a/app/javascript/mastodon/features/hashtag_timeline/index.jsx
+++ b/app/javascript/mastodon/features/hashtag_timeline/index.jsx
@@ -8,7 +8,7 @@ import { Helmet } from 'react-helmet';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
-import { ReactComponent as TagIcon } from '@material-symbols/svg-600/outlined/tag.svg';
+import TagIcon from '@material-symbols/svg-600/outlined/tag.svg?react';
import { isEqual } from 'lodash';
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
diff --git a/app/javascript/mastodon/features/home_timeline/index.jsx b/app/javascript/mastodon/features/home_timeline/index.jsx
index 613eb4b896..6fc986393e 100644
--- a/app/javascript/mastodon/features/home_timeline/index.jsx
+++ b/app/javascript/mastodon/features/home_timeline/index.jsx
@@ -10,8 +10,8 @@ import { createSelector } from '@reduxjs/toolkit';
import { List as ImmutableList } from 'immutable';
import { connect } from 'react-redux';
-import { ReactComponent as CampaignIcon } from '@material-symbols/svg-600/outlined/campaign.svg';
-import { ReactComponent as HomeIcon } from '@material-symbols/svg-600/outlined/home-fill.svg';
+import CampaignIcon from '@material-symbols/svg-600/outlined/campaign.svg?react';
+import HomeIcon from '@material-symbols/svg-600/outlined/home-fill.svg?react';
import { fetchAnnouncements, toggleShowAnnouncements } from 'mastodon/actions/announcements';
import { IconWithBadge } from 'mastodon/components/icon_with_badge';
diff --git a/app/javascript/mastodon/features/interaction_modal/index.jsx b/app/javascript/mastodon/features/interaction_modal/index.jsx
index 216c63a7e6..527cba5d97 100644
--- a/app/javascript/mastodon/features/interaction_modal/index.jsx
+++ b/app/javascript/mastodon/features/interaction_modal/index.jsx
@@ -7,10 +7,10 @@ import classNames from 'classnames';
import { connect } from 'react-redux';
-import { ReactComponent as PersonAddIcon } from '@material-symbols/svg-600/outlined/person_add.svg';
-import { ReactComponent as RepeatIcon } from '@material-symbols/svg-600/outlined/repeat.svg';
-import { ReactComponent as ReplyIcon } from '@material-symbols/svg-600/outlined/reply.svg';
-import { ReactComponent as StarIcon } from '@material-symbols/svg-600/outlined/star.svg';
+import PersonAddIcon from '@material-symbols/svg-600/outlined/person_add.svg?react';
+import RepeatIcon from '@material-symbols/svg-600/outlined/repeat.svg?react';
+import ReplyIcon from '@material-symbols/svg-600/outlined/reply.svg?react';
+import StarIcon from '@material-symbols/svg-600/outlined/star.svg?react';
import { throttle, escapeRegExp } from 'lodash';
import { openModal, closeModal } from 'mastodon/actions/modal';
diff --git a/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx b/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx
index 7552e1799b..054797d18f 100644
--- a/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx
+++ b/app/javascript/mastodon/features/keyboard_shortcuts/index.jsx
@@ -6,7 +6,7 @@ import { Helmet } from 'react-helmet';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as InfoIcon } from '@material-symbols/svg-600/outlined/info.svg';
+import InfoIcon from '@material-symbols/svg-600/outlined/info.svg?react';
import Column from 'mastodon/components/column';
import ColumnHeader from 'mastodon/components/column_header';
diff --git a/app/javascript/mastodon/features/list_adder/components/list.jsx b/app/javascript/mastodon/features/list_adder/components/list.jsx
index 6c5aab85da..14e320e00b 100644
--- a/app/javascript/mastodon/features/list_adder/components/list.jsx
+++ b/app/javascript/mastodon/features/list_adder/components/list.jsx
@@ -6,9 +6,9 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as AddIcon } from '@material-symbols/svg-600/outlined/add.svg';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
-import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg';
+import AddIcon from '@material-symbols/svg-600/outlined/add.svg?react';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
+import ListAltIcon from '@material-symbols/svg-600/outlined/list_alt.svg?react';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/list_editor/components/account.jsx b/app/javascript/mastodon/features/list_editor/components/account.jsx
index 18d5e905cb..30595ebc8b 100644
--- a/app/javascript/mastodon/features/list_editor/components/account.jsx
+++ b/app/javascript/mastodon/features/list_editor/components/account.jsx
@@ -6,8 +6,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as AddIcon } from '@material-symbols/svg-600/outlined/add.svg';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import AddIcon from '@material-symbols/svg-600/outlined/add.svg?react';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import { removeFromListEditor, addToListEditor } from '../../../actions/lists';
import { Avatar } from '../../../components/avatar';
diff --git a/app/javascript/mastodon/features/list_editor/components/edit_list_form.jsx b/app/javascript/mastodon/features/list_editor/components/edit_list_form.jsx
index 1e2446f92b..db89611db2 100644
--- a/app/javascript/mastodon/features/list_editor/components/edit_list_form.jsx
+++ b/app/javascript/mastodon/features/list_editor/components/edit_list_form.jsx
@@ -5,7 +5,7 @@ import { defineMessages, injectIntl } from 'react-intl';
import { connect } from 'react-redux';
-import { ReactComponent as CheckIcon } from '@material-symbols/svg-600/outlined/check.svg';
+import CheckIcon from '@material-symbols/svg-600/outlined/check.svg?react';
import { changeListEditorTitle, submitListEditor } from '../../../actions/lists';
import { IconButton } from '../../../components/icon_button';
diff --git a/app/javascript/mastodon/features/list_editor/components/search.jsx b/app/javascript/mastodon/features/list_editor/components/search.jsx
index 093af5cd4e..1971fd2f76 100644
--- a/app/javascript/mastodon/features/list_editor/components/search.jsx
+++ b/app/javascript/mastodon/features/list_editor/components/search.jsx
@@ -7,8 +7,8 @@ import classNames from 'classnames';
import { connect } from 'react-redux';
-import { ReactComponent as CancelIcon } from '@material-symbols/svg-600/outlined/cancel.svg';
-import { ReactComponent as SearchIcon } from '@material-symbols/svg-600/outlined/search.svg';
+import CancelIcon from '@material-symbols/svg-600/outlined/cancel.svg?react';
+import SearchIcon from '@material-symbols/svg-600/outlined/search.svg?react';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/list_timeline/index.jsx b/app/javascript/mastodon/features/list_timeline/index.jsx
index 55579c2fd1..4ea794bdd4 100644
--- a/app/javascript/mastodon/features/list_timeline/index.jsx
+++ b/app/javascript/mastodon/features/list_timeline/index.jsx
@@ -9,9 +9,9 @@ import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
-import { ReactComponent as DeleteIcon } from '@material-symbols/svg-600/outlined/delete.svg';
-import { ReactComponent as EditIcon } from '@material-symbols/svg-600/outlined/edit.svg';
-import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg';
+import DeleteIcon from '@material-symbols/svg-600/outlined/delete.svg?react';
+import EditIcon from '@material-symbols/svg-600/outlined/edit.svg?react';
+import ListAltIcon from '@material-symbols/svg-600/outlined/list_alt.svg?react';
import Toggle from 'react-toggle';
import { addColumn, removeColumn, moveColumn } from 'mastodon/actions/columns';
diff --git a/app/javascript/mastodon/features/lists/index.jsx b/app/javascript/mastodon/features/lists/index.jsx
index 9014394351..e59a6e4130 100644
--- a/app/javascript/mastodon/features/lists/index.jsx
+++ b/app/javascript/mastodon/features/lists/index.jsx
@@ -9,7 +9,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg';
+import ListAltIcon from '@material-symbols/svg-600/outlined/list_alt.svg?react';
import { fetchLists } from 'mastodon/actions/lists';
import Column from 'mastodon/components/column';
diff --git a/app/javascript/mastodon/features/mutes/index.jsx b/app/javascript/mastodon/features/mutes/index.jsx
index 7f66edc03d..ab0d30fcd1 100644
--- a/app/javascript/mastodon/features/mutes/index.jsx
+++ b/app/javascript/mastodon/features/mutes/index.jsx
@@ -8,7 +8,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as VolumeOffIcon } from '@material-symbols/svg-600/outlined/volume_off.svg';
+import VolumeOffIcon from '@material-symbols/svg-600/outlined/volume_off.svg?react';
import { debounce } from 'lodash';
import { fetchMutes, expandMutes } from '../../actions/mutes';
diff --git a/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx b/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx
index 54fa16fb67..2e257ed5c3 100644
--- a/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx
+++ b/app/javascript/mastodon/features/notifications/components/clear_column_button.jsx
@@ -3,7 +3,7 @@ import { PureComponent } from 'react';
import { FormattedMessage } from 'react-intl';
-import { ReactComponent as DeleteForeverIcon } from '@material-symbols/svg-600/outlined/delete_forever.svg';
+import DeleteForeverIcon from '@material-symbols/svg-600/outlined/delete_forever.svg?react';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/notifications/components/filter_bar.jsx b/app/javascript/mastodon/features/notifications/components/filter_bar.jsx
index 84bd4791ca..56338333b1 100644
--- a/app/javascript/mastodon/features/notifications/components/filter_bar.jsx
+++ b/app/javascript/mastodon/features/notifications/components/filter_bar.jsx
@@ -3,12 +3,12 @@ import { PureComponent } from 'react';
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
-import { ReactComponent as HomeIcon } from '@material-symbols/svg-600/outlined/home-fill.svg';
-import { ReactComponent as InsertChartIcon } from '@material-symbols/svg-600/outlined/insert_chart.svg';
-import { ReactComponent as PersonAddIcon } from '@material-symbols/svg-600/outlined/person_add.svg';
-import { ReactComponent as RepeatIcon } from '@material-symbols/svg-600/outlined/repeat.svg';
-import { ReactComponent as ReplyAllIcon } from '@material-symbols/svg-600/outlined/reply_all.svg';
-import { ReactComponent as StarIcon } from '@material-symbols/svg-600/outlined/star.svg';
+import HomeIcon from '@material-symbols/svg-600/outlined/home-fill.svg?react';
+import InsertChartIcon from '@material-symbols/svg-600/outlined/insert_chart.svg?react';
+import PersonAddIcon from '@material-symbols/svg-600/outlined/person_add.svg?react';
+import RepeatIcon from '@material-symbols/svg-600/outlined/repeat.svg?react';
+import ReplyAllIcon from '@material-symbols/svg-600/outlined/reply_all.svg?react';
+import StarIcon from '@material-symbols/svg-600/outlined/star.svg?react';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/notifications/components/follow_request.jsx b/app/javascript/mastodon/features/notifications/components/follow_request.jsx
index 03420b6c01..904b6048ae 100644
--- a/app/javascript/mastodon/features/notifications/components/follow_request.jsx
+++ b/app/javascript/mastodon/features/notifications/components/follow_request.jsx
@@ -7,8 +7,8 @@ import { Link } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as CheckIcon } from '@material-symbols/svg-600/outlined/check.svg';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CheckIcon from '@material-symbols/svg-600/outlined/check.svg?react';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import { Avatar } from 'mastodon/components/avatar';
import { DisplayName } from 'mastodon/components/display_name';
diff --git a/app/javascript/mastodon/features/notifications/components/notification.jsx b/app/javascript/mastodon/features/notifications/components/notification.jsx
index ad7308b26f..24cead5a59 100644
--- a/app/javascript/mastodon/features/notifications/components/notification.jsx
+++ b/app/javascript/mastodon/features/notifications/components/notification.jsx
@@ -8,14 +8,14 @@ import { Link, withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as EditIcon } from '@material-symbols/svg-600/outlined/edit.svg';
-import { ReactComponent as FlagIcon } from '@material-symbols/svg-600/outlined/flag-fill.svg';
-import { ReactComponent as HomeIcon } from '@material-symbols/svg-600/outlined/home-fill.svg';
-import { ReactComponent as InsertChartIcon } from '@material-symbols/svg-600/outlined/insert_chart.svg';
-import { ReactComponent as PersonIcon } from '@material-symbols/svg-600/outlined/person-fill.svg';
-import { ReactComponent as PersonAddIcon } from '@material-symbols/svg-600/outlined/person_add-fill.svg';
-import { ReactComponent as RepeatIcon } from '@material-symbols/svg-600/outlined/repeat.svg';
-import { ReactComponent as StarIcon } from '@material-symbols/svg-600/outlined/star-fill.svg';
+import EditIcon from '@material-symbols/svg-600/outlined/edit.svg?react';
+import FlagIcon from '@material-symbols/svg-600/outlined/flag-fill.svg?react';
+import HomeIcon from '@material-symbols/svg-600/outlined/home-fill.svg?react';
+import InsertChartIcon from '@material-symbols/svg-600/outlined/insert_chart.svg?react';
+import PersonIcon from '@material-symbols/svg-600/outlined/person-fill.svg?react';
+import PersonAddIcon from '@material-symbols/svg-600/outlined/person_add-fill.svg?react';
+import RepeatIcon from '@material-symbols/svg-600/outlined/repeat.svg?react';
+import StarIcon from '@material-symbols/svg-600/outlined/star-fill.svg?react';
import { HotKeys } from 'react-hotkeys';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.jsx b/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.jsx
index b7ebb4c467..1c1750f72f 100644
--- a/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.jsx
+++ b/app/javascript/mastodon/features/notifications/components/notifications_permission_banner.jsx
@@ -5,8 +5,8 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
import { connect } from 'react-redux';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
-import { ReactComponent as TuneIcon } from '@material-symbols/svg-600/outlined/tune.svg';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
+import TuneIcon from '@material-symbols/svg-600/outlined/tune.svg?react';
import { requestBrowserPermission } from 'mastodon/actions/notifications';
import { changeSetting } from 'mastodon/actions/settings';
diff --git a/app/javascript/mastodon/features/notifications/index.jsx b/app/javascript/mastodon/features/notifications/index.jsx
index 762c96ccca..a841f346dd 100644
--- a/app/javascript/mastodon/features/notifications/index.jsx
+++ b/app/javascript/mastodon/features/notifications/index.jsx
@@ -10,8 +10,8 @@ import { List as ImmutableList } from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
-import { ReactComponent as DoneAllIcon } from '@material-symbols/svg-600/outlined/done_all.svg';
-import { ReactComponent as NotificationsIcon } from '@material-symbols/svg-600/outlined/notifications-fill.svg';
+import DoneAllIcon from '@material-symbols/svg-600/outlined/done_all.svg?react';
+import NotificationsIcon from '@material-symbols/svg-600/outlined/notifications-fill.svg?react';
import { debounce } from 'lodash';
import { compareId } from 'mastodon/compare_id';
diff --git a/app/javascript/mastodon/features/onboarding/components/step.jsx b/app/javascript/mastodon/features/onboarding/components/step.jsx
index 1f83f20801..0eca65615c 100644
--- a/app/javascript/mastodon/features/onboarding/components/step.jsx
+++ b/app/javascript/mastodon/features/onboarding/components/step.jsx
@@ -2,8 +2,8 @@ import PropTypes from 'prop-types';
import { Link } from 'react-router-dom';
-import { ReactComponent as ArrowRightAltIcon } from '@material-symbols/svg-600/outlined/arrow_right_alt.svg';
-import { ReactComponent as CheckIcon } from '@material-symbols/svg-600/outlined/done.svg';
+import ArrowRightAltIcon from '@material-symbols/svg-600/outlined/arrow_right_alt.svg?react';
+import CheckIcon from '@material-symbols/svg-600/outlined/done.svg?react';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/onboarding/index.jsx b/app/javascript/mastodon/features/onboarding/index.jsx
index 51677fbc7a..54699a1349 100644
--- a/app/javascript/mastodon/features/onboarding/index.jsx
+++ b/app/javascript/mastodon/features/onboarding/index.jsx
@@ -8,11 +8,11 @@ import { Link, Switch, Route, useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux';
-import { ReactComponent as AccountCircleIcon } from '@material-symbols/svg-600/outlined/account_circle.svg';
-import { ReactComponent as ArrowRightAltIcon } from '@material-symbols/svg-600/outlined/arrow_right_alt.svg';
-import { ReactComponent as ContentCopyIcon } from '@material-symbols/svg-600/outlined/content_copy.svg';
-import { ReactComponent as EditNoteIcon } from '@material-symbols/svg-600/outlined/edit_note.svg';
-import { ReactComponent as PersonAddIcon } from '@material-symbols/svg-600/outlined/person_add.svg';
+import AccountCircleIcon from '@material-symbols/svg-600/outlined/account_circle.svg?react';
+import ArrowRightAltIcon from '@material-symbols/svg-600/outlined/arrow_right_alt.svg?react';
+import ContentCopyIcon from '@material-symbols/svg-600/outlined/content_copy.svg?react';
+import EditNoteIcon from '@material-symbols/svg-600/outlined/edit_note.svg?react';
+import PersonAddIcon from '@material-symbols/svg-600/outlined/person_add.svg?react';
import illustration from 'mastodon/../images/elephant_ui_conversation.svg';
import { focusCompose } from 'mastodon/actions/compose';
diff --git a/app/javascript/mastodon/features/onboarding/profile.jsx b/app/javascript/mastodon/features/onboarding/profile.jsx
index daaef6065c..6765c919e8 100644
--- a/app/javascript/mastodon/features/onboarding/profile.jsx
+++ b/app/javascript/mastodon/features/onboarding/profile.jsx
@@ -8,8 +8,8 @@ import { useHistory } from 'react-router-dom';
import { useDispatch } from 'react-redux';
-import { ReactComponent as AddPhotoAlternateIcon } from '@material-symbols/svg-600/outlined/add_photo_alternate.svg';
-import { ReactComponent as EditIcon } from '@material-symbols/svg-600/outlined/edit.svg';
+import AddPhotoAlternateIcon from '@material-symbols/svg-600/outlined/add_photo_alternate.svg?react';
+import EditIcon from '@material-symbols/svg-600/outlined/edit.svg?react';
import Toggle from 'react-toggle';
import { updateAccount } from 'mastodon/actions/accounts';
diff --git a/app/javascript/mastodon/features/onboarding/share.jsx b/app/javascript/mastodon/features/onboarding/share.jsx
index adc0f9cba3..657edabd74 100644
--- a/app/javascript/mastodon/features/onboarding/share.jsx
+++ b/app/javascript/mastodon/features/onboarding/share.jsx
@@ -7,8 +7,8 @@ import classNames from 'classnames';
import { Link } from 'react-router-dom';
-import { ReactComponent as ArrowRightAltIcon } from '@material-symbols/svg-600/outlined/arrow_right_alt.svg';
-import { ReactComponent as ContentCopyIcon } from '@material-symbols/svg-600/outlined/content_copy.svg';
+import ArrowRightAltIcon from '@material-symbols/svg-600/outlined/arrow_right_alt.svg?react';
+import ContentCopyIcon from '@material-symbols/svg-600/outlined/content_copy.svg?react';
import SwipeableViews from 'react-swipeable-views';
import { ColumnBackButton } from 'mastodon/components/column_back_button';
diff --git a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx
index ed86d19f5c..d73b6d2adf 100644
--- a/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx
+++ b/app/javascript/mastodon/features/picture_in_picture/components/footer.jsx
@@ -9,11 +9,11 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as OpenInNewIcon } from '@material-symbols/svg-600/outlined/open_in_new.svg';
-import { ReactComponent as RepeatIcon } from '@material-symbols/svg-600/outlined/repeat.svg';
-import { ReactComponent as ReplyIcon } from '@material-symbols/svg-600/outlined/reply.svg';
-import { ReactComponent as ReplyAllIcon } from '@material-symbols/svg-600/outlined/reply_all.svg';
-import { ReactComponent as StarIcon } from '@material-symbols/svg-600/outlined/star.svg';
+import OpenInNewIcon from '@material-symbols/svg-600/outlined/open_in_new.svg?react';
+import RepeatIcon from '@material-symbols/svg-600/outlined/repeat.svg?react';
+import ReplyIcon from '@material-symbols/svg-600/outlined/reply.svg?react';
+import ReplyAllIcon from '@material-symbols/svg-600/outlined/reply_all.svg?react';
+import StarIcon from '@material-symbols/svg-600/outlined/star.svg?react';
import { initBoostModal } from 'mastodon/actions/boosts';
import { replyCompose } from 'mastodon/actions/compose';
diff --git a/app/javascript/mastodon/features/picture_in_picture/components/header.jsx b/app/javascript/mastodon/features/picture_in_picture/components/header.jsx
index 80a13bd2e3..608142b988 100644
--- a/app/javascript/mastodon/features/picture_in_picture/components/header.jsx
+++ b/app/javascript/mastodon/features/picture_in_picture/components/header.jsx
@@ -8,7 +8,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import { Avatar } from 'mastodon/components/avatar';
import { DisplayName } from 'mastodon/components/display_name';
diff --git a/app/javascript/mastodon/features/pinned_statuses/index.jsx b/app/javascript/mastodon/features/pinned_statuses/index.jsx
index 82398ccda9..2e68336a4f 100644
--- a/app/javascript/mastodon/features/pinned_statuses/index.jsx
+++ b/app/javascript/mastodon/features/pinned_statuses/index.jsx
@@ -8,7 +8,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as PushPinIcon } from '@material-symbols/svg-600/outlined/push_pin.svg';
+import PushPinIcon from '@material-symbols/svg-600/outlined/push_pin.svg?react';
import { getStatusList } from 'mastodon/selectors';
diff --git a/app/javascript/mastodon/features/public_timeline/index.jsx b/app/javascript/mastodon/features/public_timeline/index.jsx
index 09a9f6821f..6aa6d27b9d 100644
--- a/app/javascript/mastodon/features/public_timeline/index.jsx
+++ b/app/javascript/mastodon/features/public_timeline/index.jsx
@@ -7,7 +7,7 @@ import { Helmet } from 'react-helmet';
import { connect } from 'react-redux';
-import { ReactComponent as PublicIcon } from '@material-symbols/svg-600/outlined/public.svg';
+import PublicIcon from '@material-symbols/svg-600/outlined/public.svg?react';
import { DismissableBanner } from 'mastodon/components/dismissable_banner';
import { domain } from 'mastodon/initial_state';
diff --git a/app/javascript/mastodon/features/reblogs/index.jsx b/app/javascript/mastodon/features/reblogs/index.jsx
index be17668418..aeba1ecff3 100644
--- a/app/javascript/mastodon/features/reblogs/index.jsx
+++ b/app/javascript/mastodon/features/reblogs/index.jsx
@@ -8,7 +8,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as RefreshIcon } from '@material-symbols/svg-600/outlined/refresh.svg';
+import RefreshIcon from '@material-symbols/svg-600/outlined/refresh.svg?react';
import { debounce } from 'lodash';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/report/components/option.jsx b/app/javascript/mastodon/features/report/components/option.jsx
index b3602219f5..9ffe43388c 100644
--- a/app/javascript/mastodon/features/report/components/option.jsx
+++ b/app/javascript/mastodon/features/report/components/option.jsx
@@ -3,7 +3,7 @@ import { PureComponent } from 'react';
import classNames from 'classnames';
-import { ReactComponent as CheckIcon } from '@material-symbols/svg-600/outlined/done.svg';
+import CheckIcon from '@material-symbols/svg-600/outlined/done.svg?react';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/status/components/action_bar.jsx b/app/javascript/mastodon/features/status/components/action_bar.jsx
index 663bce7431..9355cb1f5c 100644
--- a/app/javascript/mastodon/features/status/components/action_bar.jsx
+++ b/app/javascript/mastodon/features/status/components/action_bar.jsx
@@ -9,17 +9,17 @@ import { withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
-import { ReactComponent as BookmarkIcon } from '@material-symbols/svg-600/outlined/bookmark-fill.svg';
-import { ReactComponent as BookmarkBorderIcon } from '@material-symbols/svg-600/outlined/bookmark.svg';
-import { ReactComponent as MoreHorizIcon } from '@material-symbols/svg-600/outlined/more_horiz.svg';
-import { ReactComponent as RepeatIcon } from '@material-symbols/svg-600/outlined/repeat.svg';
-import { ReactComponent as ReplyIcon } from '@material-symbols/svg-600/outlined/reply.svg';
-import { ReactComponent as ReplyAllIcon } from '@material-symbols/svg-600/outlined/reply_all.svg';
-import { ReactComponent as StarIcon } from '@material-symbols/svg-600/outlined/star-fill.svg';
-import { ReactComponent as StarBorderIcon } from '@material-symbols/svg-600/outlined/star.svg';
+import BookmarkIcon from '@material-symbols/svg-600/outlined/bookmark-fill.svg?react';
+import BookmarkBorderIcon from '@material-symbols/svg-600/outlined/bookmark.svg?react';
+import MoreHorizIcon from '@material-symbols/svg-600/outlined/more_horiz.svg?react';
+import RepeatIcon from '@material-symbols/svg-600/outlined/repeat.svg?react';
+import ReplyIcon from '@material-symbols/svg-600/outlined/reply.svg?react';
+import ReplyAllIcon from '@material-symbols/svg-600/outlined/reply_all.svg?react';
+import StarIcon from '@material-symbols/svg-600/outlined/star-fill.svg?react';
+import StarBorderIcon from '@material-symbols/svg-600/outlined/star.svg?react';
-import { ReactComponent as RepeatDisabledIcon } from 'mastodon/../svg-icons/repeat_disabled.svg';
-import { ReactComponent as RepeatPrivateIcon } from 'mastodon/../svg-icons/repeat_private.svg';
+import RepeatDisabledIcon from 'mastodon/../svg-icons/repeat_disabled.svg?react';
+import RepeatPrivateIcon from 'mastodon/../svg-icons/repeat_private.svg?react';
import { PERMISSION_MANAGE_USERS, PERMISSION_MANAGE_FEDERATION } from 'mastodon/permissions';
import { WithRouterPropTypes } from 'mastodon/utils/react_router';
diff --git a/app/javascript/mastodon/features/status/components/card.jsx b/app/javascript/mastodon/features/status/components/card.jsx
index d7d688952d..9497acffac 100644
--- a/app/javascript/mastodon/features/status/components/card.jsx
+++ b/app/javascript/mastodon/features/status/components/card.jsx
@@ -10,9 +10,9 @@ import classNames from 'classnames';
import Immutable from 'immutable';
import ImmutablePropTypes from 'react-immutable-proptypes';
-import { ReactComponent as DescriptionIcon } from '@material-symbols/svg-600/outlined/description-fill.svg';
-import { ReactComponent as OpenInNewIcon } from '@material-symbols/svg-600/outlined/open_in_new.svg';
-import { ReactComponent as PlayArrowIcon } from '@material-symbols/svg-600/outlined/play_arrow-fill.svg';
+import DescriptionIcon from '@material-symbols/svg-600/outlined/description-fill.svg?react';
+import OpenInNewIcon from '@material-symbols/svg-600/outlined/open_in_new.svg?react';
+import PlayArrowIcon from '@material-symbols/svg-600/outlined/play_arrow-fill.svg?react';
import { Blurhash } from 'mastodon/components/blurhash';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/status/components/detailed_status.jsx b/app/javascript/mastodon/features/status/components/detailed_status.jsx
index d8d9559127..03bb6a50bc 100644
--- a/app/javascript/mastodon/features/status/components/detailed_status.jsx
+++ b/app/javascript/mastodon/features/status/components/detailed_status.jsx
@@ -8,9 +8,9 @@ import { Link, withRouter } from 'react-router-dom';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as AlternateEmailIcon } from '@material-symbols/svg-600/outlined/alternate_email.svg';
-import { ReactComponent as RepeatIcon } from '@material-symbols/svg-600/outlined/repeat.svg';
-import { ReactComponent as StarIcon } from '@material-symbols/svg-600/outlined/star-fill.svg';
+import AlternateEmailIcon from '@material-symbols/svg-600/outlined/alternate_email.svg?react';
+import RepeatIcon from '@material-symbols/svg-600/outlined/repeat.svg?react';
+import StarIcon from '@material-symbols/svg-600/outlined/star-fill.svg?react';
import { AnimatedNumber } from 'mastodon/components/animated_number';
import EditedTimestamp from 'mastodon/components/edited_timestamp';
diff --git a/app/javascript/mastodon/features/status/index.jsx b/app/javascript/mastodon/features/status/index.jsx
index 3832489764..d4ab3a5dcd 100644
--- a/app/javascript/mastodon/features/status/index.jsx
+++ b/app/javascript/mastodon/features/status/index.jsx
@@ -12,8 +12,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as VisibilityIcon } from '@material-symbols/svg-600/outlined/visibility.svg';
-import { ReactComponent as VisibilityOffIcon } from '@material-symbols/svg-600/outlined/visibility_off.svg';
+import VisibilityIcon from '@material-symbols/svg-600/outlined/visibility.svg?react';
+import VisibilityOffIcon from '@material-symbols/svg-600/outlined/visibility_off.svg?react';
import { HotKeys } from 'react-hotkeys';
import { Icon } from 'mastodon/components/icon';
diff --git a/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx b/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx
index ac34f7986c..f690925418 100644
--- a/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx
+++ b/app/javascript/mastodon/features/subscribed_languages_modal/index.jsx
@@ -8,7 +8,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import { followAccount } from 'mastodon/actions/accounts';
import { Button } from 'mastodon/components/button';
diff --git a/app/javascript/mastodon/features/ui/components/boost_modal.jsx b/app/javascript/mastodon/features/ui/components/boost_modal.jsx
index c6fa8ce363..851acbb719 100644
--- a/app/javascript/mastodon/features/ui/components/boost_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/boost_modal.jsx
@@ -9,7 +9,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as RepeatIcon } from '@material-symbols/svg-600/outlined/repeat.svg';
+import RepeatIcon from '@material-symbols/svg-600/outlined/repeat.svg?react';
import { changeBoostPrivacy } from 'mastodon/actions/boosts';
import AttachmentList from 'mastodon/components/attachment_list';
diff --git a/app/javascript/mastodon/features/ui/components/bundle_modal_error.jsx b/app/javascript/mastodon/features/ui/components/bundle_modal_error.jsx
index 44165f1417..31c4ce0e97 100644
--- a/app/javascript/mastodon/features/ui/components/bundle_modal_error.jsx
+++ b/app/javascript/mastodon/features/ui/components/bundle_modal_error.jsx
@@ -3,7 +3,7 @@ import { PureComponent } from 'react';
import { defineMessages, injectIntl } from 'react-intl';
-import { ReactComponent as RefreshIcon } from '@material-symbols/svg-600/outlined/refresh.svg';
+import RefreshIcon from '@material-symbols/svg-600/outlined/refresh.svg?react';
import { IconButton } from '../../../components/icon_button';
diff --git a/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx b/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx
index 413c5069f1..7807a103ee 100644
--- a/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/compare_history_modal.jsx
@@ -6,7 +6,7 @@ import { FormattedMessage } from 'react-intl';
import ImmutablePropTypes from 'react-immutable-proptypes';
import { connect } from 'react-redux';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import escapeTextContentForBrowser from 'escape-html';
import { closeModal } from 'mastodon/actions/modal';
diff --git a/app/javascript/mastodon/features/ui/components/embed_modal.jsx b/app/javascript/mastodon/features/ui/components/embed_modal.jsx
index e5c0b5cae9..60d04d2378 100644
--- a/app/javascript/mastodon/features/ui/components/embed_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/embed_modal.jsx
@@ -4,7 +4,7 @@ import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import api from 'mastodon/api';
import { IconButton } from 'mastodon/components/icon_button';
diff --git a/app/javascript/mastodon/features/ui/components/filter_modal.jsx b/app/javascript/mastodon/features/ui/components/filter_modal.jsx
index d90edddec4..3f3855d9f1 100644
--- a/app/javascript/mastodon/features/ui/components/filter_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/filter_modal.jsx
@@ -5,7 +5,7 @@ import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import { fetchFilters, createFilter, createFilterStatus } from 'mastodon/actions/filters';
import { fetchStatus } from 'mastodon/actions/statuses';
diff --git a/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx b/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx
index 91dca26718..f2998f217a 100644
--- a/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/focal_point_modal.jsx
@@ -9,7 +9,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import Textarea from 'react-textarea-autosize';
import { length } from 'stringz';
// eslint-disable-next-line import/extensions
diff --git a/app/javascript/mastodon/features/ui/components/follow_requests_column_link.jsx b/app/javascript/mastodon/features/ui/components/follow_requests_column_link.jsx
index 314b2a2652..d40c67a752 100644
--- a/app/javascript/mastodon/features/ui/components/follow_requests_column_link.jsx
+++ b/app/javascript/mastodon/features/ui/components/follow_requests_column_link.jsx
@@ -6,7 +6,7 @@ import { injectIntl, defineMessages } from 'react-intl';
import { List as ImmutableList } from 'immutable';
import { connect } from 'react-redux';
-import { ReactComponent as PersonAddIcon } from '@material-symbols/svg-600/outlined/person_add.svg';
+import PersonAddIcon from '@material-symbols/svg-600/outlined/person_add.svg?react';
import { fetchFollowRequests } from 'mastodon/actions/accounts';
import { IconWithBadge } from 'mastodon/components/icon_with_badge';
diff --git a/app/javascript/mastodon/features/ui/components/header.jsx b/app/javascript/mastodon/features/ui/components/header.jsx
index 150647ffb3..6ece50184a 100644
--- a/app/javascript/mastodon/features/ui/components/header.jsx
+++ b/app/javascript/mastodon/features/ui/components/header.jsx
@@ -7,7 +7,7 @@ import { Link, withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
-import { ReactComponent as SearchIcon } from '@material-symbols/svg-600/outlined/search.svg';
+import SearchIcon from '@material-symbols/svg-600/outlined/search.svg?react';
import { openModal } from 'mastodon/actions/modal';
import { fetchServer } from 'mastodon/actions/server';
diff --git a/app/javascript/mastodon/features/ui/components/image_modal.jsx b/app/javascript/mastodon/features/ui/components/image_modal.jsx
index c534bf1636..44fb172ad2 100644
--- a/app/javascript/mastodon/features/ui/components/image_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/image_modal.jsx
@@ -5,7 +5,7 @@ import { defineMessages, injectIntl } from 'react-intl';
import classNames from 'classnames';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import { IconButton } from 'mastodon/components/icon_button';
diff --git a/app/javascript/mastodon/features/ui/components/list_panel.jsx b/app/javascript/mastodon/features/ui/components/list_panel.jsx
index ff600730a0..b574668b20 100644
--- a/app/javascript/mastodon/features/ui/components/list_panel.jsx
+++ b/app/javascript/mastodon/features/ui/components/list_panel.jsx
@@ -5,7 +5,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg';
+import ListAltIcon from '@material-symbols/svg-600/outlined/list_alt.svg?react';
import { fetchLists } from 'mastodon/actions/lists';
diff --git a/app/javascript/mastodon/features/ui/components/media_modal.jsx b/app/javascript/mastodon/features/ui/components/media_modal.jsx
index 8c06a96531..95d8ae5df1 100644
--- a/app/javascript/mastodon/features/ui/components/media_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/media_modal.jsx
@@ -7,9 +7,9 @@ import classNames from 'classnames';
import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
-import { ReactComponent as ChevronLeftIcon } from '@material-symbols/svg-600/outlined/chevron_left.svg';
-import { ReactComponent as ChevronRightIcon } from '@material-symbols/svg-600/outlined/chevron_right.svg';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import ChevronLeftIcon from '@material-symbols/svg-600/outlined/chevron_left.svg?react';
+import ChevronRightIcon from '@material-symbols/svg-600/outlined/chevron_right.svg?react';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import ReactSwipeableViews from 'react-swipeable-views';
import { getAverageFromBlurhash } from 'mastodon/blurhash';
diff --git a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx
index d1b2a0910b..e5b762807d 100644
--- a/app/javascript/mastodon/features/ui/components/navigation_panel.jsx
+++ b/app/javascript/mastodon/features/ui/components/navigation_panel.jsx
@@ -5,16 +5,16 @@ import { defineMessages, injectIntl } from 'react-intl';
import { Link } from 'react-router-dom';
-import { ReactComponent as AlternateEmailIcon } from '@material-symbols/svg-600/outlined/alternate_email.svg';
-import { ReactComponent as BookmarksIcon } from '@material-symbols/svg-600/outlined/bookmarks-fill.svg';
-import { ReactComponent as HomeIcon } from '@material-symbols/svg-600/outlined/home-fill.svg';
-import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg';
-import { ReactComponent as MoreHorizIcon } from '@material-symbols/svg-600/outlined/more_horiz.svg';
-import { ReactComponent as PublicIcon } from '@material-symbols/svg-600/outlined/public.svg';
-import { ReactComponent as SearchIcon } from '@material-symbols/svg-600/outlined/search.svg';
-import { ReactComponent as SettingsIcon } from '@material-symbols/svg-600/outlined/settings-fill.svg';
-import { ReactComponent as StarIcon } from '@material-symbols/svg-600/outlined/star-fill.svg';
-import { ReactComponent as TagIcon } from '@material-symbols/svg-600/outlined/tag.svg';
+import AlternateEmailIcon from '@material-symbols/svg-600/outlined/alternate_email.svg?react';
+import BookmarksIcon from '@material-symbols/svg-600/outlined/bookmarks-fill.svg?react';
+import HomeIcon from '@material-symbols/svg-600/outlined/home-fill.svg?react';
+import ListAltIcon from '@material-symbols/svg-600/outlined/list_alt.svg?react';
+import MoreHorizIcon from '@material-symbols/svg-600/outlined/more_horiz.svg?react';
+import PublicIcon from '@material-symbols/svg-600/outlined/public.svg?react';
+import SearchIcon from '@material-symbols/svg-600/outlined/search.svg?react';
+import SettingsIcon from '@material-symbols/svg-600/outlined/settings-fill.svg?react';
+import StarIcon from '@material-symbols/svg-600/outlined/star-fill.svg?react';
+import TagIcon from '@material-symbols/svg-600/outlined/tag.svg?react';
import { WordmarkLogo } from 'mastodon/components/logo';
import { NavigationPortal } from 'mastodon/components/navigation_portal';
diff --git a/app/javascript/mastodon/features/ui/components/notifications_counter_icon.js b/app/javascript/mastodon/features/ui/components/notifications_counter_icon.js
index b3e9950e93..435bebd0b1 100644
--- a/app/javascript/mastodon/features/ui/components/notifications_counter_icon.js
+++ b/app/javascript/mastodon/features/ui/components/notifications_counter_icon.js
@@ -1,6 +1,6 @@
import { connect } from 'react-redux';
-import { ReactComponent as NotificationsIcon } from '@material-symbols/svg-600/outlined/notifications-fill.svg';
+import NotificationsIcon from '@material-symbols/svg-600/outlined/notifications-fill.svg?react';
import { IconWithBadge } from 'mastodon/components/icon_with_badge';
diff --git a/app/javascript/mastodon/features/ui/components/report_modal.jsx b/app/javascript/mastodon/features/ui/components/report_modal.jsx
index 3fd8ff127d..27207f2fbf 100644
--- a/app/javascript/mastodon/features/ui/components/report_modal.jsx
+++ b/app/javascript/mastodon/features/ui/components/report_modal.jsx
@@ -7,7 +7,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
import ImmutablePureComponent from 'react-immutable-pure-component';
import { connect } from 'react-redux';
-import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
+import CloseIcon from '@material-symbols/svg-600/outlined/close.svg?react';
import { submitReport } from 'mastodon/actions/reports';
import { fetchServer } from 'mastodon/actions/server';
diff --git a/app/javascript/mastodon/features/ui/components/zoomable_image.jsx b/app/javascript/mastodon/features/ui/components/zoomable_image.jsx
index 5e71da9d96..7d4f1f55dd 100644
--- a/app/javascript/mastodon/features/ui/components/zoomable_image.jsx
+++ b/app/javascript/mastodon/features/ui/components/zoomable_image.jsx
@@ -3,8 +3,8 @@ import { PureComponent } from 'react';
import { defineMessages, injectIntl } from 'react-intl';
-import { ReactComponent as FullscreenExitIcon } from '@material-symbols/svg-600/outlined/fullscreen_exit.svg';
-import { ReactComponent as RectangleIcon } from '@material-symbols/svg-600/outlined/rectangle.svg';
+import FullscreenExitIcon from '@material-symbols/svg-600/outlined/fullscreen_exit.svg?react';
+import RectangleIcon from '@material-symbols/svg-600/outlined/rectangle.svg?react';
import { IconButton } from 'mastodon/components/icon_button';
diff --git a/app/javascript/mastodon/features/video/index.jsx b/app/javascript/mastodon/features/video/index.jsx
index e908715e91..73034bbf66 100644
--- a/app/javascript/mastodon/features/video/index.jsx
+++ b/app/javascript/mastodon/features/video/index.jsx
@@ -7,14 +7,14 @@ import classNames from 'classnames';
import { is } from 'immutable';
-import { ReactComponent as FullscreenIcon } from '@material-symbols/svg-600/outlined/fullscreen.svg';
-import { ReactComponent as FullscreenExitIcon } from '@material-symbols/svg-600/outlined/fullscreen_exit.svg';
-import { ReactComponent as PauseIcon } from '@material-symbols/svg-600/outlined/pause.svg';
-import { ReactComponent as PlayArrowIcon } from '@material-symbols/svg-600/outlined/play_arrow-fill.svg';
-import { ReactComponent as RectangleIcon } from '@material-symbols/svg-600/outlined/rectangle.svg';
-import { ReactComponent as VisibilityOffIcon } from '@material-symbols/svg-600/outlined/visibility_off.svg';
-import { ReactComponent as VolumeOffIcon } from '@material-symbols/svg-600/outlined/volume_off-fill.svg';
-import { ReactComponent as VolumeUpIcon } from '@material-symbols/svg-600/outlined/volume_up-fill.svg';
+import FullscreenIcon from '@material-symbols/svg-600/outlined/fullscreen.svg?react';
+import FullscreenExitIcon from '@material-symbols/svg-600/outlined/fullscreen_exit.svg?react';
+import PauseIcon from '@material-symbols/svg-600/outlined/pause.svg?react';
+import PlayArrowIcon from '@material-symbols/svg-600/outlined/play_arrow-fill.svg?react';
+import RectangleIcon from '@material-symbols/svg-600/outlined/rectangle.svg?react';
+import VisibilityOffIcon from '@material-symbols/svg-600/outlined/visibility_off.svg?react';
+import VolumeOffIcon from '@material-symbols/svg-600/outlined/volume_off-fill.svg?react';
+import VolumeUpIcon from '@material-symbols/svg-600/outlined/volume_up-fill.svg?react';
import { throttle } from 'lodash';
import { Blurhash } from 'mastodon/components/blurhash';
diff --git a/app/javascript/types/image.d.ts b/app/javascript/types/image.d.ts
index 07d1929555..8a08eca9f6 100644
--- a/app/javascript/types/image.d.ts
+++ b/app/javascript/types/image.d.ts
@@ -20,16 +20,20 @@ declare module '*.png' {
}
declare module '*.svg' {
+ const path: string;
+ export default path;
+}
+
+declare module '*.svg?react' {
import type React from 'react';
interface SVGPropsWithTitle extends React.SVGProps {
title?: string;
}
- export const ReactComponent: React.FC;
+ const ReactComponent: React.FC;
- const path: string;
- export default path;
+ export default ReactComponent;
}
declare module '*.webp' {
diff --git a/app/lib/activitypub/activity/create.rb b/app/lib/activitypub/activity/create.rb
index 8eff9fdf40..eb332a44cd 100644
--- a/app/lib/activitypub/activity/create.rb
+++ b/app/lib/activitypub/activity/create.rb
@@ -283,6 +283,7 @@ class ActivityPub::Activity::Create < ActivityPub::Activity
RedownloadMediaWorker.perform_in(rand(30..600).seconds, media_attachment.id)
rescue Seahorse::Client::NetworkingError => e
Rails.logger.warn "Error storing media attachment: #{e}"
+ RedownloadMediaWorker.perform_async(media_attachment.id)
end
end
diff --git a/app/lib/status_reach_finder.rb b/app/lib/status_reach_finder.rb
index 36fb0e80fb..17e42e3ec3 100644
--- a/app/lib/status_reach_finder.rb
+++ b/app/lib/status_reach_finder.rb
@@ -16,28 +16,28 @@ class StatusReachFinder
private
def reached_account_inboxes
+ Account.where(id: reached_account_ids).inboxes
+ end
+
+ def reached_account_ids
# When the status is a reblog, there are no interactions with it
# directly, we assume all interactions are with the original one
if @status.reblog?
- []
+ [reblog_of_account_id]
else
- Account.where(id: reached_account_ids).inboxes
- end
- end
-
- def reached_account_ids
- [
- replied_to_account_id,
- reblog_of_account_id,
- mentioned_account_ids,
- reblogs_account_ids,
- favourites_account_ids,
- replies_account_ids,
- ].tap do |arr|
- arr.flatten!
- arr.compact!
- arr.uniq!
+ [
+ replied_to_account_id,
+ reblog_of_account_id,
+ mentioned_account_ids,
+ reblogs_account_ids,
+ favourites_account_ids,
+ replies_account_ids,
+ ].tap do |arr|
+ arr.flatten!
+ arr.compact!
+ arr.uniq!
+ end
end
end
diff --git a/app/models/account.rb b/app/models/account.rb
index 0e38e07be8..526a8abccb 100644
--- a/app/models/account.rb
+++ b/app/models/account.rb
@@ -133,7 +133,6 @@ class Account < ApplicationRecord
scope :without_unapproved, -> { left_outer_joins(:user).merge(User.approved.confirmed).or(remote) }
scope :searchable, -> { without_unapproved.without_suspended.where(moved_to_account_id: nil) }
scope :discoverable, -> { searchable.without_silenced.where(discoverable: true).joins(:account_stat) }
- scope :followable_by, ->(account) { joins(arel_table.join(Follow.arel_table, Arel::Nodes::OuterJoin).on(arel_table[:id].eq(Follow.arel_table[:target_account_id]).and(Follow.arel_table[:account_id].eq(account.id))).join_sources).where(Follow.arel_table[:id].eq(nil)).joins(arel_table.join(FollowRequest.arel_table, Arel::Nodes::OuterJoin).on(arel_table[:id].eq(FollowRequest.arel_table[:target_account_id]).and(FollowRequest.arel_table[:account_id].eq(account.id))).join_sources).where(FollowRequest.arel_table[:id].eq(nil)) }
scope :by_recent_status, -> { includes(:account_stat).merge(AccountStat.order('last_status_at DESC NULLS LAST')).references(:account_stat) }
scope :by_recent_activity, -> { left_joins(:user, :account_stat).order(coalesced_activity_timestamps.desc).order(id: :desc) }
scope :popular, -> { order('account_stats.followers_count desc') }
diff --git a/app/models/account_suggestions/source.rb b/app/models/account_suggestions/source.rb
index ee93a1342f..d83f5e3773 100644
--- a/app/models/account_suggestions/source.rb
+++ b/app/models/account_suggestions/source.rb
@@ -8,11 +8,31 @@ class AccountSuggestions::Source
protected
def base_account_scope(account)
- Account.searchable
- .followable_by(account)
- .not_excluded_by_account(account)
- .not_domain_blocked_by_account(account)
- .where.not(id: account.id)
- .joins("LEFT OUTER JOIN follow_recommendation_mutes ON follow_recommendation_mutes.target_account_id = accounts.id AND follow_recommendation_mutes.account_id = #{account.id}").where(follow_recommendation_mutes: { target_account_id: nil })
+ Account
+ .searchable
+ .where.not(follows_sql, id: account.id)
+ .where.not(follow_requests_sql, id: account.id)
+ .not_excluded_by_account(account)
+ .not_domain_blocked_by_account(account)
+ .where.not(id: account.id)
+ .where.not(follow_recommendation_mutes_sql, id: account.id)
+ end
+
+ def follows_sql
+ <<~SQL.squish
+ EXISTS (SELECT 1 FROM follows WHERE follows.target_account_id = accounts.id AND follows.account_id = :id)
+ SQL
+ end
+
+ def follow_requests_sql
+ <<~SQL.squish
+ EXISTS (SELECT 1 FROM follow_requests WHERE follow_requests.target_account_id = accounts.id AND follow_requests.account_id = :id)
+ SQL
+ end
+
+ def follow_recommendation_mutes_sql
+ <<~SQL.squish
+ EXISTS (SELECT 1 FROM follow_recommendation_mutes WHERE follow_recommendation_mutes.target_account_id = accounts.id AND follow_recommendation_mutes.account_id = :id)
+ SQL
end
end
diff --git a/app/services/reblog_service.rb b/app/services/reblog_service.rb
index 18e1748cea..9c3d410182 100644
--- a/app/services/reblog_service.rb
+++ b/app/services/reblog_service.rb
@@ -43,11 +43,7 @@ class ReblogService < BaseService
def create_notification(reblog)
reblogged_status = reblog.reblog
- if reblogged_status.account.local?
- LocalNotificationWorker.perform_async(reblogged_status.account_id, reblog.id, reblog.class.name, 'reblog')
- elsif reblogged_status.account.activitypub? && !reblogged_status.account.following?(reblog.account)
- ActivityPub::DeliveryWorker.perform_async(build_json(reblog), reblog.account_id, reblogged_status.account.inbox_url)
- end
+ LocalNotificationWorker.perform_async(reblogged_status.account_id, reblog.id, reblog.class.name, 'reblog') if reblogged_status.account.local?
end
def increment_statistics
diff --git a/config/webpack/rules/file.js b/config/webpack/rules/file.js
index 25cda0eae5..fd9b14cad6 100644
--- a/config/webpack/rules/file.js
+++ b/config/webpack/rules/file.js
@@ -4,6 +4,7 @@ const { settings } = require('../configuration');
module.exports = {
test: new RegExp(`(${settings.static_assets_extensions.join('|')})$`, 'i'),
+ exclude: [/node_modules\/@material-symbols/, /svg-icons/],
use: [
{
loader: 'file-loader',
diff --git a/jest.config.js b/jest.config.js
index 9e61124e2f..5062c2fc6a 100644
--- a/jest.config.js
+++ b/jest.config.js
@@ -22,7 +22,7 @@ const config = {
coverageDirectory: '/coverage',
moduleDirectories: ['node_modules', '/app/javascript'],
moduleNameMapper: {
- '\\.svg$': '/app/javascript/__mocks__/svg.js',
+ '\\.svg\\?react$': '/app/javascript/__mocks__/svg.js',
},
};
diff --git a/spec/lib/activitypub/tag_manager_spec.rb b/spec/lib/activitypub/tag_manager_spec.rb
index 2bff125a6a..55e9b4bb51 100644
--- a/spec/lib/activitypub/tag_manager_spec.rb
+++ b/spec/lib/activitypub/tag_manager_spec.rb
@@ -112,6 +112,14 @@ RSpec.describe ActivityPub::TagManager do
expect(subject.cc(status)).to include(subject.uri_for(foo))
expect(subject.cc(status)).to_not include(subject.uri_for(alice))
end
+
+ it 'returns poster of reblogged post, if reblog' do
+ bob = Fabricate(:account, username: 'bob', domain: 'example.com', inbox_url: 'http://example.com/bob')
+ alice = Fabricate(:account, username: 'alice')
+ status = Fabricate(:status, visibility: :public, account: bob)
+ reblog = Fabricate(:status, visibility: :public, account: alice, reblog: status)
+ expect(subject.cc(reblog)).to include(subject.uri_for(bob))
+ end
end
describe '#local_uri?' do
diff --git a/spec/services/reblog_service_spec.rb b/spec/services/reblog_service_spec.rb
index c6d13e5a12..357b315af0 100644
--- a/spec/services/reblog_service_spec.rb
+++ b/spec/services/reblog_service_spec.rb
@@ -86,9 +86,5 @@ RSpec.describe ReblogService, type: :service do
it 'distributes to followers' do
expect(ActivityPub::DistributionWorker).to have_received(:perform_async)
end
-
- it 'sends an announce activity to the author', :sidekiq_inline do
- expect(a_request(:post, bob.inbox_url)).to have_been_made.once
- end
end
end
diff --git a/spec/services/remove_status_service_spec.rb b/spec/services/remove_status_service_spec.rb
index 63a9df548f..109acfb09a 100644
--- a/spec/services/remove_status_service_spec.rb
+++ b/spec/services/remove_status_service_spec.rb
@@ -116,4 +116,22 @@ RSpec.describe RemoveStatusService, :sidekiq_inline, type: :service do
)).to have_been_made.once
end
end
+
+ context 'when removed status is a reblog of a non-follower' do
+ let!(:original_status) { Fabricate(:status, account: bill, text: 'Hello ThisIsASecret', visibility: :public) }
+ let!(:status) { ReblogService.new.call(alice, original_status) }
+
+ it 'sends Undo activity to followers' do
+ subject.call(status)
+ expect(a_request(:post, bill.inbox_url).with(
+ body: hash_including({
+ 'type' => 'Undo',
+ 'object' => hash_including({
+ 'type' => 'Announce',
+ 'object' => ActivityPub::TagManager.instance.uri_for(original_status),
+ }),
+ })
+ )).to have_been_made.once
+ end
+ end
end