mirror of
https://git.kescher.at/CatCatNya/catstodon.git
synced 2024-11-22 11:48:06 +01:00
Merge commit 'a0e237a96fca2774d3c9ed43063a45e395bb7f40' into glitch-soc/merge-upstream
This commit is contained in:
commit
51d2d98174
25 changed files with 167 additions and 104 deletions
11
.eslintrc.js
11
.eslintrc.js
|
@ -245,7 +245,7 @@ module.exports = defineConfig({
|
||||||
},
|
},
|
||||||
// Immutable / Redux / data store
|
// Immutable / Redux / data store
|
||||||
{
|
{
|
||||||
pattern: '{immutable,react-redux,react-immutable-proptypes,react-immutable-pure-component,reselect}',
|
pattern: '{immutable,@reduxjs/toolkit,react-redux,react-immutable-proptypes,react-immutable-pure-component}',
|
||||||
group: 'external',
|
group: 'external',
|
||||||
position: 'before',
|
position: 'before',
|
||||||
},
|
},
|
||||||
|
@ -370,7 +370,14 @@ module.exports = defineConfig({
|
||||||
'@typescript-eslint/consistent-type-exports': 'error',
|
'@typescript-eslint/consistent-type-exports': 'error',
|
||||||
'@typescript-eslint/consistent-type-imports': 'error',
|
'@typescript-eslint/consistent-type-imports': 'error',
|
||||||
"@typescript-eslint/prefer-nullish-coalescing": ['error', { ignorePrimitives: { boolean: true } }],
|
"@typescript-eslint/prefer-nullish-coalescing": ['error', { ignorePrimitives: { boolean: true } }],
|
||||||
|
"@typescript-eslint/no-restricted-imports": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"name": "react-redux",
|
||||||
|
"importNames": ["useSelector", "useDispatch"],
|
||||||
|
"message": "Use typed hooks `useAppDispatch` and `useAppSelector` instead."
|
||||||
|
}
|
||||||
|
],
|
||||||
'jsdoc/require-jsdoc': 'off',
|
'jsdoc/require-jsdoc': 'off',
|
||||||
|
|
||||||
// Those rules set stricter rules for TS files
|
// Those rules set stricter rules for TS files
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { useEmoji } from '../../../actions/emojis';
|
import { useEmoji } from '../../../actions/emojis';
|
||||||
import { changeSetting } from '../../../actions/settings';
|
import { changeSetting } from '../../../actions/settings';
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { changeComposeLanguage } from 'mastodon/actions/compose';
|
import { changeComposeLanguage } from 'mastodon/actions/compose';
|
||||||
import { useLanguage } from 'mastodon/actions/languages';
|
import { useLanguage } from 'mastodon/actions/languages';
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { addReaction, removeReaction, dismissAnnouncement } from 'mastodon/actions/announcements';
|
import { addReaction, removeReaction, dismissAnnouncement } from 'mastodon/actions/announcements';
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,9 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { List as ImmutableList } from 'immutable';
|
import { List as ImmutableList } from 'immutable';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { ReactComponent as CampaignIcon } from '@material-symbols/svg-600/outlined/campaign.svg';
|
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 { ReactComponent as HomeIcon } from '@material-symbols/svg-600/outlined/home-fill.svg';
|
||||||
|
|
|
@ -2,10 +2,10 @@ import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { injectIntl } from 'react-intl';
|
import { injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { setupListAdder, resetListAdder } from '../../actions/lists';
|
import { setupListAdder, resetListAdder } from '../../actions/lists';
|
||||||
import NewListForm from '../lists/components/new_list_form';
|
import NewListForm from '../lists/components/new_list_form';
|
||||||
|
|
|
@ -4,10 +4,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg';
|
import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg';
|
||||||
|
|
||||||
|
|
|
@ -5,10 +5,10 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { List as ImmutableList } from 'immutable';
|
import { List as ImmutableList } from 'immutable';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { ReactComponent as DoneAllIcon } from '@material-symbols/svg-600/outlined/done_all.svg';
|
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 { ReactComponent as NotificationsIcon } from '@material-symbols/svg-600/outlined/notifications-fill.svg';
|
||||||
|
|
|
@ -3,10 +3,10 @@ import { useCallback, useEffect, useRef } from 'react';
|
||||||
|
|
||||||
import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
|
import { useIntl, defineMessages, FormattedMessage } from 'react-intl';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { OrderedSet, List as ImmutableList } from 'immutable';
|
import { OrderedSet, List as ImmutableList } from 'immutable';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import { shallowEqual } from 'react-redux';
|
import { shallowEqual } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import Toggle from 'react-toggle';
|
import Toggle from 'react-toggle';
|
||||||
|
|
||||||
|
|
|
@ -6,11 +6,11 @@ import classNames from 'classnames';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import { withRouter } from 'react-router-dom';
|
import { withRouter } from 'react-router-dom';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import Immutable from 'immutable';
|
import Immutable from 'immutable';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { ReactComponent as VisibilityIcon } from '@material-symbols/svg-600/outlined/visibility.svg';
|
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 { ReactComponent as VisibilityOffIcon } from '@material-symbols/svg-600/outlined/visibility_off.svg';
|
||||||
|
|
|
@ -2,11 +2,11 @@ import PropTypes from 'prop-types';
|
||||||
|
|
||||||
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
|
import { defineMessages, FormattedMessage, injectIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { is, List as ImmutableList, Set as ImmutableSet } from 'immutable';
|
import { is, List as ImmutableList, Set as ImmutableSet } from 'immutable';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
|
import { ReactComponent as CloseIcon } from '@material-symbols/svg-600/outlined/close.svg';
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg';
|
import { ReactComponent as ListAltIcon } from '@material-symbols/svg-600/outlined/list_alt.svg';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
|
||||||
import { connect } from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
|
import type { Reducer } from '@reduxjs/toolkit';
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
|
|
||||||
import type { Reducer } from 'redux';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
followAccountSuccess,
|
followAccountSuccess,
|
||||||
unfollowAccountSuccess,
|
unfollowAccountSuccess,
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { Record as ImmutableRecord, Stack } from 'immutable';
|
|
||||||
|
|
||||||
import type { Reducer } from '@reduxjs/toolkit';
|
import type { Reducer } from '@reduxjs/toolkit';
|
||||||
|
import { Record as ImmutableRecord, Stack } from 'immutable';
|
||||||
|
|
||||||
import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from '../actions/compose';
|
import { COMPOSE_UPLOAD_CHANGE_SUCCESS } from '../actions/compose';
|
||||||
import type { ModalType } from '../actions/modal';
|
import type { ModalType } from '../actions/modal';
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { Map as ImmutableMap } from 'immutable';
|
|
||||||
|
|
||||||
import { isFulfilled } from '@reduxjs/toolkit';
|
import { isFulfilled } from '@reduxjs/toolkit';
|
||||||
import type { Reducer } from 'redux';
|
import type { Reducer } from '@reduxjs/toolkit';
|
||||||
|
import { Map as ImmutableMap } from 'immutable';
|
||||||
|
|
||||||
import type { ApiRelationshipJSON } from 'mastodon/api_types/relationships';
|
import type { ApiRelationshipJSON } from 'mastodon/api_types/relationships';
|
||||||
import type { Account } from 'mastodon/models/account';
|
import type { Account } from 'mastodon/models/account';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { Record as ImmutableRecord } from 'immutable';
|
import { Record as ImmutableRecord } from 'immutable';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { accountDefaultValues } from 'mastodon/models/account';
|
import { accountDefaultValues } from 'mastodon/models/account';
|
||||||
import type { Account, AccountShape } from 'mastodon/models/account';
|
import type { Account, AccountShape } from 'mastodon/models/account';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { createSelector } from '@reduxjs/toolkit';
|
||||||
import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
import { List as ImmutableList, Map as ImmutableMap } from 'immutable';
|
||||||
import { createSelector } from 'reselect';
|
|
||||||
|
|
||||||
import { toServerSideType } from 'mastodon/utils/filters';
|
import { toServerSideType } from 'mastodon/utils/filters';
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,34 @@
|
||||||
import type { AnyAction, Middleware } from 'redux';
|
import { isAction } from '@reduxjs/toolkit';
|
||||||
|
import type { Action, Middleware } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import type { RootState } from '..';
|
import type { RootState } from '..';
|
||||||
import { showAlertForError } from '../../actions/alerts';
|
import { showAlertForError } from '../../actions/alerts';
|
||||||
|
|
||||||
const defaultFailSuffix = 'FAIL';
|
const defaultFailSuffix = 'FAIL';
|
||||||
|
const isFailedAction = new RegExp(`${defaultFailSuffix}$`, 'g');
|
||||||
|
|
||||||
export const errorsMiddleware: Middleware<unknown, RootState> =
|
interface ActionWithMaybeAlertParams extends Action {
|
||||||
|
skipAlert?: boolean;
|
||||||
|
skipNotFound?: boolean;
|
||||||
|
error?: unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isActionWithmaybeAlertParams(
|
||||||
|
action: unknown,
|
||||||
|
): action is ActionWithMaybeAlertParams {
|
||||||
|
return isAction(action);
|
||||||
|
}
|
||||||
|
|
||||||
|
export const errorsMiddleware: Middleware<Record<string, never>, RootState> =
|
||||||
({ dispatch }) =>
|
({ dispatch }) =>
|
||||||
(next) =>
|
(next) =>
|
||||||
(action: AnyAction & { skipAlert?: boolean; skipNotFound?: boolean }) => {
|
(action) => {
|
||||||
if (action.type && !action.skipAlert) {
|
if (
|
||||||
const isFail = new RegExp(`${defaultFailSuffix}$`, 'g');
|
isActionWithmaybeAlertParams(action) &&
|
||||||
|
!action.skipAlert &&
|
||||||
if (typeof action.type === 'string' && action.type.match(isFail)) {
|
action.type.match(isFailedAction)
|
||||||
dispatch(showAlertForError(action.error, action.skipNotFound));
|
) {
|
||||||
}
|
dispatch(showAlertForError(action.error, action.skipNotFound));
|
||||||
}
|
}
|
||||||
|
|
||||||
return next(action);
|
return next(action);
|
||||||
|
|
|
@ -3,9 +3,11 @@ import {
|
||||||
isPending as isThunkActionPending,
|
isPending as isThunkActionPending,
|
||||||
isFulfilled as isThunkActionFulfilled,
|
isFulfilled as isThunkActionFulfilled,
|
||||||
isRejected as isThunkActionRejected,
|
isRejected as isThunkActionRejected,
|
||||||
|
isAction,
|
||||||
} from '@reduxjs/toolkit';
|
} from '@reduxjs/toolkit';
|
||||||
|
import type { Middleware, UnknownAction } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import { showLoading, hideLoading } from 'react-redux-loading-bar';
|
import { showLoading, hideLoading } from 'react-redux-loading-bar';
|
||||||
import type { AnyAction, Middleware } from 'redux';
|
|
||||||
|
|
||||||
import type { RootState } from '..';
|
import type { RootState } from '..';
|
||||||
|
|
||||||
|
@ -19,14 +21,28 @@ const defaultTypeSuffixes: Config['promiseTypeSuffixes'] = [
|
||||||
'REJECTED',
|
'REJECTED',
|
||||||
];
|
];
|
||||||
|
|
||||||
|
interface ActionWithSkipLoading extends UnknownAction {
|
||||||
|
skipLoading: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function isActionWithSkipLoading(
|
||||||
|
action: unknown,
|
||||||
|
): action is ActionWithSkipLoading {
|
||||||
|
return (
|
||||||
|
isAction(action) &&
|
||||||
|
'skipLoading' in action &&
|
||||||
|
typeof action.skipLoading === 'boolean'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
export const loadingBarMiddleware = (
|
export const loadingBarMiddleware = (
|
||||||
config: Config = {},
|
config: Config = {},
|
||||||
): Middleware<unknown, RootState> => {
|
): Middleware<{ skipLoading?: boolean }, RootState> => {
|
||||||
const promiseTypeSuffixes = config.promiseTypeSuffixes ?? defaultTypeSuffixes;
|
const promiseTypeSuffixes = config.promiseTypeSuffixes ?? defaultTypeSuffixes;
|
||||||
|
|
||||||
return ({ dispatch }) =>
|
return ({ dispatch }) =>
|
||||||
(next) =>
|
(next) =>
|
||||||
(action: AnyAction) => {
|
(action) => {
|
||||||
let isPending = false;
|
let isPending = false;
|
||||||
let isFulfilled = false;
|
let isFulfilled = false;
|
||||||
let isRejected = false;
|
let isRejected = false;
|
||||||
|
@ -39,7 +55,7 @@ export const loadingBarMiddleware = (
|
||||||
else if (isThunkActionFulfilled(action)) isFulfilled = true;
|
else if (isThunkActionFulfilled(action)) isFulfilled = true;
|
||||||
else if (isThunkActionRejected(action)) isRejected = true;
|
else if (isThunkActionRejected(action)) isRejected = true;
|
||||||
} else if (
|
} else if (
|
||||||
action.type &&
|
isActionWithSkipLoading(action) &&
|
||||||
!action.skipLoading &&
|
!action.skipLoading &&
|
||||||
typeof action.type === 'string'
|
typeof action.type === 'string'
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import type { Middleware, AnyAction } from 'redux';
|
import { isAction } from '@reduxjs/toolkit';
|
||||||
|
import type { Middleware, UnknownAction } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import ready from 'mastodon/ready';
|
import ready from 'mastodon/ready';
|
||||||
import { assetHost } from 'mastodon/utils/config';
|
import { assetHost } from 'mastodon/utils/config';
|
||||||
|
@ -10,6 +11,21 @@ interface AudioSource {
|
||||||
type: string;
|
type: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface ActionWithMetaSound extends UnknownAction {
|
||||||
|
meta: { sound: string };
|
||||||
|
}
|
||||||
|
|
||||||
|
function isActionWithMetaSound(action: unknown): action is ActionWithMetaSound {
|
||||||
|
return (
|
||||||
|
isAction(action) &&
|
||||||
|
'meta' in action &&
|
||||||
|
typeof action.meta === 'object' &&
|
||||||
|
!!action.meta &&
|
||||||
|
'sound' in action.meta &&
|
||||||
|
typeof action.meta.sound === 'string'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const createAudio = (sources: AudioSource[]) => {
|
const createAudio = (sources: AudioSource[]) => {
|
||||||
const audio = new Audio();
|
const audio = new Audio();
|
||||||
sources.forEach(({ type, src }) => {
|
sources.forEach(({ type, src }) => {
|
||||||
|
@ -34,7 +50,10 @@ const play = (audio: HTMLAudioElement) => {
|
||||||
void audio.play();
|
void audio.play();
|
||||||
};
|
};
|
||||||
|
|
||||||
export const soundsMiddleware = (): Middleware<unknown, RootState> => {
|
export const soundsMiddleware = (): Middleware<
|
||||||
|
Record<string, never>,
|
||||||
|
RootState
|
||||||
|
> => {
|
||||||
const soundCache: Record<string, HTMLAudioElement> = {};
|
const soundCache: Record<string, HTMLAudioElement> = {};
|
||||||
|
|
||||||
void ready(() => {
|
void ready(() => {
|
||||||
|
@ -50,15 +69,15 @@ export const soundsMiddleware = (): Middleware<unknown, RootState> => {
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
return () =>
|
return () => (next) => (action) => {
|
||||||
(next) =>
|
if (isActionWithMetaSound(action)) {
|
||||||
(action: AnyAction & { meta?: { sound?: string } }) => {
|
const sound = action.meta.sound;
|
||||||
const sound = action.meta?.sound;
|
|
||||||
|
|
||||||
if (sound && Object.hasOwn(soundCache, sound)) {
|
if (sound && Object.hasOwn(soundCache, sound)) {
|
||||||
play(soundCache[sound]);
|
play(soundCache[sound]);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return next(action);
|
return next(action);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import type { TypedUseSelectorHook } from 'react-redux';
|
|
||||||
import { useDispatch, useSelector } from 'react-redux';
|
|
||||||
|
|
||||||
import { createAsyncThunk } from '@reduxjs/toolkit';
|
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||||
|
import type { TypedUseSelectorHook } from 'react-redux';
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
|
|
||||||
import type { AppDispatch, RootState } from './store';
|
import type { AppDispatch, RootState } from './store';
|
||||||
|
|
||||||
|
|
|
@ -7,8 +7,14 @@ module.exports = {
|
||||||
include: [
|
include: [
|
||||||
settings.source_path,
|
settings.source_path,
|
||||||
...settings.resolved_paths,
|
...settings.resolved_paths,
|
||||||
|
'node_modules/@reduxjs'
|
||||||
].map(p => resolve(p)),
|
].map(p => resolve(p)),
|
||||||
exclude: /node_modules/,
|
exclude: function(modulePath) {
|
||||||
|
return (
|
||||||
|
/node_modules/.test(modulePath) &&
|
||||||
|
!/@reduxjs/.test(modulePath)
|
||||||
|
);
|
||||||
|
},
|
||||||
use: [
|
use: [
|
||||||
{
|
{
|
||||||
loader: 'babel-loader',
|
loader: 'babel-loader',
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
"@github/webauthn-json": "^2.1.1",
|
"@github/webauthn-json": "^2.1.1",
|
||||||
"@material-symbols/svg-600": "^0.14.0",
|
"@material-symbols/svg-600": "^0.14.0",
|
||||||
"@rails/ujs": "^7.1.1",
|
"@rails/ujs": "^7.1.1",
|
||||||
"@reduxjs/toolkit": "^1.9.5",
|
"@reduxjs/toolkit": "^2.0.1",
|
||||||
"@svgr/webpack": "^5.5.0",
|
"@svgr/webpack": "^5.5.0",
|
||||||
"arrow-key-navigation": "^1.2.0",
|
"arrow-key-navigation": "^1.2.0",
|
||||||
"async-mutex": "^0.4.0",
|
"async-mutex": "^0.4.0",
|
||||||
|
@ -109,8 +109,8 @@
|
||||||
"react-motion": "^0.5.2",
|
"react-motion": "^0.5.2",
|
||||||
"react-notification": "^6.8.5",
|
"react-notification": "^6.8.5",
|
||||||
"react-overlays": "^5.2.1",
|
"react-overlays": "^5.2.1",
|
||||||
"react-redux": "^8.0.4",
|
"react-redux": "^9.0.4",
|
||||||
"react-redux-loading-bar": "^5.0.4",
|
"react-redux-loading-bar": "^5.0.8",
|
||||||
"react-router": "^5.3.4",
|
"react-router": "^5.3.4",
|
||||||
"react-router-dom": "^5.3.4",
|
"react-router-dom": "^5.3.4",
|
||||||
"react-router-scroll-4": "^1.0.0-beta.1",
|
"react-router-scroll-4": "^1.0.0-beta.1",
|
||||||
|
@ -119,12 +119,9 @@
|
||||||
"react-swipeable-views": "^0.14.0",
|
"react-swipeable-views": "^0.14.0",
|
||||||
"react-textarea-autosize": "^8.4.1",
|
"react-textarea-autosize": "^8.4.1",
|
||||||
"react-toggle": "^4.1.3",
|
"react-toggle": "^4.1.3",
|
||||||
"redux": "^4.2.1",
|
|
||||||
"redux-immutable": "^4.0.0",
|
"redux-immutable": "^4.0.0",
|
||||||
"redux-thunk": "^2.4.2",
|
|
||||||
"regenerator-runtime": "^0.14.0",
|
"regenerator-runtime": "^0.14.0",
|
||||||
"requestidlecallback": "^0.3.0",
|
"requestidlecallback": "^0.3.0",
|
||||||
"reselect": "^4.1.8",
|
|
||||||
"rimraf": "^5.0.1",
|
"rimraf": "^5.0.1",
|
||||||
"sass": "^1.62.1",
|
"sass": "^1.62.1",
|
||||||
"sass-loader": "^10.2.0",
|
"sass-loader": "^10.2.0",
|
||||||
|
|
104
yarn.lock
104
yarn.lock
|
@ -1483,7 +1483,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.1, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
|
"@babel/runtime@npm:^7.0.0, @babel/runtime@npm:^7.1.2, @babel/runtime@npm:^7.11.2, @babel/runtime@npm:^7.12.0, @babel/runtime@npm:^7.12.13, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.8, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.2.0, @babel/runtime@npm:^7.20.13, @babel/runtime@npm:^7.22.3, @babel/runtime@npm:^7.23.2, @babel/runtime@npm:^7.3.1, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.6.3, @babel/runtime@npm:^7.8.4, @babel/runtime@npm:^7.8.7, @babel/runtime@npm:^7.9.2":
|
||||||
version: 7.23.7
|
version: 7.23.7
|
||||||
resolution: "@babel/runtime@npm:7.23.7"
|
resolution: "@babel/runtime@npm:7.23.7"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -2302,7 +2302,7 @@ __metadata:
|
||||||
"@github/webauthn-json": "npm:^2.1.1"
|
"@github/webauthn-json": "npm:^2.1.1"
|
||||||
"@material-symbols/svg-600": "npm:^0.14.0"
|
"@material-symbols/svg-600": "npm:^0.14.0"
|
||||||
"@rails/ujs": "npm:^7.1.1"
|
"@rails/ujs": "npm:^7.1.1"
|
||||||
"@reduxjs/toolkit": "npm:^1.9.5"
|
"@reduxjs/toolkit": "npm:^2.0.1"
|
||||||
"@svgr/webpack": "npm:^5.5.0"
|
"@svgr/webpack": "npm:^5.5.0"
|
||||||
"@testing-library/jest-dom": "npm:^6.0.0"
|
"@testing-library/jest-dom": "npm:^6.0.0"
|
||||||
"@testing-library/react": "npm:^14.0.0"
|
"@testing-library/react": "npm:^14.0.0"
|
||||||
|
@ -2413,8 +2413,8 @@ __metadata:
|
||||||
react-motion: "npm:^0.5.2"
|
react-motion: "npm:^0.5.2"
|
||||||
react-notification: "npm:^6.8.5"
|
react-notification: "npm:^6.8.5"
|
||||||
react-overlays: "npm:^5.2.1"
|
react-overlays: "npm:^5.2.1"
|
||||||
react-redux: "npm:^8.0.4"
|
react-redux: "npm:^9.0.4"
|
||||||
react-redux-loading-bar: "npm:^5.0.4"
|
react-redux-loading-bar: "npm:^5.0.8"
|
||||||
react-router: "npm:^5.3.4"
|
react-router: "npm:^5.3.4"
|
||||||
react-router-dom: "npm:^5.3.4"
|
react-router-dom: "npm:^5.3.4"
|
||||||
react-router-scroll-4: "npm:^1.0.0-beta.1"
|
react-router-scroll-4: "npm:^1.0.0-beta.1"
|
||||||
|
@ -2424,12 +2424,9 @@ __metadata:
|
||||||
react-test-renderer: "npm:^18.2.0"
|
react-test-renderer: "npm:^18.2.0"
|
||||||
react-textarea-autosize: "npm:^8.4.1"
|
react-textarea-autosize: "npm:^8.4.1"
|
||||||
react-toggle: "npm:^4.1.3"
|
react-toggle: "npm:^4.1.3"
|
||||||
redux: "npm:^4.2.1"
|
|
||||||
redux-immutable: "npm:^4.0.0"
|
redux-immutable: "npm:^4.0.0"
|
||||||
redux-thunk: "npm:^2.4.2"
|
|
||||||
regenerator-runtime: "npm:^0.14.0"
|
regenerator-runtime: "npm:^0.14.0"
|
||||||
requestidlecallback: "npm:^0.3.0"
|
requestidlecallback: "npm:^0.3.0"
|
||||||
reselect: "npm:^4.1.8"
|
|
||||||
rimraf: "npm:^5.0.1"
|
rimraf: "npm:^5.0.1"
|
||||||
sass: "npm:^1.62.1"
|
sass: "npm:^1.62.1"
|
||||||
sass-loader: "npm:^10.2.0"
|
sass-loader: "npm:^10.2.0"
|
||||||
|
@ -2625,23 +2622,23 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@reduxjs/toolkit@npm:^1.9.5":
|
"@reduxjs/toolkit@npm:^2.0.1":
|
||||||
version: 1.9.7
|
version: 2.0.1
|
||||||
resolution: "@reduxjs/toolkit@npm:1.9.7"
|
resolution: "@reduxjs/toolkit@npm:2.0.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
immer: "npm:^9.0.21"
|
immer: "npm:^10.0.3"
|
||||||
redux: "npm:^4.2.1"
|
redux: "npm:^5.0.0"
|
||||||
redux-thunk: "npm:^2.4.2"
|
redux-thunk: "npm:^3.1.0"
|
||||||
reselect: "npm:^4.1.8"
|
reselect: "npm:^5.0.1"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
react: ^16.9.0 || ^17.0.0 || ^18
|
react: ^16.9.0 || ^17.0.0 || ^18
|
||||||
react-redux: ^7.2.1 || ^8.0.2
|
react-redux: ^7.2.1 || ^8.1.3 || ^9.0.0
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
react:
|
react:
|
||||||
optional: true
|
optional: true
|
||||||
react-redux:
|
react-redux:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: fa0aa4b7c6973ac87ce0ac7e45faa02c73b66c4ee0bc950d178494539a42a1bb908d109297102458b7ea14d5e7dae356e7a7ce9a1b9849b0e8451e6dd70fca9c
|
checksum: 161b9b8e11d9688890ab97b604a4c10c0d41b1369425a5fa821586932db4cd5a391d15799732b3612e6120a6336458ff577ff254219315c05ecd68da5d15fd79
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -9152,10 +9149,10 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"immer@npm:^9.0.21":
|
"immer@npm:^10.0.3":
|
||||||
version: 9.0.21
|
version: 10.0.3
|
||||||
resolution: "immer@npm:9.0.21"
|
resolution: "immer@npm:10.0.3"
|
||||||
checksum: 03ea3ed5d4d72e8bd428df4a38ad7e483ea8308e9a113d3b42e0ea2cc0cc38340eb0a6aca69592abbbf047c685dbda04e3d34bf2ff438ab57339ed0a34cc0a05
|
checksum: 282a4f8479a40f7d12b2b3243c095e3e892bf99058e2ffcdd6b8e9fd143e6a90f2717ab9b6c8b97c927ffb8054465c8f647056f41660dbfd672e240cf1063503
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -13128,7 +13125,17 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.15, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4":
|
"postcss-selector-parser@npm:^6.0.11, postcss-selector-parser@npm:^6.0.13, postcss-selector-parser@npm:^6.0.2, postcss-selector-parser@npm:^6.0.4":
|
||||||
|
version: 6.0.13
|
||||||
|
resolution: "postcss-selector-parser@npm:6.0.13"
|
||||||
|
dependencies:
|
||||||
|
cssesc: "npm:^3.0.0"
|
||||||
|
util-deprecate: "npm:^1.0.2"
|
||||||
|
checksum: 51f099b27f7c7198ea1826470ef0adfa58b3bd3f59b390fda123baa0134880a5fa9720137b6009c4c1373357b144f700b0edac73335d0067422063129371444e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"postcss-selector-parser@npm:^6.0.15":
|
||||||
version: 6.0.15
|
version: 6.0.15
|
||||||
resolution: "postcss-selector-parser@npm:6.0.15"
|
resolution: "postcss-selector-parser@npm:6.0.15"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -13717,7 +13724,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"react-redux-loading-bar@npm:^5.0.4":
|
"react-redux-loading-bar@npm:^5.0.8":
|
||||||
version: 5.0.8
|
version: 5.0.8
|
||||||
resolution: "react-redux-loading-bar@npm:5.0.8"
|
resolution: "react-redux-loading-bar@npm:5.0.8"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -13732,35 +13739,25 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"react-redux@npm:^8.0.4":
|
"react-redux@npm:^9.0.4":
|
||||||
version: 8.1.3
|
version: 9.0.4
|
||||||
resolution: "react-redux@npm:8.1.3"
|
resolution: "react-redux@npm:9.0.4"
|
||||||
dependencies:
|
dependencies:
|
||||||
"@babel/runtime": "npm:^7.12.1"
|
|
||||||
"@types/hoist-non-react-statics": "npm:^3.3.1"
|
|
||||||
"@types/use-sync-external-store": "npm:^0.0.3"
|
"@types/use-sync-external-store": "npm:^0.0.3"
|
||||||
hoist-non-react-statics: "npm:^3.3.2"
|
|
||||||
react-is: "npm:^18.0.0"
|
|
||||||
use-sync-external-store: "npm:^1.0.0"
|
use-sync-external-store: "npm:^1.0.0"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
"@types/react": ^16.8 || ^17.0 || ^18.0
|
"@types/react": ^18.2.25
|
||||||
"@types/react-dom": ^16.8 || ^17.0 || ^18.0
|
react: ^18.0
|
||||||
react: ^16.8 || ^17.0 || ^18.0
|
react-native: ">=0.69"
|
||||||
react-dom: ^16.8 || ^17.0 || ^18.0
|
redux: ^5.0.0
|
||||||
react-native: ">=0.59"
|
|
||||||
redux: ^4 || ^5.0.0-beta.0
|
|
||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
"@types/react":
|
"@types/react":
|
||||||
optional: true
|
optional: true
|
||||||
"@types/react-dom":
|
|
||||||
optional: true
|
|
||||||
react-dom:
|
|
||||||
optional: true
|
|
||||||
react-native:
|
react-native:
|
||||||
optional: true
|
optional: true
|
||||||
redux:
|
redux:
|
||||||
optional: true
|
optional: true
|
||||||
checksum: 64c8be2765568dc66a3c442a41dd0ed74fe048d5ceb7a4fe72e5bac3d3687996a7115f57b5156af7406521087065a0e60f9194318c8ca99c55e9ce48558980ce
|
checksum: 23af10014b129aeb051de729bde01de21175170b860deefb7ad83483feab5816253f770a4cea93333fc22a53ac9ac699b27f5c3705c388dab53dbcb2906a571a
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
@ -14063,16 +14060,16 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"redux-thunk@npm:^2.4.2":
|
"redux-thunk@npm:^3.1.0":
|
||||||
version: 2.4.2
|
version: 3.1.0
|
||||||
resolution: "redux-thunk@npm:2.4.2"
|
resolution: "redux-thunk@npm:3.1.0"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
redux: ^4
|
redux: ^5.0.0
|
||||||
checksum: e202d6ef7dfa7df08ed24cb221aa89d6c84dbaa7d65fe90dbd8e826d0c10d801f48388f9a7598a4fd970ecbc93d335014570a61ca7bc8bf569eab5de77b31a3c
|
checksum: 21557f6a30e1b2e3e470933247e51749be7f1d5a9620069a3125778675ce4d178d84bdee3e2a0903427a5c429e3aeec6d4df57897faf93eb83455bc1ef7b66fd
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"redux@npm:^4.0.0, redux@npm:^4.2.1":
|
"redux@npm:^4.0.0":
|
||||||
version: 4.2.1
|
version: 4.2.1
|
||||||
resolution: "redux@npm:4.2.1"
|
resolution: "redux@npm:4.2.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -14081,6 +14078,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"redux@npm:^5.0.0":
|
||||||
|
version: 5.0.1
|
||||||
|
resolution: "redux@npm:5.0.1"
|
||||||
|
checksum: b10c28357194f38e7d53b760ed5e64faa317cc63de1fb95bc5d9e127fab956392344368c357b8e7a9bedb0c35b111e7efa522210cfdc3b3c75e5074718e9069c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"reflect.getprototypeof@npm:^1.0.4":
|
"reflect.getprototypeof@npm:^1.0.4":
|
||||||
version: 1.0.4
|
version: 1.0.4
|
||||||
resolution: "reflect.getprototypeof@npm:1.0.4"
|
resolution: "reflect.getprototypeof@npm:1.0.4"
|
||||||
|
@ -14250,10 +14254,10 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"reselect@npm:^4.1.8":
|
"reselect@npm:^5.0.1":
|
||||||
version: 4.1.8
|
version: 5.0.1
|
||||||
resolution: "reselect@npm:4.1.8"
|
resolution: "reselect@npm:5.0.1"
|
||||||
checksum: 06a305a504affcbb67dd0561ddc8306b35796199c7e15b38934c80606938a021eadcf68cfd58e7bb5e17786601c37602a3362a4665c7bf0a96c1041ceee9d0b7
|
checksum: 0724b4555cd6411849de334a75177780f127af849eb71c4b709966d07ade8090d125c0c926dc6cf936866d23ebadda6aad1da93cd8340525323b889f25d56d51
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue