[Glitch] Add stricter ESLint rules for Typescript files
Port 5eeb40bdbe to glitch-soc
Signed-off-by: Claire <claire.github-309c@sitedethib.com>
			
			
This commit is contained in:
		@@ -319,7 +319,7 @@ module.exports = {
 | 
			
		||||
              },
 | 
			
		||||
              // Internal packages
 | 
			
		||||
              {
 | 
			
		||||
                pattern: '{mastodon/**}',
 | 
			
		||||
                pattern: '{mastodon/**,flavours/glitch-soc/**}',
 | 
			
		||||
                group: 'internal',
 | 
			
		||||
                position: 'after',
 | 
			
		||||
              },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,9 @@
 | 
			
		||||
import { createAction } from '@reduxjs/toolkit';
 | 
			
		||||
 | 
			
		||||
import type { LayoutType } from '../is_mobile';
 | 
			
		||||
 | 
			
		||||
type ChangeLayoutPayload = {
 | 
			
		||||
interface ChangeLayoutPayload {
 | 
			
		||||
  layout: LayoutType;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
export const changeLayout =
 | 
			
		||||
  createAction<ChangeLayoutPayload>('APP_LAYOUT_CHANGE');
 | 
			
		||||
 
 | 
			
		||||
@@ -1,12 +1,12 @@
 | 
			
		||||
import api from '../api';
 | 
			
		||||
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_SUCCESS = 'PINNED_STATUSES_FETCH_SUCCESS';
 | 
			
		||||
export const PINNED_STATUSES_FETCH_FAIL = 'PINNED_STATUSES_FETCH_FAIL';
 | 
			
		||||
 | 
			
		||||
import { me } from 'flavours/glitch/initial_state';
 | 
			
		||||
 | 
			
		||||
export function fetchPinnedStatuses() {
 | 
			
		||||
  return (dispatch, getState) => {
 | 
			
		||||
    dispatch(fetchPinnedStatusesRequest());
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,11 @@
 | 
			
		||||
import React, { useCallback, useState } from 'react';
 | 
			
		||||
import ShortNumber from './short_number';
 | 
			
		||||
 | 
			
		||||
import { TransitionMotion, spring } from 'react-motion';
 | 
			
		||||
 | 
			
		||||
import { reduceMotion } from '../initial_state';
 | 
			
		||||
 | 
			
		||||
import ShortNumber from './short_number';
 | 
			
		||||
 | 
			
		||||
const obfuscatedCount = (count: number) => {
 | 
			
		||||
  if (count < 0) {
 | 
			
		||||
    return 0;
 | 
			
		||||
@@ -13,10 +16,10 @@ const obfuscatedCount = (count: number) => {
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
interface Props {
 | 
			
		||||
  value: number;
 | 
			
		||||
  obfuscate?: boolean;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
export const AnimatedNumber: React.FC<Props> = ({ value, obfuscate }) => {
 | 
			
		||||
  const [previousValue, setPreviousValue] = useState(value);
 | 
			
		||||
  const [direction, setDirection] = useState<1 | -1>(1);
 | 
			
		||||
@@ -64,7 +67,11 @@ export const AnimatedNumber: React.FC<Props> = ({ value, obfuscate }) => {
 | 
			
		||||
                transform: `translateY(${style.y * 100}%)`,
 | 
			
		||||
              }}
 | 
			
		||||
            >
 | 
			
		||||
              {obfuscate ? obfuscatedCount(data) : <ShortNumber value={data} />}
 | 
			
		||||
              {obfuscate ? (
 | 
			
		||||
                obfuscatedCount(data as number)
 | 
			
		||||
              ) : (
 | 
			
		||||
                <ShortNumber value={data as number} />
 | 
			
		||||
              )}
 | 
			
		||||
            </span>
 | 
			
		||||
          ))}
 | 
			
		||||
        </span>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,18 @@
 | 
			
		||||
import * as React from 'react';
 | 
			
		||||
 | 
			
		||||
import classNames from 'classnames';
 | 
			
		||||
import { autoPlayGif } from 'flavours/glitch/initial_state';
 | 
			
		||||
 | 
			
		||||
import { useHovering } from 'flavours/glitch/hooks/useHovering';
 | 
			
		||||
import { autoPlayGif } from 'flavours/glitch/initial_state';
 | 
			
		||||
import type { Account } from 'flavours/glitch/types/resources';
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
interface Props {
 | 
			
		||||
  account: Account | undefined;
 | 
			
		||||
  className?: string;
 | 
			
		||||
  size: number;
 | 
			
		||||
  style?: React.CSSProperties;
 | 
			
		||||
  inline?: boolean;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const Avatar: React.FC<Props> = ({
 | 
			
		||||
  account,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,14 @@
 | 
			
		||||
import { decode } from 'blurhash';
 | 
			
		||||
import React, { useRef, useEffect } from 'react';
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
import { decode } from 'blurhash';
 | 
			
		||||
 | 
			
		||||
interface Props extends React.HTMLAttributes<HTMLCanvasElement> {
 | 
			
		||||
  hash: string;
 | 
			
		||||
  width?: number;
 | 
			
		||||
  height?: number;
 | 
			
		||||
  dummy?: boolean; // Whether dummy mode is enabled. If enabled, nothing is rendered and canvas left untouched
 | 
			
		||||
  children?: never;
 | 
			
		||||
  [key: string]: any;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
const Blurhash: React.FC<Props> = ({
 | 
			
		||||
  hash,
 | 
			
		||||
  width = 32,
 | 
			
		||||
@@ -21,6 +21,7 @@ const Blurhash: React.FC<Props> = ({
 | 
			
		||||
  useEffect(() => {
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
 | 
			
		||||
    const canvas = canvasRef.current!;
 | 
			
		||||
 | 
			
		||||
    // eslint-disable-next-line no-self-assign
 | 
			
		||||
    canvas.width = canvas.width; // resets canvas
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,9 @@
 | 
			
		||||
import React, { useCallback } from 'react';
 | 
			
		||||
 | 
			
		||||
import type { InjectedIntl } from 'react-intl';
 | 
			
		||||
import { defineMessages, injectIntl } from 'react-intl';
 | 
			
		||||
 | 
			
		||||
import { IconButton } from './icon_button';
 | 
			
		||||
import { InjectedIntl, defineMessages, injectIntl } from 'react-intl';
 | 
			
		||||
 | 
			
		||||
const messages = defineMessages({
 | 
			
		||||
  unblockDomain: {
 | 
			
		||||
@@ -9,11 +12,11 @@ const messages = defineMessages({
 | 
			
		||||
  },
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
interface Props {
 | 
			
		||||
  domain: string;
 | 
			
		||||
  onUnblockDomain: (domain: string) => void;
 | 
			
		||||
  intl: InjectedIntl;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
const _Domain: React.FC<Props> = ({ domain, onUnblockDomain, intl }) => {
 | 
			
		||||
  const handleDomainUnblock = useCallback(() => {
 | 
			
		||||
    onUnblockDomain(domain);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import React, { useCallback, useState } from 'react';
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
interface Props {
 | 
			
		||||
  src: string;
 | 
			
		||||
  key: string;
 | 
			
		||||
  alt?: string;
 | 
			
		||||
@@ -8,7 +8,7 @@ type Props = {
 | 
			
		||||
  width: number;
 | 
			
		||||
  height: number;
 | 
			
		||||
  onClick?: () => void;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const GIFV: React.FC<Props> = ({
 | 
			
		||||
  src,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,14 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
 | 
			
		||||
import classNames from 'classnames';
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
interface Props extends React.HTMLAttributes<HTMLImageElement> {
 | 
			
		||||
  id: string;
 | 
			
		||||
  className?: string;
 | 
			
		||||
  fixedWidth?: boolean;
 | 
			
		||||
  children?: never;
 | 
			
		||||
  [key: string]: any;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const Icon: React.FC<Props> = ({
 | 
			
		||||
  id,
 | 
			
		||||
  className,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,11 @@
 | 
			
		||||
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;
 | 
			
		||||
  title: string;
 | 
			
		||||
  icon: string;
 | 
			
		||||
@@ -26,11 +28,11 @@ type Props = {
 | 
			
		||||
  obfuscateCount?: boolean;
 | 
			
		||||
  href?: string;
 | 
			
		||||
  ariaHidden: boolean;
 | 
			
		||||
};
 | 
			
		||||
type States = {
 | 
			
		||||
}
 | 
			
		||||
interface States {
 | 
			
		||||
  activate: boolean;
 | 
			
		||||
  deactivate: boolean;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
export class IconButton extends React.PureComponent<Props, States> {
 | 
			
		||||
  static defaultProps = {
 | 
			
		||||
    size: 18,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +1,15 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
 | 
			
		||||
import { Icon } from './icon';
 | 
			
		||||
 | 
			
		||||
const formatNumber = (num: number): number | string => (num > 40 ? '40+' : num);
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
interface Props {
 | 
			
		||||
  id: string;
 | 
			
		||||
  count: number;
 | 
			
		||||
  issueBadge: boolean;
 | 
			
		||||
  className: string;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
export const IconWithBadge: React.FC<Props> = ({
 | 
			
		||||
  id,
 | 
			
		||||
  count,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
 | 
			
		||||
import { FormattedMessage } from 'react-intl';
 | 
			
		||||
 | 
			
		||||
export const NotSignedInIndicator: React.FC = () => (
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,14 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
 | 
			
		||||
import classNames from 'classnames';
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
interface Props {
 | 
			
		||||
  value: string;
 | 
			
		||||
  checked: boolean;
 | 
			
		||||
  name: string;
 | 
			
		||||
  onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
 | 
			
		||||
  label: React.ReactNode;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const RadioButton: React.FC<Props> = ({
 | 
			
		||||
  name,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,7 @@
 | 
			
		||||
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({
 | 
			
		||||
  today: { id: 'relative_time.today', defaultMessage: 'today' },
 | 
			
		||||
@@ -187,16 +189,16 @@ const timeRemainingString = (
 | 
			
		||||
  return relativeTime;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
interface Props {
 | 
			
		||||
  intl: InjectedIntl;
 | 
			
		||||
  timestamp: string;
 | 
			
		||||
  year: number;
 | 
			
		||||
  futureDate?: boolean;
 | 
			
		||||
  short?: boolean;
 | 
			
		||||
};
 | 
			
		||||
type States = {
 | 
			
		||||
}
 | 
			
		||||
interface States {
 | 
			
		||||
  now: number;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
class RelativeTimestamp extends React.Component<Props, States> {
 | 
			
		||||
  state = {
 | 
			
		||||
    now: this.props.intl.now(),
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,15 @@
 | 
			
		||||
import React, { useCallback, useState } from 'react';
 | 
			
		||||
import { Blurhash } from './blurhash';
 | 
			
		||||
 | 
			
		||||
import classNames from 'classnames';
 | 
			
		||||
 | 
			
		||||
type Props = {
 | 
			
		||||
import { Blurhash } from './blurhash';
 | 
			
		||||
 | 
			
		||||
interface Props {
 | 
			
		||||
  src: string;
 | 
			
		||||
  srcSet?: string;
 | 
			
		||||
  blurhash?: string;
 | 
			
		||||
  className?: string;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export const ServerHeroImage: React.FC<Props> = ({
 | 
			
		||||
  src,
 | 
			
		||||
 
 | 
			
		||||
@@ -3,7 +3,7 @@ import { connect } from 'react-redux';
 | 
			
		||||
import ImmutablePropTypes from 'react-immutable-proptypes';
 | 
			
		||||
import PropTypes from 'prop-types';
 | 
			
		||||
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 LoadingIndicator from '../../components/loading_indicator';
 | 
			
		||||
import Column from '../ui/components/column';
 | 
			
		||||
 
 | 
			
		||||
@@ -18,7 +18,7 @@ import {
 | 
			
		||||
  BookmarkedStatuses,
 | 
			
		||||
  ListTimeline,
 | 
			
		||||
  Directory,
 | 
			
		||||
} from '../../ui/util/async-components';
 | 
			
		||||
} from '../util/async-components';
 | 
			
		||||
import ComposePanel from './compose_panel';
 | 
			
		||||
import NavigationPanel from './navigation_panel';
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
 | 
			
		||||
import ImmutablePureComponent from 'react-immutable-pure-component';
 | 
			
		||||
import { connect } from 'react-redux';
 | 
			
		||||
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 { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
 | 
			
		||||
import { IconButton } from 'flavours/glitch/components/icon_button';
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
import React from 'react';
 | 
			
		||||
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 { FormattedMessage } from 'react-intl';
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ import Header from './components/header';
 | 
			
		||||
 | 
			
		||||
// Dummy import, to make sure that <Status /> ends up in the application bundle.
 | 
			
		||||
// Without this it ends up in ~8 very commonly used bundles.
 | 
			
		||||
import '../../../glitch/components/status';
 | 
			
		||||
import "../../components/status";
 | 
			
		||||
 | 
			
		||||
const messages = defineMessages({
 | 
			
		||||
  beforeUnload: { id: 'ui.beforeunload', defaultMessage: 'Your draft will be lost if you leave Mastodon.' },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
import { supportsPassiveEvents } from 'detect-passive-events';
 | 
			
		||||
 | 
			
		||||
import { forceSingleColumn } from 'flavours/glitch/initial_state';
 | 
			
		||||
 | 
			
		||||
const LAYOUT_BREAKPOINT = 630;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,9 @@
 | 
			
		||||
import 'packs/public-path';
 | 
			
		||||
import { start } from '@rails/ujs';
 | 
			
		||||
 | 
			
		||||
start();
 | 
			
		||||
 | 
			
		||||
import 'flavours/glitch/styles/index.scss';
 | 
			
		||||
 | 
			
		||||
start();
 | 
			
		||||
 | 
			
		||||
//  This ensures that webpack compiles our images.
 | 
			
		||||
require.context('../images', true);
 | 
			
		||||
 
 | 
			
		||||
@@ -10,8 +10,13 @@ if (!HTMLCanvasElement.prototype.toBlob) {
 | 
			
		||||
  const BASE64_MARKER = ';base64,';
 | 
			
		||||
 | 
			
		||||
  Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
 | 
			
		||||
    value(callback: BlobCallback, type = 'image/png', quality: any) {
 | 
			
		||||
      const dataURL = this.toDataURL(type, quality);
 | 
			
		||||
    value: function (
 | 
			
		||||
      this: HTMLCanvasElement,
 | 
			
		||||
      callback: BlobCallback,
 | 
			
		||||
      type = 'image/png',
 | 
			
		||||
      quality: unknown
 | 
			
		||||
    ) {
 | 
			
		||||
      const dataURL: string = this.toDataURL(type, quality);
 | 
			
		||||
      let data;
 | 
			
		||||
 | 
			
		||||
      if (dataURL.indexOf(BASE64_MARKER) >= 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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 modal from './modal';
 | 
			
		||||
import user_lists from './user_lists';
 | 
			
		||||
import domain_lists from './domain_lists';
 | 
			
		||||
import { combineReducers } from 'redux-immutable';
 | 
			
		||||
 | 
			
		||||
import account_notes from './account_notes';
 | 
			
		||||
import accounts from './accounts';
 | 
			
		||||
import accounts_counters from './accounts_counters';
 | 
			
		||||
import statuses from './statuses';
 | 
			
		||||
import relationships from './relationships';
 | 
			
		||||
import settings from './settings';
 | 
			
		||||
import local_settings from './local_settings';
 | 
			
		||||
import push_notifications from './push_notifications';
 | 
			
		||||
import status_lists from './status_lists';
 | 
			
		||||
import mutes from './mutes';
 | 
			
		||||
import accounts_map from './accounts_map';
 | 
			
		||||
import alerts from './alerts';
 | 
			
		||||
import announcements from './announcements';
 | 
			
		||||
import blocks from './blocks';
 | 
			
		||||
import server from './server';
 | 
			
		||||
import boosts from './boosts';
 | 
			
		||||
import contexts from './contexts';
 | 
			
		||||
import compose from './compose';
 | 
			
		||||
import search from './search';
 | 
			
		||||
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 contexts from './contexts';
 | 
			
		||||
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 polls from './polls';
 | 
			
		||||
import trends from './trends';
 | 
			
		||||
import announcements from './announcements';
 | 
			
		||||
import markers from './markers';
 | 
			
		||||
import account_notes from './account_notes';
 | 
			
		||||
import picture_in_picture from './picture_in_picture';
 | 
			
		||||
import accounts_map from './accounts_map';
 | 
			
		||||
import history from './history';
 | 
			
		||||
import push_notifications from './push_notifications';
 | 
			
		||||
import relationships from './relationships';
 | 
			
		||||
import search from './search';
 | 
			
		||||
import server from './server';
 | 
			
		||||
import settings from './settings';
 | 
			
		||||
import status_lists from './status_lists';
 | 
			
		||||
import statuses from './statuses';
 | 
			
		||||
import suggestions from './suggestions';
 | 
			
		||||
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 = {
 | 
			
		||||
  announcements,
 | 
			
		||||
 
 | 
			
		||||
@@ -2,13 +2,13 @@ import {
 | 
			
		||||
  MARKERS_SUBMIT_SUCCESS,
 | 
			
		||||
} from '../actions/markers';
 | 
			
		||||
 | 
			
		||||
import { Map as ImmutableMap } from 'immutable';
 | 
			
		||||
 | 
			
		||||
const initialState = ImmutableMap({
 | 
			
		||||
  home: '0',
 | 
			
		||||
  notifications: '0',
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
import { Map as ImmutableMap } from 'immutable';
 | 
			
		||||
 | 
			
		||||
export default function markers(state = initialState, action) {
 | 
			
		||||
  switch(action.type) {
 | 
			
		||||
  case MARKERS_SUBMIT_SUCCESS:
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,13 @@
 | 
			
		||||
import type { TypedUseSelectorHook } from 'react-redux';
 | 
			
		||||
import { useDispatch, useSelector } from 'react-redux';
 | 
			
		||||
 | 
			
		||||
import { configureStore } from '@reduxjs/toolkit';
 | 
			
		||||
 | 
			
		||||
import { rootReducer } from '../reducers';
 | 
			
		||||
import { loadingBarMiddleware } from './middlewares/loading_bar';
 | 
			
		||||
 | 
			
		||||
import { errorsMiddleware } from './middlewares/errors';
 | 
			
		||||
import { loadingBarMiddleware } from './middlewares/loading_bar';
 | 
			
		||||
import { soundsMiddleware } from './middlewares/sounds';
 | 
			
		||||
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
 | 
			
		||||
 | 
			
		||||
export const store = configureStore({
 | 
			
		||||
  reducer: rootReducer,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,19 @@
 | 
			
		||||
import { Middleware } from 'redux';
 | 
			
		||||
import type { AnyAction, Middleware } from 'redux';
 | 
			
		||||
 | 
			
		||||
import { showAlertForError } from 'flavours/glitch/actions/alerts';
 | 
			
		||||
import { RootState } from '..';
 | 
			
		||||
 | 
			
		||||
import type { RootState } from '..';
 | 
			
		||||
 | 
			
		||||
const defaultFailSuffix = 'FAIL';
 | 
			
		||||
 | 
			
		||||
export const errorsMiddleware: Middleware<Record<string, never>, RootState> =
 | 
			
		||||
  ({ dispatch }) =>
 | 
			
		||||
  (next) =>
 | 
			
		||||
  (action) => {
 | 
			
		||||
  (action: AnyAction & { skipAlert?: boolean; skipNotFound?: boolean }) => {
 | 
			
		||||
    if (action.type && !action.skipAlert) {
 | 
			
		||||
      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));
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
import { showLoading, hideLoading } from 'react-redux-loading-bar';
 | 
			
		||||
import { Middleware } from 'redux';
 | 
			
		||||
import { RootState } from '..';
 | 
			
		||||
import type { AnyAction, Middleware } from 'redux';
 | 
			
		||||
 | 
			
		||||
import type { RootState } from '..';
 | 
			
		||||
 | 
			
		||||
interface Config {
 | 
			
		||||
  promiseTypeSuffixes?: string[];
 | 
			
		||||
@@ -19,7 +20,7 @@ export const loadingBarMiddleware = (
 | 
			
		||||
 | 
			
		||||
  return ({ dispatch }) =>
 | 
			
		||||
    (next) =>
 | 
			
		||||
    (action) => {
 | 
			
		||||
    (action: AnyAction) => {
 | 
			
		||||
      if (action.type && !action.skipLoading) {
 | 
			
		||||
        const [PENDING, FULFILLED, REJECTED] = promiseTypeSuffixes;
 | 
			
		||||
 | 
			
		||||
@@ -27,6 +28,7 @@ export const loadingBarMiddleware = (
 | 
			
		||||
        const isFulfilled = new RegExp(`${FULFILLED}$`, 'g');
 | 
			
		||||
        const isRejected = new RegExp(`${REJECTED}$`, 'g');
 | 
			
		||||
 | 
			
		||||
        if (typeof action.type === 'string') {
 | 
			
		||||
          if (action.type.match(isPending)) {
 | 
			
		||||
            dispatch(showLoading());
 | 
			
		||||
          } else if (
 | 
			
		||||
@@ -36,6 +38,7 @@ export const loadingBarMiddleware = (
 | 
			
		||||
            dispatch(hideLoading());
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return next(action);
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,6 @@
 | 
			
		||||
import { Middleware, AnyAction } from 'redux';
 | 
			
		||||
import { RootState } from '..';
 | 
			
		||||
import type { Middleware, AnyAction } from 'redux';
 | 
			
		||||
 | 
			
		||||
import type { RootState } from '..';
 | 
			
		||||
 | 
			
		||||
interface AudioSource {
 | 
			
		||||
  src: string;
 | 
			
		||||
@@ -27,7 +28,7 @@ const play = (audio: HTMLAudioElement) => {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  audio.play();
 | 
			
		||||
  void audio.play();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const soundsMiddleware = (): Middleware<
 | 
			
		||||
@@ -47,7 +48,9 @@ export const soundsMiddleware = (): Middleware<
 | 
			
		||||
    ]),
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  return () => (next) => (action: AnyAction) => {
 | 
			
		||||
  return () =>
 | 
			
		||||
    (next) =>
 | 
			
		||||
    (action: AnyAction & { meta?: { sound?: string } }) => {
 | 
			
		||||
      const sound = action?.meta?.sound;
 | 
			
		||||
 | 
			
		||||
      if (sound && soundCache[sound]) {
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,7 @@ type AccountField = Record<{
 | 
			
		||||
  verified_at: string | null;
 | 
			
		||||
}>;
 | 
			
		||||
 | 
			
		||||
type AccountApiResponseValues = {
 | 
			
		||||
interface AccountApiResponseValues {
 | 
			
		||||
  acct: string;
 | 
			
		||||
  avatar: string;
 | 
			
		||||
  avatar_static: string;
 | 
			
		||||
@@ -34,7 +34,7 @@ type AccountApiResponseValues = {
 | 
			
		||||
  statuses_count: number;
 | 
			
		||||
  url: string;
 | 
			
		||||
  username: string;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type NormalizedAccountField = Record<{
 | 
			
		||||
  name_emojified: string;
 | 
			
		||||
@@ -42,12 +42,12 @@ type NormalizedAccountField = Record<{
 | 
			
		||||
  value_plain: string;
 | 
			
		||||
}>;
 | 
			
		||||
 | 
			
		||||
type NormalizedAccountValues = {
 | 
			
		||||
interface NormalizedAccountValues {
 | 
			
		||||
  display_name_html: string;
 | 
			
		||||
  fields: NormalizedAccountField[];
 | 
			
		||||
  note_emojified: string;
 | 
			
		||||
  note_plain: string;
 | 
			
		||||
};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type Account = Record<
 | 
			
		||||
  AccountApiResponseValues & NormalizedAccountValues
 | 
			
		||||
 
 | 
			
		||||
@@ -170,7 +170,7 @@ const resizeImage = (img, type = 'image/png') => new Promise((resolve, reject) =
 | 
			
		||||
    .catch(reject);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default inputFile => new Promise((resolve) => {
 | 
			
		||||
const resizeFile = (inputFile) => new Promise((resolve) => {
 | 
			
		||||
  if (!inputFile.type.match(/image.*/) || inputFile.type === 'image/gif') {
 | 
			
		||||
    resolve(inputFile);
 | 
			
		||||
    return;
 | 
			
		||||
@@ -187,3 +187,5 @@ export default inputFile => new Promise((resolve) => {
 | 
			
		||||
      .catch(() => resolve(inputFile));
 | 
			
		||||
  }).catch(() => resolve(inputFile));
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
export default resizeFile;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,8 +1,9 @@
 | 
			
		||||
export function uuid(a?: string): string {
 | 
			
		||||
  return a
 | 
			
		||||
    ? (
 | 
			
		||||
        (a as any as number) ^
 | 
			
		||||
        ((Math.random() * 16) >> ((a as any as number) / 4))
 | 
			
		||||
        (a as unknown as number) ^
 | 
			
		||||
        ((Math.random() * 16) >> ((a as unknown as number) / 4))
 | 
			
		||||
      ).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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,6 +12,8 @@
 | 
			
		||||
    "baseUrl": "./",
 | 
			
		||||
    "paths": {
 | 
			
		||||
      "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/*"],
 | 
			
		||||
      "mastodon": ["app/javascript/mastodon"],
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user