[Glitch] Add stricter ESLint rules for Typescript files

Port 5eeb40bdbe to glitch-soc

Signed-off-by: Claire <claire.github-309c@sitedethib.com>
shrike
Renaud Chaput 2023-05-10 12:59:29 +02:00 committed by Claire
parent e8fc445e14
commit e6a7cfd12e
33 changed files with 171 additions and 123 deletions

View File

@ -319,7 +319,7 @@ module.exports = {
}, },
// Internal packages // Internal packages
{ {
pattern: '{mastodon/**}', pattern: '{mastodon/**,flavours/glitch-soc/**}',
group: 'internal', group: 'internal',
position: 'after', position: 'after',
}, },

View File

@ -1,8 +1,9 @@
import { createAction } from '@reduxjs/toolkit'; import { createAction } from '@reduxjs/toolkit';
import type { LayoutType } from '../is_mobile'; import type { LayoutType } from '../is_mobile';
type ChangeLayoutPayload = { interface ChangeLayoutPayload {
layout: LayoutType; layout: LayoutType;
}; }
export const changeLayout = export const changeLayout =
createAction<ChangeLayoutPayload>('APP_LAYOUT_CHANGE'); createAction<ChangeLayoutPayload>('APP_LAYOUT_CHANGE');

View File

@ -1,12 +1,12 @@
import api from '../api'; import api from '../api';
import { importFetchedStatuses } from './importer'; import { importFetchedStatuses } from './importer';
import { me } from 'flavours/glitch/initial_state';
export const PINNED_STATUSES_FETCH_REQUEST = 'PINNED_STATUSES_FETCH_REQUEST'; export const PINNED_STATUSES_FETCH_REQUEST = 'PINNED_STATUSES_FETCH_REQUEST';
export const PINNED_STATUSES_FETCH_SUCCESS = 'PINNED_STATUSES_FETCH_SUCCESS'; export const PINNED_STATUSES_FETCH_SUCCESS = 'PINNED_STATUSES_FETCH_SUCCESS';
export const PINNED_STATUSES_FETCH_FAIL = 'PINNED_STATUSES_FETCH_FAIL'; export const PINNED_STATUSES_FETCH_FAIL = 'PINNED_STATUSES_FETCH_FAIL';
import { me } from 'flavours/glitch/initial_state';
export function fetchPinnedStatuses() { export function fetchPinnedStatuses() {
return (dispatch, getState) => { return (dispatch, getState) => {
dispatch(fetchPinnedStatusesRequest()); dispatch(fetchPinnedStatusesRequest());

View File

@ -1,8 +1,11 @@
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import ShortNumber from './short_number';
import { TransitionMotion, spring } from 'react-motion'; import { TransitionMotion, spring } from 'react-motion';
import { reduceMotion } from '../initial_state'; import { reduceMotion } from '../initial_state';
import ShortNumber from './short_number';
const obfuscatedCount = (count: number) => { const obfuscatedCount = (count: number) => {
if (count < 0) { if (count < 0) {
return 0; return 0;
@ -13,10 +16,10 @@ const obfuscatedCount = (count: number) => {
} }
}; };
type Props = { interface Props {
value: number; value: number;
obfuscate?: boolean; obfuscate?: boolean;
}; }
export const AnimatedNumber: React.FC<Props> = ({ value, obfuscate }) => { export const AnimatedNumber: React.FC<Props> = ({ value, obfuscate }) => {
const [previousValue, setPreviousValue] = useState(value); const [previousValue, setPreviousValue] = useState(value);
const [direction, setDirection] = useState<1 | -1>(1); const [direction, setDirection] = useState<1 | -1>(1);
@ -64,7 +67,11 @@ export const AnimatedNumber: React.FC<Props> = ({ value, obfuscate }) => {
transform: `translateY(${style.y * 100}%)`, transform: `translateY(${style.y * 100}%)`,
}} }}
> >
{obfuscate ? obfuscatedCount(data) : <ShortNumber value={data} />} {obfuscate ? (
obfuscatedCount(data as number)
) : (
<ShortNumber value={data as number} />
)}
</span> </span>
))} ))}
</span> </span>

View File

@ -1,16 +1,18 @@
import * as React from 'react'; import * as React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import { autoPlayGif } from 'flavours/glitch/initial_state';
import { useHovering } from 'flavours/glitch/hooks/useHovering'; import { useHovering } from 'flavours/glitch/hooks/useHovering';
import { autoPlayGif } from 'flavours/glitch/initial_state';
import type { Account } from 'flavours/glitch/types/resources'; import type { Account } from 'flavours/glitch/types/resources';
type Props = { interface Props {
account: Account | undefined; account: Account | undefined;
className?: string; className?: string;
size: number; size: number;
style?: React.CSSProperties; style?: React.CSSProperties;
inline?: boolean; inline?: boolean;
}; }
export const Avatar: React.FC<Props> = ({ export const Avatar: React.FC<Props> = ({
account, account,

View File

@ -1,14 +1,14 @@
import { decode } from 'blurhash';
import React, { useRef, useEffect } from 'react'; import React, { useRef, useEffect } from 'react';
type Props = { import { decode } from 'blurhash';
interface Props extends React.HTMLAttributes<HTMLCanvasElement> {
hash: string; hash: string;
width?: number; width?: number;
height?: number; height?: number;
dummy?: boolean; // Whether dummy mode is enabled. If enabled, nothing is rendered and canvas left untouched dummy?: boolean; // Whether dummy mode is enabled. If enabled, nothing is rendered and canvas left untouched
children?: never; children?: never;
[key: string]: any; }
};
const Blurhash: React.FC<Props> = ({ const Blurhash: React.FC<Props> = ({
hash, hash,
width = 32, width = 32,
@ -21,6 +21,7 @@ const Blurhash: React.FC<Props> = ({
useEffect(() => { useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const canvas = canvasRef.current!; const canvas = canvasRef.current!;
// eslint-disable-next-line no-self-assign // eslint-disable-next-line no-self-assign
canvas.width = canvas.width; // resets canvas canvas.width = canvas.width; // resets canvas

View File

@ -1,6 +1,9 @@
import React, { useCallback } from 'react'; import React, { useCallback } from 'react';
import type { InjectedIntl } from 'react-intl';
import { defineMessages, injectIntl } from 'react-intl';
import { IconButton } from './icon_button'; import { IconButton } from './icon_button';
import { InjectedIntl, defineMessages, injectIntl } from 'react-intl';
const messages = defineMessages({ const messages = defineMessages({
unblockDomain: { unblockDomain: {
@ -9,11 +12,11 @@ const messages = defineMessages({
}, },
}); });
type Props = { interface Props {
domain: string; domain: string;
onUnblockDomain: (domain: string) => void; onUnblockDomain: (domain: string) => void;
intl: InjectedIntl; intl: InjectedIntl;
}; }
const _Domain: React.FC<Props> = ({ domain, onUnblockDomain, intl }) => { const _Domain: React.FC<Props> = ({ domain, onUnblockDomain, intl }) => {
const handleDomainUnblock = useCallback(() => { const handleDomainUnblock = useCallback(() => {
onUnblockDomain(domain); onUnblockDomain(domain);

View File

@ -1,6 +1,6 @@
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
type Props = { interface Props {
src: string; src: string;
key: string; key: string;
alt?: string; alt?: string;
@ -8,7 +8,7 @@ type Props = {
width: number; width: number;
height: number; height: number;
onClick?: () => void; onClick?: () => void;
}; }
export const GIFV: React.FC<Props> = ({ export const GIFV: React.FC<Props> = ({
src, src,

View File

@ -1,13 +1,14 @@
import React from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
type Props = { interface Props extends React.HTMLAttributes<HTMLImageElement> {
id: string; id: string;
className?: string; className?: string;
fixedWidth?: boolean; fixedWidth?: boolean;
children?: never; children?: never;
[key: string]: any; }
};
export const Icon: React.FC<Props> = ({ export const Icon: React.FC<Props> = ({
id, id,
className, className,

View File

@ -1,9 +1,11 @@
import React from 'react'; import React from 'react';
import classNames from 'classnames';
import { Icon } from './icon';
import { AnimatedNumber } from './animated_number';
type Props = { import classNames from 'classnames';
import { AnimatedNumber } from './animated_number';
import { Icon } from './icon';
interface Props {
className?: string; className?: string;
title: string; title: string;
icon: string; icon: string;
@ -26,11 +28,11 @@ type Props = {
obfuscateCount?: boolean; obfuscateCount?: boolean;
href?: string; href?: string;
ariaHidden: boolean; ariaHidden: boolean;
}; }
type States = { interface States {
activate: boolean; activate: boolean;
deactivate: boolean; deactivate: boolean;
}; }
export class IconButton extends React.PureComponent<Props, States> { export class IconButton extends React.PureComponent<Props, States> {
static defaultProps = { static defaultProps = {
size: 18, size: 18,

View File

@ -1,14 +1,15 @@
import React from 'react'; import React from 'react';
import { Icon } from './icon'; import { Icon } from './icon';
const formatNumber = (num: number): number | string => (num > 40 ? '40+' : num); const formatNumber = (num: number): number | string => (num > 40 ? '40+' : num);
type Props = { interface Props {
id: string; id: string;
count: number; count: number;
issueBadge: boolean; issueBadge: boolean;
className: string; className: string;
}; }
export const IconWithBadge: React.FC<Props> = ({ export const IconWithBadge: React.FC<Props> = ({
id, id,
count, count,

View File

@ -1,4 +1,5 @@
import React from 'react'; import React from 'react';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';
export const NotSignedInIndicator: React.FC = () => ( export const NotSignedInIndicator: React.FC = () => (

View File

@ -1,13 +1,14 @@
import React from 'react'; import React from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
type Props = { interface Props {
value: string; value: string;
checked: boolean; checked: boolean;
name: string; name: string;
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void; onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
label: React.ReactNode; label: React.ReactNode;
}; }
export const RadioButton: React.FC<Props> = ({ export const RadioButton: React.FC<Props> = ({
name, name,

View File

@ -1,5 +1,7 @@
import React from 'react'; import React from 'react';
import { injectIntl, defineMessages, InjectedIntl } from 'react-intl';
import type { InjectedIntl } from 'react-intl';
import { injectIntl, defineMessages } from 'react-intl';
const messages = defineMessages({ const messages = defineMessages({
today: { id: 'relative_time.today', defaultMessage: 'today' }, today: { id: 'relative_time.today', defaultMessage: 'today' },
@ -187,16 +189,16 @@ const timeRemainingString = (
return relativeTime; return relativeTime;
}; };
type Props = { interface Props {
intl: InjectedIntl; intl: InjectedIntl;
timestamp: string; timestamp: string;
year: number; year: number;
futureDate?: boolean; futureDate?: boolean;
short?: boolean; short?: boolean;
}; }
type States = { interface States {
now: number; now: number;
}; }
class RelativeTimestamp extends React.Component<Props, States> { class RelativeTimestamp extends React.Component<Props, States> {
state = { state = {
now: this.props.intl.now(), now: this.props.intl.now(),

View File

@ -1,13 +1,15 @@
import React, { useCallback, useState } from 'react'; import React, { useCallback, useState } from 'react';
import { Blurhash } from './blurhash';
import classNames from 'classnames'; import classNames from 'classnames';
type Props = { import { Blurhash } from './blurhash';
interface Props {
src: string; src: string;
srcSet?: string; srcSet?: string;
blurhash?: string; blurhash?: string;
className?: string; className?: string;
}; }
export const ServerHeroImage: React.FC<Props> = ({ export const ServerHeroImage: React.FC<Props> = ({
src, src,

View File

@ -3,7 +3,7 @@ import { connect } from 'react-redux';
import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePropTypes from 'react-immutable-proptypes';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { lookupAccount, fetchAccount } from 'flavours/glitch/actions/accounts'; import { lookupAccount, fetchAccount } from 'flavours/glitch/actions/accounts';
import { expandAccountFeaturedTimeline, expandAccountTimeline } from 'flavours/glitch/actions/timelines'; import { expandAccountFeaturedTimeline, expandAccountTimeline } from '../../actions/timelines';
import StatusList from '../../components/status_list'; import StatusList from '../../components/status_list';
import LoadingIndicator from '../../components/loading_indicator'; import LoadingIndicator from '../../components/loading_indicator';
import Column from '../ui/components/column'; import Column from '../ui/components/column';

View File

@ -18,7 +18,7 @@ import {
BookmarkedStatuses, BookmarkedStatuses,
ListTimeline, ListTimeline,
Directory, Directory,
} from '../../ui/util/async-components'; } from '../util/async-components';
import ComposePanel from './compose_panel'; import ComposePanel from './compose_panel';
import NavigationPanel from './navigation_panel'; import NavigationPanel from './navigation_panel';

View File

@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
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 classNames from 'classnames'; import classNames from 'classnames';
import { changeUploadCompose, uploadThumbnail, onChangeMediaDescription, onChangeMediaFocus } from 'flavours/glitch/actions/compose'; import { changeUploadCompose, uploadThumbnail, onChangeMediaDescription, onChangeMediaFocus } from '../../../actions/compose';
import Video, { getPointerPosition } from 'flavours/glitch/features/video'; import Video, { getPointerPosition } from 'flavours/glitch/features/video';
import { FormattedMessage, defineMessages, injectIntl } from 'react-intl'; import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
import { IconButton } from 'flavours/glitch/components/icon_button'; import { IconButton } from 'flavours/glitch/components/icon_button';

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Motion from '../../ui/util/optional_motion'; import Motion from '../util/optional_motion';
import spring from 'react-motion/lib/spring'; import spring from 'react-motion/lib/spring';
import { FormattedMessage } from 'react-intl'; import { FormattedMessage } from 'react-intl';

View File

@ -64,7 +64,7 @@ import Header from './components/header';
// Dummy import, to make sure that <Status /> ends up in the application bundle. // Dummy import, to make sure that <Status /> ends up in the application bundle.
// Without this it ends up in ~8 very commonly used bundles. // Without this it ends up in ~8 very commonly used bundles.
import '../../../glitch/components/status'; import "../../components/status";
const messages = defineMessages({ const messages = defineMessages({
beforeUnload: { id: 'ui.beforeunload', defaultMessage: 'Your draft will be lost if you leave Mastodon.' }, beforeUnload: { id: 'ui.beforeunload', defaultMessage: 'Your draft will be lost if you leave Mastodon.' },

View File

@ -1,4 +1,5 @@
import { supportsPassiveEvents } from 'detect-passive-events'; import { supportsPassiveEvents } from 'detect-passive-events';
import { forceSingleColumn } from 'flavours/glitch/initial_state'; import { forceSingleColumn } from 'flavours/glitch/initial_state';
const LAYOUT_BREAKPOINT = 630; const LAYOUT_BREAKPOINT = 630;

View File

@ -1,9 +1,9 @@
import 'packs/public-path'; import 'packs/public-path';
import { start } from '@rails/ujs'; import { start } from '@rails/ujs';
start();
import 'flavours/glitch/styles/index.scss'; import 'flavours/glitch/styles/index.scss';
start();
// This ensures that webpack compiles our images. // This ensures that webpack compiles our images.
require.context('../images', true); require.context('../images', true);

View File

@ -10,8 +10,13 @@ if (!HTMLCanvasElement.prototype.toBlob) {
const BASE64_MARKER = ';base64,'; const BASE64_MARKER = ';base64,';
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', { Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
value(callback: BlobCallback, type = 'image/png', quality: any) { value: function (
const dataURL = this.toDataURL(type, quality); this: HTMLCanvasElement,
callback: BlobCallback,
type = 'image/png',
quality: unknown
) {
const dataURL: string = this.toDataURL(type, quality);
let data; let data;
if (dataURL.indexOf(BASE64_MARKER) >= 0) { if (dataURL.indexOf(BASE64_MARKER) >= 0) {

View File

@ -1,48 +1,49 @@
import { combineReducers } from 'redux-immutable';
import dropdown_menu from './dropdown_menu';
import timelines from './timelines';
import meta from './meta';
import alerts from './alerts';
import { loadingBarReducer } from 'react-redux-loading-bar'; import { loadingBarReducer } from 'react-redux-loading-bar';
import modal from './modal'; import { combineReducers } from 'redux-immutable';
import user_lists from './user_lists';
import domain_lists from './domain_lists'; import account_notes from './account_notes';
import accounts from './accounts'; import accounts from './accounts';
import accounts_counters from './accounts_counters'; import accounts_counters from './accounts_counters';
import statuses from './statuses'; import accounts_map from './accounts_map';
import relationships from './relationships'; import alerts from './alerts';
import settings from './settings'; import announcements from './announcements';
import local_settings from './local_settings';
import push_notifications from './push_notifications';
import status_lists from './status_lists';
import mutes from './mutes';
import blocks from './blocks'; import blocks from './blocks';
import server from './server';
import boosts from './boosts'; import boosts from './boosts';
import contexts from './contexts';
import compose from './compose'; import compose from './compose';
import search from './search'; import contexts from './contexts';
import media_attachments from './media_attachments';
import notifications from './notifications';
import height_cache from './height_cache';
import custom_emojis from './custom_emojis';
import lists from './lists';
import listEditor from './list_editor';
import listAdder from './list_adder';
import filters from './filters';
import conversations from './conversations'; import conversations from './conversations';
import suggestions from './suggestions'; import custom_emojis from './custom_emojis';
import domain_lists from './domain_lists';
import dropdown_menu from './dropdown_menu';
import filters from './filters';
import followed_tags from './followed_tags';
import height_cache from './height_cache';
import history from './history';
import listAdder from './list_adder';
import listEditor from './list_editor';
import lists from './lists';
import local_settings from './local_settings';
import markers from './markers';
import media_attachments from './media_attachments';
import meta from './meta';
import modal from './modal';
import mutes from './mutes';
import notifications from './notifications';
import picture_in_picture from './picture_in_picture';
import pinnedAccountsEditor from './pinned_accounts_editor'; import pinnedAccountsEditor from './pinned_accounts_editor';
import polls from './polls'; import polls from './polls';
import trends from './trends'; import push_notifications from './push_notifications';
import announcements from './announcements'; import relationships from './relationships';
import markers from './markers'; import search from './search';
import account_notes from './account_notes'; import server from './server';
import picture_in_picture from './picture_in_picture'; import settings from './settings';
import accounts_map from './accounts_map'; import status_lists from './status_lists';
import history from './history'; import statuses from './statuses';
import suggestions from './suggestions';
import tags from './tags'; import tags from './tags';
import followed_tags from './followed_tags'; import timelines from './timelines';
import trends from './trends';
import user_lists from './user_lists';
const reducers = { const reducers = {
announcements, announcements,

View File

@ -2,13 +2,13 @@ import {
MARKERS_SUBMIT_SUCCESS, MARKERS_SUBMIT_SUCCESS,
} from '../actions/markers'; } from '../actions/markers';
import { Map as ImmutableMap } from 'immutable';
const initialState = ImmutableMap({ const initialState = ImmutableMap({
home: '0', home: '0',
notifications: '0', notifications: '0',
}); });
import { Map as ImmutableMap } from 'immutable';
export default function markers(state = initialState, action) { export default function markers(state = initialState, action) {
switch(action.type) { switch(action.type) {
case MARKERS_SUBMIT_SUCCESS: case MARKERS_SUBMIT_SUCCESS:

View File

@ -1,9 +1,13 @@
import type { TypedUseSelectorHook } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit'; import { configureStore } from '@reduxjs/toolkit';
import { rootReducer } from '../reducers'; import { rootReducer } from '../reducers';
import { loadingBarMiddleware } from './middlewares/loading_bar';
import { errorsMiddleware } from './middlewares/errors'; import { errorsMiddleware } from './middlewares/errors';
import { loadingBarMiddleware } from './middlewares/loading_bar';
import { soundsMiddleware } from './middlewares/sounds'; import { soundsMiddleware } from './middlewares/sounds';
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
export const store = configureStore({ export const store = configureStore({
reducer: rootReducer, reducer: rootReducer,

View File

@ -1,17 +1,19 @@
import { Middleware } from 'redux'; import type { AnyAction, Middleware } from 'redux';
import { showAlertForError } from 'flavours/glitch/actions/alerts'; import { showAlertForError } from 'flavours/glitch/actions/alerts';
import { RootState } from '..';
import type { RootState } from '..';
const defaultFailSuffix = 'FAIL'; const defaultFailSuffix = 'FAIL';
export const errorsMiddleware: Middleware<Record<string, never>, RootState> = export const errorsMiddleware: Middleware<Record<string, never>, RootState> =
({ dispatch }) => ({ dispatch }) =>
(next) => (next) =>
(action) => { (action: AnyAction & { skipAlert?: boolean; skipNotFound?: boolean }) => {
if (action.type && !action.skipAlert) { if (action.type && !action.skipAlert) {
const isFail = new RegExp(`${defaultFailSuffix}$`, 'g'); const isFail = new RegExp(`${defaultFailSuffix}$`, 'g');
if (action.type.match(isFail)) { if (typeof action.type === 'string' && action.type.match(isFail)) {
dispatch(showAlertForError(action.error, action.skipNotFound)); dispatch(showAlertForError(action.error, action.skipNotFound));
} }
} }

View File

@ -1,6 +1,7 @@
import { showLoading, hideLoading } from 'react-redux-loading-bar'; import { showLoading, hideLoading } from 'react-redux-loading-bar';
import { Middleware } from 'redux'; import type { AnyAction, Middleware } from 'redux';
import { RootState } from '..';
import type { RootState } from '..';
interface Config { interface Config {
promiseTypeSuffixes?: string[]; promiseTypeSuffixes?: string[];
@ -19,7 +20,7 @@ export const loadingBarMiddleware = (
return ({ dispatch }) => return ({ dispatch }) =>
(next) => (next) =>
(action) => { (action: AnyAction) => {
if (action.type && !action.skipLoading) { if (action.type && !action.skipLoading) {
const [PENDING, FULFILLED, REJECTED] = promiseTypeSuffixes; const [PENDING, FULFILLED, REJECTED] = promiseTypeSuffixes;
@ -27,13 +28,15 @@ export const loadingBarMiddleware = (
const isFulfilled = new RegExp(`${FULFILLED}$`, 'g'); const isFulfilled = new RegExp(`${FULFILLED}$`, 'g');
const isRejected = new RegExp(`${REJECTED}$`, 'g'); const isRejected = new RegExp(`${REJECTED}$`, 'g');
if (action.type.match(isPending)) { if (typeof action.type === 'string') {
dispatch(showLoading()); if (action.type.match(isPending)) {
} else if ( dispatch(showLoading());
action.type.match(isFulfilled) || } else if (
action.type.match(isRejected) action.type.match(isFulfilled) ||
) { action.type.match(isRejected)
dispatch(hideLoading()); ) {
dispatch(hideLoading());
}
} }
} }

View File

@ -1,5 +1,6 @@
import { Middleware, AnyAction } from 'redux'; import type { Middleware, AnyAction } from 'redux';
import { RootState } from '..';
import type { RootState } from '..';
interface AudioSource { interface AudioSource {
src: string; src: string;
@ -27,7 +28,7 @@ const play = (audio: HTMLAudioElement) => {
} }
} }
audio.play(); void audio.play();
}; };
export const soundsMiddleware = (): Middleware< export const soundsMiddleware = (): Middleware<
@ -47,13 +48,15 @@ export const soundsMiddleware = (): Middleware<
]), ]),
}; };
return () => (next) => (action: AnyAction) => { return () =>
const sound = action?.meta?.sound; (next) =>
(action: AnyAction & { meta?: { sound?: string } }) => {
const sound = action?.meta?.sound;
if (sound && soundCache[sound]) { if (sound && soundCache[sound]) {
play(soundCache[sound]); play(soundCache[sound]);
} }
return next(action); return next(action);
}; };
}; };

View File

@ -12,7 +12,7 @@ type AccountField = Record<{
verified_at: string | null; verified_at: string | null;
}>; }>;
type AccountApiResponseValues = { interface AccountApiResponseValues {
acct: string; acct: string;
avatar: string; avatar: string;
avatar_static: string; avatar_static: string;
@ -34,7 +34,7 @@ type AccountApiResponseValues = {
statuses_count: number; statuses_count: number;
url: string; url: string;
username: string; username: string;
}; }
type NormalizedAccountField = Record<{ type NormalizedAccountField = Record<{
name_emojified: string; name_emojified: string;
@ -42,12 +42,12 @@ type NormalizedAccountField = Record<{
value_plain: string; value_plain: string;
}>; }>;
type NormalizedAccountValues = { interface NormalizedAccountValues {
display_name_html: string; display_name_html: string;
fields: NormalizedAccountField[]; fields: NormalizedAccountField[];
note_emojified: string; note_emojified: string;
note_plain: string; note_plain: string;
}; }
export type Account = Record< export type Account = Record<
AccountApiResponseValues & NormalizedAccountValues AccountApiResponseValues & NormalizedAccountValues

View File

@ -170,7 +170,7 @@ const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) =
.catch(reject); .catch(reject);
}); });
export default inputFile => new Promise((resolve) => { const resizeFile = (inputFile) => new Promise((resolve) => {
if (!inputFile.type.match(/image.*/) || inputFile.type === 'image/gif') { if (!inputFile.type.match(/image.*/) || inputFile.type === 'image/gif') {
resolve(inputFile); resolve(inputFile);
return; return;
@ -187,3 +187,5 @@ export default inputFile => new Promise((resolve) => {
.catch(() => resolve(inputFile)); .catch(() => resolve(inputFile));
}).catch(() => resolve(inputFile)); }).catch(() => resolve(inputFile));
}); });
export default resizeFile;

View File

@ -1,8 +1,9 @@
export function uuid(a?: string): string { export function uuid(a?: string): string {
return a return a
? ( ? (
(a as any as number) ^ (a as unknown as number) ^
((Math.random() * 16) >> ((a as any as number) / 4)) ((Math.random() * 16) >> ((a as unknown as number) / 4))
).toString(16) ).toString(16)
: ('' + 1e7 + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, uuid); : // eslint-disable-next-line @typescript-eslint/restrict-plus-operands
('' + 1e7 + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, uuid);
} }

View File

@ -12,6 +12,8 @@
"baseUrl": "./", "baseUrl": "./",
"paths": { "paths": {
"locales": ["app/javascript/locales"], "locales": ["app/javascript/locales"],
"styles/*": ["app/javascript/styles/*"],
"packs/public-path": ["app/javascript/packs/public-path"],
"flavours/glitch": ["app/javascript/flavours/glitch"], "flavours/glitch": ["app/javascript/flavours/glitch"],
"flavours/glitch/*": ["app/javascript/flavours/glitch/*"], "flavours/glitch/*": ["app/javascript/flavours/glitch/*"],
"mastodon": ["app/javascript/mastodon"], "mastodon": ["app/javascript/mastodon"],