Merge remote-tracking branch 'upstream/main'
This commit is contained in:
commit
7cbfc6b4ac
344 changed files with 3967 additions and 1611 deletions
|
|
@ -16,4 +16,5 @@ pack:
|
|||
modal: public.js
|
||||
public: public.js
|
||||
settings: settings.js
|
||||
sign_up:
|
||||
share:
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -2,14 +2,14 @@ import React, { Fragment } from 'react';
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Avatar } from './avatar';
|
||||
import DisplayName from './display_name';
|
||||
import { DisplayName } from './display_name';
|
||||
import Permalink from './permalink';
|
||||
import { IconButton } from './icon_button';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { me } from 'flavours/glitch/initial_state';
|
||||
import { RelativeTimestamp } from './relative_timestamp';
|
||||
import Skeleton from 'flavours/glitch/components/skeleton';
|
||||
import { Skeleton } from 'flavours/glitch/components/skeleton';
|
||||
|
||||
const messages = defineMessages({
|
||||
follow: { id: 'account.follow', defaultMessage: 'Follow' },
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import api from 'flavours/glitch/api';
|
|||
import { FormattedNumber } from 'react-intl';
|
||||
import { Sparklines, SparklinesCurve } from 'react-sparklines';
|
||||
import classNames from 'classnames';
|
||||
import Skeleton from 'flavours/glitch/components/skeleton';
|
||||
import { Skeleton } from 'flavours/glitch/components/skeleton';
|
||||
|
||||
const percIncrease = (a, b) => {
|
||||
let percent;
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||
import api from 'flavours/glitch/api';
|
||||
import { FormattedNumber } from 'react-intl';
|
||||
import { roundTo10 } from 'flavours/glitch/utils/numbers';
|
||||
import Skeleton from 'flavours/glitch/components/skeleton';
|
||||
import { Skeleton } from 'flavours/glitch/components/skeleton';
|
||||
|
||||
export default class Dimension extends React.PureComponent {
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ export default class AutosuggestInput extends ImmutablePureComponent {
|
|||
this.input.focus();
|
||||
};
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.suggestions !== this.props.suggestions && nextProps.suggestions.size > 0 && this.state.suggestionsHidden && this.state.focused) {
|
||||
this.setState({ suggestionsHidden: false });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -153,7 +153,7 @@ export default class AutosuggestTextarea extends ImmutablePureComponent {
|
|||
this.textarea.focus();
|
||||
};
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.suggestions !== this.props.suggestions && nextProps.suggestions.size > 0 && this.state.suggestionsHidden && this.state.focused) {
|
||||
this.setState({ suggestionsHidden: false });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ import PropTypes from 'prop-types';
|
|||
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||
import { scrollTop } from '../scroll';
|
||||
|
||||
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
||||
|
||||
export default class Column extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
|
|
@ -37,17 +39,17 @@ export default class Column extends React.PureComponent {
|
|||
|
||||
componentDidMount () {
|
||||
if (this.props.bindToDocument) {
|
||||
document.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
||||
document.addEventListener('wheel', this.handleWheel, listenerOptions);
|
||||
} else {
|
||||
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : false);
|
||||
this.node.addEventListener('wheel', this.handleWheel, listenerOptions);
|
||||
}
|
||||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
if (this.props.bindToDocument) {
|
||||
document.removeEventListener('wheel', this.handleWheel);
|
||||
document.removeEventListener('wheel', this.handleWheel, listenerOptions);
|
||||
} else {
|
||||
this.node.removeEventListener('wheel', this.handleWheel);
|
||||
this.node.removeEventListener('wheel', this.handleWheel, listenerOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -14,17 +14,15 @@ export default class ColumnBackButton extends React.PureComponent {
|
|||
multiColumn: PropTypes.bool,
|
||||
};
|
||||
|
||||
handleClick = (event) => {
|
||||
// if history is exhausted, or we would leave mastodon, just go to root.
|
||||
if (window.history.state) {
|
||||
const state = this.context.router.history.location.state;
|
||||
if (event.shiftKey && state && state.mastodonBackSteps) {
|
||||
this.context.router.history.go(-state.mastodonBackSteps);
|
||||
} else {
|
||||
this.context.router.history.goBack();
|
||||
}
|
||||
handleClick = () => {
|
||||
const { router } = this.context;
|
||||
|
||||
// Check if there is a previous page in the app to go back to per https://stackoverflow.com/a/70532858/9703201
|
||||
// When upgrading to V6, check `location.key !== 'default'` instead per https://github.com/remix-run/history/blob/main/docs/api-reference.md#location
|
||||
if (router.route.location.key) {
|
||||
router.history.goBack();
|
||||
} else {
|
||||
this.context.router.history.push('/');
|
||||
router.history.push('/');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -9,17 +9,15 @@ export default class ColumnBackButtonSlim extends React.PureComponent {
|
|||
router: PropTypes.object,
|
||||
};
|
||||
|
||||
handleClick = (event) => {
|
||||
// if history is exhausted, or we would leave mastodon, just go to root.
|
||||
if (window.history.state) {
|
||||
const state = this.context.router.history.location.state;
|
||||
if (event.shiftKey && state && state.mastodonBackSteps) {
|
||||
this.context.router.history.go(-state.mastodonBackSteps);
|
||||
} else {
|
||||
this.context.router.history.goBack();
|
||||
}
|
||||
handleClick = () => {
|
||||
const { router } = this.context;
|
||||
|
||||
// Check if there is a previous page in the app to go back to per https://stackoverflow.com/a/70532858/9703201
|
||||
// When upgrading to V6, check `location.key !== 'default'` instead per https://github.com/remix-run/history/blob/main/docs/api-reference.md#location
|
||||
if (router.route.location.key) {
|
||||
router.history.goBack();
|
||||
} else {
|
||||
this.context.router.history.push('/');
|
||||
router.history.push('/');
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -42,20 +42,6 @@ class ColumnHeader extends React.PureComponent {
|
|||
animating: false,
|
||||
};
|
||||
|
||||
historyBack = (skip) => {
|
||||
// if history is exhausted, or we would leave mastodon, just go to root.
|
||||
if (window.history.state) {
|
||||
const state = this.context.router.history.location.state;
|
||||
if (skip && state && state.mastodonBackSteps) {
|
||||
this.context.router.history.go(-state.mastodonBackSteps);
|
||||
} else {
|
||||
this.context.router.history.goBack();
|
||||
}
|
||||
} else {
|
||||
this.context.router.history.push('/');
|
||||
}
|
||||
};
|
||||
|
||||
handleToggleClick = (e) => {
|
||||
e.stopPropagation();
|
||||
this.setState({ collapsed: !this.state.collapsed, animating: true });
|
||||
|
|
@ -73,8 +59,16 @@ class ColumnHeader extends React.PureComponent {
|
|||
this.props.onMove(1);
|
||||
};
|
||||
|
||||
handleBackClick = (event) => {
|
||||
this.historyBack(event.shiftKey);
|
||||
handleBackClick = () => {
|
||||
const { router } = this.context;
|
||||
|
||||
// Check if there is a previous page in the app to go back to per https://stackoverflow.com/a/70532858/9703201
|
||||
// When upgrading to V6, check `location.key !== 'default'` instead per https://github.com/remix-run/history/blob/main/docs/api-reference.md#location
|
||||
if (router.route.location.key) {
|
||||
router.history.goBack();
|
||||
} else {
|
||||
router.history.push('/');
|
||||
}
|
||||
};
|
||||
|
||||
handleTransitionEnd = () => {
|
||||
|
|
@ -83,8 +77,9 @@ class ColumnHeader extends React.PureComponent {
|
|||
|
||||
handlePin = () => {
|
||||
if (!this.props.pinned) {
|
||||
this.historyBack();
|
||||
this.context.router.history.replace('/');
|
||||
}
|
||||
|
||||
this.props.onPin();
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,83 +0,0 @@
|
|||
import React from 'react';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import { autoPlayGif } from 'flavours/glitch/initial_state';
|
||||
import Skeleton from 'flavours/glitch/components/skeleton';
|
||||
|
||||
export default class DisplayName extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
others: ImmutablePropTypes.list,
|
||||
localDomain: PropTypes.string,
|
||||
inline: PropTypes.bool,
|
||||
};
|
||||
|
||||
handleMouseEnter = ({ currentTarget }) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
const emojis = currentTarget.querySelectorAll('.custom-emoji');
|
||||
|
||||
for (var i = 0; i < emojis.length; i++) {
|
||||
let emoji = emojis[i];
|
||||
emoji.src = emoji.getAttribute('data-original');
|
||||
}
|
||||
};
|
||||
|
||||
handleMouseLeave = ({ currentTarget }) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
const emojis = currentTarget.querySelectorAll('.custom-emoji');
|
||||
|
||||
for (var i = 0; i < emojis.length; i++) {
|
||||
let emoji = emojis[i];
|
||||
emoji.src = emoji.getAttribute('data-static');
|
||||
}
|
||||
};
|
||||
|
||||
render () {
|
||||
const { others, localDomain, inline } = this.props;
|
||||
|
||||
let displayName, suffix, account;
|
||||
|
||||
if (others && others.size > 1) {
|
||||
displayName = others.take(2).map(a => <bdi key={a.get('id')}><strong className='display-name__html' dangerouslySetInnerHTML={{ __html: a.get('display_name_html') }} /></bdi>).reduce((prev, cur) => [prev, ', ', cur]);
|
||||
|
||||
if (others.size - 2 > 0) {
|
||||
suffix = `+${others.size - 2}`;
|
||||
}
|
||||
} else if ((others && others.size > 0) || this.props.account) {
|
||||
if (others && others.size > 0) {
|
||||
account = others.first();
|
||||
} else {
|
||||
account = this.props.account;
|
||||
}
|
||||
|
||||
let acct = account.get('acct');
|
||||
|
||||
if (acct.indexOf('@') === -1 && localDomain) {
|
||||
acct = `${acct}@${localDomain}`;
|
||||
}
|
||||
|
||||
displayName = <bdi><strong className='display-name__html' dangerouslySetInnerHTML={{ __html: account.get('display_name_html') }} /></bdi>;
|
||||
suffix = <span className='display-name__account'>@{acct}</span>;
|
||||
} else {
|
||||
displayName = <bdi><strong className='display-name__html'><Skeleton width='10ch' /></strong></bdi>;
|
||||
suffix = <span className='display-name__account'><Skeleton width='7ch' /></span>;
|
||||
}
|
||||
|
||||
return (
|
||||
<span className={classNames('display-name', { inline })} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave}>
|
||||
{displayName}
|
||||
{inline ? ' ' : null}
|
||||
{suffix}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
124
app/javascript/flavours/glitch/components/display_name.tsx
Normal file
124
app/javascript/flavours/glitch/components/display_name.tsx
Normal file
|
|
@ -0,0 +1,124 @@
|
|||
import React from 'react';
|
||||
|
||||
import classNames from 'classnames';
|
||||
|
||||
import type { List } from 'immutable';
|
||||
|
||||
import type { Account } from 'flavours/glitch/types/resources';
|
||||
|
||||
import { autoPlayGif } from '../initial_state';
|
||||
|
||||
import { Skeleton } from './skeleton';
|
||||
|
||||
interface Props {
|
||||
account: Account;
|
||||
others: List<Account>;
|
||||
localDomain: string;
|
||||
inline?: boolean;
|
||||
}
|
||||
export class DisplayName extends React.PureComponent<Props> {
|
||||
handleMouseEnter: React.ReactEventHandler<HTMLSpanElement> = ({
|
||||
currentTarget,
|
||||
}) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
const emojis =
|
||||
currentTarget.querySelectorAll<HTMLImageElement>('img.custom-emoji');
|
||||
|
||||
emojis.forEach((emoji) => {
|
||||
const originalSrc = emoji.getAttribute('data-original');
|
||||
if (originalSrc != null) emoji.src = originalSrc;
|
||||
});
|
||||
};
|
||||
|
||||
handleMouseLeave: React.ReactEventHandler<HTMLSpanElement> = ({
|
||||
currentTarget,
|
||||
}) => {
|
||||
if (autoPlayGif) {
|
||||
return;
|
||||
}
|
||||
|
||||
const emojis =
|
||||
currentTarget.querySelectorAll<HTMLImageElement>('img.custom-emoji');
|
||||
|
||||
emojis.forEach((emoji) => {
|
||||
const staticSrc = emoji.getAttribute('data-static');
|
||||
if (staticSrc != null) emoji.src = staticSrc;
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
const { others, localDomain, inline } = this.props;
|
||||
|
||||
let displayName: React.ReactNode, suffix: React.ReactNode, account: Account;
|
||||
|
||||
if (others && others.size > 1) {
|
||||
displayName = others
|
||||
.take(2)
|
||||
.map((a) => (
|
||||
<bdi key={a.get('id')}>
|
||||
<strong
|
||||
className='display-name__html'
|
||||
dangerouslySetInnerHTML={{ __html: a.get('display_name_html') }}
|
||||
/>
|
||||
</bdi>
|
||||
))
|
||||
.reduce((prev, cur) => [prev, ', ', cur]);
|
||||
|
||||
if (others.size - 2 > 0) {
|
||||
suffix = `+${others.size - 2}`;
|
||||
}
|
||||
} else if ((others && others.size > 0) || this.props.account) {
|
||||
if (others && others.size > 0) {
|
||||
account = others.first();
|
||||
} else {
|
||||
account = this.props.account;
|
||||
}
|
||||
|
||||
let acct = account.get('acct');
|
||||
|
||||
if (acct.indexOf('@') === -1 && localDomain) {
|
||||
acct = `${acct}@${localDomain}`;
|
||||
}
|
||||
|
||||
displayName = (
|
||||
<bdi>
|
||||
<strong
|
||||
className='display-name__html'
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: account.get('display_name_html'),
|
||||
}}
|
||||
/>
|
||||
</bdi>
|
||||
);
|
||||
suffix = <span className='display-name__account'>@{acct}</span>;
|
||||
} else {
|
||||
displayName = (
|
||||
<bdi>
|
||||
<strong className='display-name__html'>
|
||||
<Skeleton width='10ch' />
|
||||
</strong>
|
||||
</bdi>
|
||||
);
|
||||
suffix = (
|
||||
<span className='display-name__account'>
|
||||
<Skeleton width='7ch' />
|
||||
</span>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<span
|
||||
className={classNames('display-name', { inline })}
|
||||
onMouseEnter={this.handleMouseEnter}
|
||||
onMouseLeave={this.handleMouseLeave}
|
||||
>
|
||||
{displayName}
|
||||
{inline ? ' ' : null}
|
||||
{suffix}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import { supportsPassiveEvents } from 'detect-passive-events';
|
|||
import classNames from 'classnames';
|
||||
import { CircularProgress } from 'flavours/glitch/components/loading_indicator';
|
||||
|
||||
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
||||
const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
|
||||
let id = 0;
|
||||
|
||||
class DropdownMenu extends React.PureComponent {
|
||||
|
|
@ -35,12 +35,13 @@ class DropdownMenu extends React.PureComponent {
|
|||
handleDocumentClick = e => {
|
||||
if (this.node && !this.node.contains(e.target)) {
|
||||
this.props.onClose();
|
||||
e.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount () {
|
||||
document.addEventListener('click', this.handleDocumentClick, false);
|
||||
document.addEventListener('keydown', this.handleKeyDown, false);
|
||||
document.addEventListener('click', this.handleDocumentClick, { capture: true });
|
||||
document.addEventListener('keydown', this.handleKeyDown, { capture: true });
|
||||
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
|
||||
|
||||
if (this.focusedItem && this.props.openedViaKeyboard) {
|
||||
|
|
@ -49,8 +50,8 @@ class DropdownMenu extends React.PureComponent {
|
|||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
document.removeEventListener('click', this.handleDocumentClick, false);
|
||||
document.removeEventListener('keydown', this.handleKeyDown, false);
|
||||
document.removeEventListener('click', this.handleDocumentClick, { capture: true });
|
||||
document.removeEventListener('keydown', this.handleKeyDown, { capture: true });
|
||||
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import PropTypes from 'prop-types';
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import Permalink from './permalink';
|
||||
import ShortNumber from 'flavours/glitch/components/short_number';
|
||||
import Skeleton from 'flavours/glitch/components/skeleton';
|
||||
import { Skeleton } from 'flavours/glitch/components/skeleton';
|
||||
import classNames from 'classnames';
|
||||
|
||||
class SilentErrorBoundary extends React.Component {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ class MediaGallery extends React.PureComponent {
|
|||
window.removeEventListener('resize', this.handleResize);
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
if (!is(nextProps.media, this.props.media) && nextProps.visible === undefined) {
|
||||
this.setState({ visible: displayMedia !== 'hide_all' && !nextProps.sensitive || displayMedia === 'show_all' });
|
||||
} else if (!is(nextProps.visible, this.props.visible) && nextProps.visible !== undefined) {
|
||||
|
|
@ -286,7 +286,7 @@ class MediaGallery extends React.PureComponent {
|
|||
};
|
||||
|
||||
handleClick = (index) => {
|
||||
this.props.onOpenMedia(this.props.media, index);
|
||||
this.props.onOpenMedia(this.props.media, index, this.props.lang);
|
||||
};
|
||||
|
||||
handleRef = (node) => {
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ export default class ModalRoot extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
if (!!nextProps.children && !this.props.children) {
|
||||
this.activeElement = document.activeElement;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import React from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
export const NotSignedInIndicator: React.FC = () => (
|
||||
|
|
@ -6,7 +7,7 @@ export const NotSignedInIndicator: React.FC = () => (
|
|||
<div className='empty-column-indicator'>
|
||||
<FormattedMessage
|
||||
id='not_signed_in_indicator.not_signed_in'
|
||||
defaultMessage='You need to sign in to access this resource.'
|
||||
defaultMessage='You need to login to access this resource.'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -24,9 +24,7 @@ export default class Permalink extends React.PureComponent {
|
|||
|
||||
if (this.context.router) {
|
||||
e.preventDefault();
|
||||
let state = { ...this.context.router.history.location.state };
|
||||
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
|
||||
this.context.router.history.push(this.props.to, state);
|
||||
this.context.router.history.push(this.props.to);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ import { connect } from 'react-redux';
|
|||
|
||||
const MOUSE_IDLE_DELAY = 300;
|
||||
|
||||
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
||||
|
||||
const mapStateToProps = (state, { scrollKey }) => {
|
||||
return {
|
||||
preventScroll: scrollKey === state.getIn(['dropdown_menu', 'scroll_key']),
|
||||
|
|
@ -237,20 +239,20 @@ class ScrollableList extends PureComponent {
|
|||
attachScrollListener () {
|
||||
if (this.props.bindToDocument) {
|
||||
document.addEventListener('scroll', this.handleScroll);
|
||||
document.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : undefined);
|
||||
document.addEventListener('wheel', this.handleWheel, listenerOptions);
|
||||
} else {
|
||||
this.node.addEventListener('scroll', this.handleScroll);
|
||||
this.node.addEventListener('wheel', this.handleWheel, supportsPassiveEvents ? { passive: true } : undefined);
|
||||
this.node.addEventListener('wheel', this.handleWheel, listenerOptions);
|
||||
}
|
||||
}
|
||||
|
||||
detachScrollListener () {
|
||||
if (this.props.bindToDocument) {
|
||||
document.removeEventListener('scroll', this.handleScroll);
|
||||
document.removeEventListener('wheel', this.handleWheel);
|
||||
document.removeEventListener('wheel', this.handleWheel, listenerOptions);
|
||||
} else {
|
||||
this.node.removeEventListener('scroll', this.handleScroll);
|
||||
this.node.removeEventListener('wheel', this.handleWheel);
|
||||
this.node.removeEventListener('wheel', this.handleWheel, listenerOptions);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ import { FormattedMessage, defineMessages, injectIntl } from 'react-intl';
|
|||
import { connect } from 'react-redux';
|
||||
import { fetchServer } from 'flavours/glitch/actions/server';
|
||||
import ShortNumber from 'flavours/glitch/components/short_number';
|
||||
import Skeleton from 'flavours/glitch/components/skeleton';
|
||||
import { Skeleton } from 'flavours/glitch/components/skeleton';
|
||||
import Account from 'flavours/glitch/containers/account_container';
|
||||
import { domain } from 'flavours/glitch/initial_state';
|
||||
import { Image } from 'flavours/glitch/components/image';
|
||||
import { ServerHeroImage } from 'flavours/glitch/components/server_hero_image';
|
||||
import { Link } from 'react-router-dom';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
|
@ -41,7 +41,7 @@ class ServerBanner extends React.PureComponent {
|
|||
<FormattedMessage id='server_banner.introduction' defaultMessage='{domain} is part of the decentralized social network powered by {mastodon}.' values={{ domain: <strong>{domain}</strong>, mastodon: <a href='https://joinmastodon.org' target='_blank'>Mastodon</a> }} />
|
||||
</div>
|
||||
|
||||
<Image blurhash={server.getIn(['thumbnail', 'blurhash'])} src={server.getIn(['thumbnail', 'url'])} className='server-banner__hero' />
|
||||
<ServerHeroImage blurhash={server.getIn(['thumbnail', 'blurhash'])} src={server.getIn(['thumbnail', 'url'])} className='server-banner__hero' />
|
||||
|
||||
<div className='server-banner__description'>
|
||||
{isLoading ? (
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
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 Image: React.FC<Props> = ({
|
||||
export const ServerHeroImage: React.FC<Props> = ({
|
||||
src,
|
||||
srcSet,
|
||||
blurhash,
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const Skeleton = ({ width, height }) => <span className='skeleton' style={{ width, height }}>‌</span>;
|
||||
|
||||
Skeleton.propTypes = {
|
||||
width: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
||||
height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
|
||||
};
|
||||
|
||||
export default Skeleton;
|
||||
12
app/javascript/flavours/glitch/components/skeleton.tsx
Normal file
12
app/javascript/flavours/glitch/components/skeleton.tsx
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import React from 'react';
|
||||
|
||||
interface Props {
|
||||
width?: number | string;
|
||||
height?: number | string;
|
||||
}
|
||||
|
||||
export const Skeleton: React.FC<Props> = ({ width, height }) => (
|
||||
<span className='skeleton' style={{ width, height }}>
|
||||
‌
|
||||
</span>
|
||||
);
|
||||
|
|
@ -372,9 +372,7 @@ class Status extends ImmutablePureComponent {
|
|||
status.getIn(['reblog', 'id'], status.get('id'))
|
||||
}`;
|
||||
}
|
||||
let state = { ...router.history.location.state };
|
||||
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
|
||||
router.history.push(destination, state);
|
||||
router.history.push(destination);
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
|
|
@ -394,11 +392,12 @@ class Status extends ImmutablePureComponent {
|
|||
|
||||
handleOpenVideo = (options) => {
|
||||
const { status } = this.props;
|
||||
this.props.onOpenVideo(status.get('id'), status.getIn(['media_attachments', 0]), options);
|
||||
this.props.onOpenVideo(status.get('id'), status.getIn(['media_attachments', 0]), status.get('language'), options);
|
||||
};
|
||||
|
||||
handleOpenMedia = (media, index) => {
|
||||
this.props.onOpenMedia(this.props.status.get('id'), media, index);
|
||||
const { status } = this.props;
|
||||
this.props.onOpenMedia(status.get('id'), media, index, status.get('language'));
|
||||
};
|
||||
|
||||
handleHotkeyOpenMedia = e => {
|
||||
|
|
@ -445,16 +444,12 @@ class Status extends ImmutablePureComponent {
|
|||
};
|
||||
|
||||
handleHotkeyOpen = () => {
|
||||
let state = { ...this.context.router.history.location.state };
|
||||
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
|
||||
const status = this.props.status;
|
||||
this.context.router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`, state);
|
||||
this.context.router.history.push(`/@${status.getIn(['account', 'acct'])}/${status.get('id')}`);
|
||||
};
|
||||
|
||||
handleHotkeyOpenProfile = () => {
|
||||
let state = { ...this.context.router.history.location.state };
|
||||
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
|
||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`, state);
|
||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
|
||||
};
|
||||
|
||||
handleHotkeyMoveUp = e => {
|
||||
|
|
|
|||
|
|
@ -170,10 +170,9 @@ class StatusActionBar extends ImmutablePureComponent {
|
|||
handleOpen = () => {
|
||||
let state = { ...this.context.router.history.location.state };
|
||||
if (state.mastodonModalKey) {
|
||||
this.context.router.history.replace(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`, { mastodonBackSteps: (state.mastodonBackSteps || 0) + 1 });
|
||||
this.context.router.history.replace(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`);
|
||||
} else {
|
||||
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
|
||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`, state);
|
||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}/${this.props.status.get('id')}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
|||
// Mastodon imports.
|
||||
import { Avatar } from './avatar';
|
||||
import AvatarOverlay from './avatar_overlay';
|
||||
import DisplayName from './display_name';
|
||||
import { DisplayName } from './display_name';
|
||||
|
||||
export default class StatusHeader extends React.PureComponent {
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ export default class StatusList extends ImmutablePureComponent {
|
|||
alwaysPrepend: PropTypes.bool,
|
||||
withCounters: PropTypes.bool,
|
||||
timelineId: PropTypes.string.isRequired,
|
||||
lastId: PropTypes.string,
|
||||
regex: PropTypes.string,
|
||||
};
|
||||
|
||||
|
|
@ -56,7 +57,8 @@ export default class StatusList extends ImmutablePureComponent {
|
|||
};
|
||||
|
||||
handleLoadOlder = debounce(() => {
|
||||
this.props.onLoadMore(this.props.statusIds.size > 0 ? this.props.statusIds.last() : undefined);
|
||||
const { statusIds, lastId, onLoadMore } = this.props;
|
||||
onLoadMore(lastId || (statusIds.size > 0 ? statusIds.last() : undefined));
|
||||
}, 300, { leading: true });
|
||||
|
||||
_selectChild (index, align_top) {
|
||||
|
|
|
|||
|
|
@ -1,18 +0,0 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
const TimelineHint = ({ resource, url }) => (
|
||||
<div className='timeline-hint'>
|
||||
<strong><FormattedMessage id='timeline_hint.remote_resource_not_displayed' defaultMessage='{resource} from other servers are not displayed.' values={{ resource }} /></strong>
|
||||
<br />
|
||||
<a href={url} target='_blank'><FormattedMessage id='account.browse_more_on_origin_server' defaultMessage='Browse more on the original profile' /></a>
|
||||
</div>
|
||||
);
|
||||
|
||||
TimelineHint.propTypes = {
|
||||
resource: PropTypes.node.isRequired,
|
||||
url: PropTypes.string.isRequired,
|
||||
};
|
||||
|
||||
export default TimelineHint;
|
||||
27
app/javascript/flavours/glitch/components/timeline_hint.tsx
Normal file
27
app/javascript/flavours/glitch/components/timeline_hint.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import React from 'react';
|
||||
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
interface Props {
|
||||
resource: JSX.Element;
|
||||
url: string;
|
||||
}
|
||||
|
||||
export const TimelineHint: React.FC<Props> = ({ resource, url }) => (
|
||||
<div className='timeline-hint'>
|
||||
<strong>
|
||||
<FormattedMessage
|
||||
id='timeline_hint.remote_resource_not_displayed'
|
||||
defaultMessage='{resource} from other servers are not displayed.'
|
||||
values={{ resource }}
|
||||
/>
|
||||
</strong>
|
||||
<br />
|
||||
<a href={url} target='_blank' rel='noopener noreferrer'>
|
||||
<FormattedMessage
|
||||
id='account.browse_more_on_origin_server'
|
||||
defaultMessage='Browse more on the original profile'
|
||||
/>
|
||||
</a>
|
||||
</div>
|
||||
);
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
import React, { PureComponent, Fragment } from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createPortal } from 'react-dom';
|
||||
import PropTypes from 'prop-types';
|
||||
import { IntlProvider, addLocaleData } from 'react-intl';
|
||||
import { fromJS } from 'immutable';
|
||||
|
|
@ -29,19 +29,20 @@ export default class MediaContainer extends PureComponent {
|
|||
state = {
|
||||
media: null,
|
||||
index: null,
|
||||
lang: null,
|
||||
time: null,
|
||||
backgroundColor: null,
|
||||
options: null,
|
||||
};
|
||||
|
||||
handleOpenMedia = (media, index) => {
|
||||
handleOpenMedia = (media, index, lang) => {
|
||||
document.body.classList.add('with-modals--active');
|
||||
document.documentElement.style.marginRight = `${getScrollbarWidth()}px`;
|
||||
|
||||
this.setState({ media, index });
|
||||
this.setState({ media, index, lang });
|
||||
};
|
||||
|
||||
handleOpenVideo = (options) => {
|
||||
handleOpenVideo = (lang, options) => {
|
||||
const { components } = this.props;
|
||||
const { media } = JSON.parse(components[options.componentIndex].getAttribute('data-props'));
|
||||
const mediaList = fromJS(media);
|
||||
|
|
@ -49,7 +50,7 @@ export default class MediaContainer extends PureComponent {
|
|||
document.body.classList.add('with-modals--active');
|
||||
document.documentElement.style.marginRight = `${getScrollbarWidth()}px`;
|
||||
|
||||
this.setState({ media: mediaList, options });
|
||||
this.setState({ media: mediaList, lang, options });
|
||||
};
|
||||
|
||||
handleCloseMedia = () => {
|
||||
|
|
@ -94,7 +95,7 @@ export default class MediaContainer extends PureComponent {
|
|||
}),
|
||||
});
|
||||
|
||||
return ReactDOM.createPortal(
|
||||
return createPortal(
|
||||
<Component {...props} key={`media-${i}`} />,
|
||||
component,
|
||||
);
|
||||
|
|
@ -105,6 +106,7 @@ export default class MediaContainer extends PureComponent {
|
|||
<MediaModal
|
||||
media={this.state.media}
|
||||
index={this.state.index || 0}
|
||||
lang={this.state.lang}
|
||||
currentTime={this.state.options?.startTime}
|
||||
autoPlay={this.state.options?.autoPlay}
|
||||
volume={this.state.options?.defaultVolume}
|
||||
|
|
|
|||
|
|
@ -221,12 +221,12 @@ const mapDispatchToProps = (dispatch, { intl, contextType }) => ({
|
|||
dispatch(mentionCompose(account, router));
|
||||
},
|
||||
|
||||
onOpenMedia (statusId, media, index) {
|
||||
dispatch(openModal('MEDIA', { statusId, media, index }));
|
||||
onOpenMedia (statusId, media, index, lang) {
|
||||
dispatch(openModal('MEDIA', { statusId, media, index, lang }));
|
||||
},
|
||||
|
||||
onOpenVideo (statusId, media, options) {
|
||||
dispatch(openModal('VIDEO', { statusId, media, options }));
|
||||
onOpenVideo (statusId, media, lang, options) {
|
||||
dispatch(openModal('VIDEO', { statusId, media, lang, options }));
|
||||
},
|
||||
|
||||
onBlock (status) {
|
||||
|
|
|
|||
|
|
@ -8,10 +8,10 @@ import LinkFooter from 'flavours/glitch/features/ui/components/link_footer';
|
|||
import { Helmet } from 'react-helmet';
|
||||
import { fetchServer, fetchExtendedDescription, fetchDomainBlocks } from 'flavours/glitch/actions/server';
|
||||
import Account from 'flavours/glitch/containers/account_container';
|
||||
import Skeleton from 'flavours/glitch/components/skeleton';
|
||||
import { Skeleton } from 'flavours/glitch/components/skeleton';
|
||||
import { Icon } from 'flavours/glitch/components/icon';
|
||||
import classNames from 'classnames';
|
||||
import { Image } from 'flavours/glitch/components/image';
|
||||
import { ServerHeroImage } from 'flavours/glitch/components/server_hero_image';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'column.about', defaultMessage: 'About' },
|
||||
|
|
@ -114,7 +114,7 @@ class About extends React.PureComponent {
|
|||
<Column bindToDocument={!multiColumn} label={intl.formatMessage(messages.title)}>
|
||||
<div className='scrollable about'>
|
||||
<div className='about__header'>
|
||||
<Image blurhash={server.getIn(['thumbnail', 'blurhash'])} src={server.getIn(['thumbnail', 'url'])} srcSet={server.getIn(['thumbnail', 'versions'])?.map((value, key) => `${value} ${key.replace('@', '')}`).join(', ')} className='about__header__hero' />
|
||||
<ServerHeroImage blurhash={server.getIn(['thumbnail', 'blurhash'])} src={server.getIn(['thumbnail', 'url'])} srcSet={server.getIn(['thumbnail', 'versions'])?.map((value, key) => `${value} ${key.replace('@', '')}`).join(', ')} className='about__header__hero' />
|
||||
<h1>{isLoading ? <Skeleton width='10ch' /> : server.get('domain')}</h1>
|
||||
<p><FormattedMessage id='about.powered_by' defaultMessage='Decentralized social media powered by {mastodon}' values={{ mastodon: <a href='https://joinmastodon.org' className='about__mail' target='_blank'>Mastodon</a> }} /></p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -142,16 +142,17 @@ class AccountGallery extends ImmutablePureComponent {
|
|||
handleOpenMedia = attachment => {
|
||||
const { dispatch } = this.props;
|
||||
const statusId = attachment.getIn(['status', 'id']);
|
||||
const lang = attachment.getIn(['status', 'language']);
|
||||
|
||||
if (attachment.get('type') === 'video') {
|
||||
dispatch(openModal('VIDEO', { media: attachment, statusId, options: { autoPlay: true } }));
|
||||
dispatch(openModal('VIDEO', { media: attachment, statusId, lang, options: { autoPlay: true } }));
|
||||
} else if (attachment.get('type') === 'audio') {
|
||||
dispatch(openModal('AUDIO', { media: attachment, statusId, options: { autoPlay: true } }));
|
||||
dispatch(openModal('AUDIO', { media: attachment, statusId, lang, options: { autoPlay: true } }));
|
||||
} else {
|
||||
const media = attachment.getIn(['status', 'media_attachments']);
|
||||
const index = media.findIndex(x => x.get('id') === attachment.get('id'));
|
||||
|
||||
dispatch(openModal('MEDIA', { media, index, statusId }));
|
||||
dispatch(openModal('MEDIA', { media, index, statusId, lang }));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes';
|
|||
import { FormattedMessage } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import AvatarOverlay from '../../../components/avatar_overlay';
|
||||
import DisplayName from '../../../components/display_name';
|
||||
import { DisplayName } from '../../../components/display_name';
|
||||
import { Icon } from 'flavours/glitch/components/icon';
|
||||
|
||||
export default class MovedNote extends ImmutablePureComponent {
|
||||
|
|
@ -21,9 +21,7 @@ export default class MovedNote extends ImmutablePureComponent {
|
|||
handleAccountClick = e => {
|
||||
if (e.button === 0) {
|
||||
e.preventDefault();
|
||||
let state = { ...this.context.router.history.location.state };
|
||||
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
|
||||
this.context.router.history.push(`/@${this.props.to.get('acct')}`, state);
|
||||
this.context.router.history.push(`/@${this.props.to.get('acct')}`);
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
@ -12,7 +12,7 @@ import HeaderContainer from './containers/header_container';
|
|||
import { List as ImmutableList } from 'immutable';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import TimelineHint from 'flavours/glitch/components/timeline_hint';
|
||||
import { TimelineHint } from 'flavours/glitch/components/timeline_hint';
|
||||
import LimitedAccountHint from './components/limited_account_hint';
|
||||
import { getAccountHidden } from 'flavours/glitch/selectors';
|
||||
import { fetchFeaturedTags } from '../../actions/featured_tags';
|
||||
|
|
@ -122,7 +122,7 @@ class AccountTimeline extends ImmutablePureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
const { dispatch } = this.props;
|
||||
|
||||
if ((nextProps.params.accountId !== this.props.params.accountId && nextProps.params.accountId) || nextProps.withReplies !== this.props.withReplies) {
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ class Audio extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
if (!is(nextProps.visible, this.props.visible) && nextProps.visible !== undefined) {
|
||||
this.setState({ revealed: nextProps.visible });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class Blocks extends ImmutablePureComponent {
|
|||
multiColumn: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
UNSAFE_componentWillMount () {
|
||||
this.props.dispatch(fetchBlocks());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class Bookmarks extends ImmutablePureComponent {
|
|||
isLoading: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
UNSAFE_componentWillMount () {
|
||||
this.props.dispatch(fetchBookmarkedStatuses());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React from 'react';
|
||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||
import DisplayName from 'flavours/glitch/components/display_name';
|
||||
import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||
|
||||
// Components.
|
||||
import { Icon } from 'flavours/glitch/components/icon';
|
||||
|
||||
// Utils.
|
||||
import { withPassive } from 'flavours/glitch/utils/dom_helpers';
|
||||
const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
|
||||
|
||||
// The component.
|
||||
export default class ComposerOptionsDropdownContent extends React.PureComponent {
|
||||
|
|
@ -41,6 +41,7 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
|
|||
handleDocumentClick = (e) => {
|
||||
if (this.node && !this.node.contains(e.target)) {
|
||||
this.props.onClose();
|
||||
e.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -51,8 +52,8 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
|
|||
|
||||
// On mounting, we add our listeners.
|
||||
componentDidMount () {
|
||||
document.addEventListener('click', this.handleDocumentClick, false);
|
||||
document.addEventListener('touchend', this.handleDocumentClick, withPassive);
|
||||
document.addEventListener('click', this.handleDocumentClick, { capture: true });
|
||||
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
|
||||
if (this.focusedItem) {
|
||||
this.focusedItem.focus({ preventScroll: true });
|
||||
} else {
|
||||
|
|
@ -62,8 +63,8 @@ export default class ComposerOptionsDropdownContent extends React.PureComponent
|
|||
|
||||
// On unmounting, we remove our listeners.
|
||||
componentWillUnmount () {
|
||||
document.removeEventListener('click', this.handleDocumentClick, false);
|
||||
document.removeEventListener('touchend', this.handleDocumentClick, withPassive);
|
||||
document.removeEventListener('click', this.handleDocumentClick, { capture: true });
|
||||
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
|
||||
}
|
||||
|
||||
handleClick = (e) => {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const messages = defineMessages({
|
|||
|
||||
let EmojiPicker, Emoji; // load asynchronously
|
||||
|
||||
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
||||
const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
|
||||
|
||||
const backgroundImageFn = () => `${assetHost}/emoji/sheet_13.png`;
|
||||
|
||||
|
|
@ -60,7 +60,7 @@ class ModifierPickerMenu extends React.PureComponent {
|
|||
this.props.onSelect(e.currentTarget.getAttribute('data-index') * 1);
|
||||
};
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.active) {
|
||||
this.attachListeners();
|
||||
} else {
|
||||
|
|
@ -79,12 +79,12 @@ class ModifierPickerMenu extends React.PureComponent {
|
|||
};
|
||||
|
||||
attachListeners () {
|
||||
document.addEventListener('click', this.handleDocumentClick, false);
|
||||
document.addEventListener('click', this.handleDocumentClick, { capture: true });
|
||||
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
|
||||
}
|
||||
|
||||
removeListeners () {
|
||||
document.removeEventListener('click', this.handleDocumentClick, false);
|
||||
document.removeEventListener('click', this.handleDocumentClick, { capture: true });
|
||||
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
|
||||
}
|
||||
|
||||
|
|
@ -177,7 +177,7 @@ class EmojiPickerMenuImpl extends React.PureComponent {
|
|||
};
|
||||
|
||||
componentDidMount () {
|
||||
document.addEventListener('click', this.handleDocumentClick, false);
|
||||
document.addEventListener('click', this.handleDocumentClick, { capture: true });
|
||||
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
|
||||
|
||||
// Because of https://github.com/react-bootstrap/react-bootstrap/issues/2614 we need
|
||||
|
|
@ -192,7 +192,7 @@ class EmojiPickerMenuImpl extends React.PureComponent {
|
|||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
document.removeEventListener('click', this.handleDocumentClick, false);
|
||||
document.removeEventListener('click', this.handleDocumentClick, { capture: true });
|
||||
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ const messages = defineMessages({
|
|||
clear: { id: 'emoji_button.clear', defaultMessage: 'Clear' },
|
||||
});
|
||||
|
||||
const listenerOptions = supportsPassiveEvents ? { passive: true } : false;
|
||||
const listenerOptions = supportsPassiveEvents ? { passive: true, capture: true } : true;
|
||||
|
||||
class LanguageDropdownMenu extends React.PureComponent {
|
||||
|
||||
|
|
@ -39,11 +39,12 @@ class LanguageDropdownMenu extends React.PureComponent {
|
|||
handleDocumentClick = e => {
|
||||
if (this.node && !this.node.contains(e.target)) {
|
||||
this.props.onClose();
|
||||
e.stopPropagation();
|
||||
}
|
||||
};
|
||||
|
||||
componentDidMount () {
|
||||
document.addEventListener('click', this.handleDocumentClick, false);
|
||||
document.addEventListener('click', this.handleDocumentClick, { capture: true });
|
||||
document.addEventListener('touchend', this.handleDocumentClick, listenerOptions);
|
||||
|
||||
// Because of https://github.com/react-bootstrap/react-bootstrap/issues/2614 we need
|
||||
|
|
@ -57,7 +58,7 @@ class LanguageDropdownMenu extends React.PureComponent {
|
|||
}
|
||||
|
||||
componentWillUnmount () {
|
||||
document.removeEventListener('click', this.handleDocumentClick, false);
|
||||
document.removeEventListener('click', this.handleDocumentClick, { capture: true });
|
||||
document.removeEventListener('touchend', this.handleDocumentClick, listenerOptions);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -59,9 +59,7 @@ class Conversation extends ImmutablePureComponent {
|
|||
}
|
||||
destination = `/statuses/${lastStatus.get('id')}`;
|
||||
}
|
||||
let state = { ...router.history.location.state };
|
||||
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
|
||||
router.history.push(destination, state);
|
||||
router.history.push(destination);
|
||||
e.preventDefault();
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import PropTypes from 'prop-types';
|
|||
import { connect } from 'react-redux';
|
||||
import { makeGetAccount } from 'flavours/glitch/selectors';
|
||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||
import DisplayName from 'flavours/glitch/components/display_name';
|
||||
import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||
import Permalink from 'flavours/glitch/components/permalink';
|
||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||
import Button from 'flavours/glitch/components/button';
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class Blocks extends ImmutablePureComponent {
|
|||
multiColumn: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
UNSAFE_componentWillMount () {
|
||||
this.props.dispatch(fetchDomainBlocks());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||
import { Blurhash } from 'flavours/glitch/components/blurhash';
|
||||
import { accountsCountRenderer } from 'flavours/glitch/components/hashtag';
|
||||
import ShortNumber from 'flavours/glitch/components/short_number';
|
||||
import Skeleton from 'flavours/glitch/components/skeleton';
|
||||
import { Skeleton } from 'flavours/glitch/components/skeleton';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export default class Story extends React.PureComponent {
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ class Favourites extends ImmutablePureComponent {
|
|||
isLoading: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
UNSAFE_componentWillMount () {
|
||||
this.props.dispatch(fetchFavouritedStatuses());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@ class Favourites extends ImmutablePureComponent {
|
|||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
UNSAFE_componentWillMount () {
|
||||
if (!this.props.accountIds) {
|
||||
this.props.dispatch(fetchFavourites(this.props.params.statusId));
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
|
||||
this.props.dispatch(fetchFavourites(nextProps.params.statusId));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
|||
import { connect } from 'react-redux';
|
||||
import { makeGetAccount } from 'flavours/glitch/selectors';
|
||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||
import DisplayName from 'flavours/glitch/components/display_name';
|
||||
import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||
import Permalink from 'flavours/glitch/components/permalink';
|
||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||
import { injectIntl, defineMessages } from 'react-intl';
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import Permalink from 'flavours/glitch/components/permalink';
|
||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||
import DisplayName from 'flavours/glitch/components/display_name';
|
||||
import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class FollowRequests extends ImmutablePureComponent {
|
|||
multiColumn: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
UNSAFE_componentWillMount () {
|
||||
this.props.dispatch(fetchFollowRequests());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import ProfileColumnHeader from 'flavours/glitch/features/account/components/pro
|
|||
import HeaderContainer from 'flavours/glitch/features/account_timeline/containers/header_container';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ScrollableList from 'flavours/glitch/components/scrollable_list';
|
||||
import TimelineHint from 'flavours/glitch/components/timeline_hint';
|
||||
import { TimelineHint } from 'flavours/glitch/components/timeline_hint';
|
||||
import LimitedAccountHint from '../account_timeline/components/limited_account_hint';
|
||||
import { getAccountHidden } from 'flavours/glitch/selectors';
|
||||
import { normalizeForLookup } from 'flavours/glitch/reducers/accounts_map';
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import ProfileColumnHeader from 'flavours/glitch/features/account/components/pro
|
|||
import HeaderContainer from 'flavours/glitch/features/account_timeline/containers/header_container';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ScrollableList from 'flavours/glitch/components/scrollable_list';
|
||||
import TimelineHint from 'flavours/glitch/components/timeline_hint';
|
||||
import { TimelineHint } from 'flavours/glitch/components/timeline_hint';
|
||||
import LimitedAccountHint from '../account_timeline/components/limited_account_hint';
|
||||
import { getAccountHidden } from 'flavours/glitch/selectors';
|
||||
import { normalizeForLookup } from 'flavours/glitch/reducers/accounts_map';
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ class GettingStarted extends ImmutablePureComponent {
|
|||
openSettings: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
UNSAFE_componentWillMount () {
|
||||
this.props.fetchLists();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -143,7 +143,7 @@ class InteractionModal extends React.PureComponent {
|
|||
<div className='interaction-modal__choices'>
|
||||
<div className='interaction-modal__choices__choice'>
|
||||
<h3><FormattedMessage id='interaction_modal.on_this_server' defaultMessage='On this server' /></h3>
|
||||
<a href='/auth/sign_in' className='button button--block'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Sign in' /></a>
|
||||
<a href='/auth/sign_in' className='button button--block'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Login' /></a>
|
||||
{signupButton}
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { makeGetAccount } from '../../../selectors';
|
|||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { Avatar } from '../../../components/avatar';
|
||||
import DisplayName from '../../../components/display_name';
|
||||
import { DisplayName } from '../../../components/display_name';
|
||||
import { injectIntl } from 'react-intl';
|
||||
|
||||
const makeMapStateToProps = () => {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||
import DisplayName from 'flavours/glitch/components/display_name';
|
||||
import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||
import { defineMessages } from 'react-intl';
|
||||
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ class ListTimeline extends React.PureComponent {
|
|||
this.disconnect = dispatch(connectListStream(id));
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
const { dispatch } = this.props;
|
||||
const { id } = nextProps.params;
|
||||
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ class Lists extends ImmutablePureComponent {
|
|||
multiColumn: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
UNSAFE_componentWillMount () {
|
||||
this.props.dispatch(fetchLists());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class Mutes extends ImmutablePureComponent {
|
|||
multiColumn: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
UNSAFE_componentWillMount () {
|
||||
this.props.dispatch(fetchMutes());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { Fragment } from 'react';
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import PropTypes from 'prop-types';
|
||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||
import DisplayName from 'flavours/glitch/components/display_name';
|
||||
import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||
import Permalink from 'flavours/glitch/components/permalink';
|
||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||
import { defineMessages, injectIntl, FormattedMessage } from 'react-intl';
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import PropTypes from 'prop-types';
|
|||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||
import { Link } from 'react-router-dom';
|
||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||
import DisplayName from 'flavours/glitch/components/display_name';
|
||||
import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
|
||||
const messages = defineMessages({
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ class PinnedStatuses extends ImmutablePureComponent {
|
|||
multiColumn: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
UNSAFE_componentWillMount () {
|
||||
this.props.dispatch(fetchPinnedStatuses());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import { Helmet } from 'react-helmet';
|
|||
import { FormattedMessage, FormattedDate, injectIntl, defineMessages } from 'react-intl';
|
||||
import Column from 'flavours/glitch/components/column';
|
||||
import api from 'flavours/glitch/api';
|
||||
import Skeleton from 'flavours/glitch/components/skeleton';
|
||||
import { Skeleton } from 'flavours/glitch/components/skeleton';
|
||||
|
||||
const messages = defineMessages({
|
||||
title: { id: 'privacy_policy.title', defaultMessage: 'Privacy Policy' },
|
||||
|
|
|
|||
|
|
@ -32,13 +32,13 @@ class Reblogs extends ImmutablePureComponent {
|
|||
intl: PropTypes.object.isRequired,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
UNSAFE_componentWillMount () {
|
||||
if (!this.props.accountIds) {
|
||||
this.props.dispatch(fetchReblogs(this.props.params.statusId));
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.params.statusId !== this.props.params.statusId && nextProps.params.statusId) {
|
||||
this.props.dispatch(fetchReblogs(nextProps.params.statusId));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import StatusContent from 'flavours/glitch/components/status_content';
|
||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||
import DisplayName from 'flavours/glitch/components/display_name';
|
||||
import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||
import { RelativeTimestamp } from 'flavours/glitch/components/relative_timestamp';
|
||||
import Option from './option';
|
||||
import MediaAttachments from 'flavours/glitch/components/media_attachments';
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ export default class Card extends React.PureComponent {
|
|||
revealed: !this.props.sensitive,
|
||||
};
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
if (!Immutable.is(this.props.card, nextProps.card)) {
|
||||
this.setState({ embedded: false, previewLoaded: false });
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||
import DisplayName from 'flavours/glitch/components/display_name';
|
||||
import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||
import StatusContent from 'flavours/glitch/components/status_content';
|
||||
import MediaGallery from 'flavours/glitch/components/media_gallery';
|
||||
import AttachmentList from 'flavours/glitch/components/attachment_list';
|
||||
|
|
@ -59,9 +59,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||
handleAccountClick = (e) => {
|
||||
if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey) && this.context.router) {
|
||||
e.preventDefault();
|
||||
let state = { ...this.context.router.history.location.state };
|
||||
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
|
||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`, state);
|
||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
|
|
@ -70,9 +68,7 @@ class DetailedStatus extends ImmutablePureComponent {
|
|||
parseClick = (e, destination) => {
|
||||
if (e.button === 0 && !(e.ctrlKey || e.altKey || e.metaKey) && this.context.router) {
|
||||
e.preventDefault();
|
||||
let state = { ...this.context.router.history.location.state };
|
||||
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
|
||||
this.context.router.history.push(destination, state);
|
||||
this.context.router.history.push(destination);
|
||||
}
|
||||
|
||||
e.stopPropagation();
|
||||
|
|
|
|||
|
|
@ -125,12 +125,12 @@ const mapDispatchToProps = (dispatch, { intl }) => ({
|
|||
dispatch(mentionCompose(account, router));
|
||||
},
|
||||
|
||||
onOpenMedia (media, index) {
|
||||
dispatch(openModal('MEDIA', { media, index }));
|
||||
onOpenMedia (media, index, lang) {
|
||||
dispatch(openModal('MEDIA', { media, index, lang }));
|
||||
},
|
||||
|
||||
onOpenVideo (media, options) {
|
||||
dispatch(openModal('VIDEO', { media, options }));
|
||||
onOpenVideo (media, lang, options) {
|
||||
dispatch(openModal('VIDEO', { media, lang, options }));
|
||||
},
|
||||
|
||||
onBlock (status) {
|
||||
|
|
|
|||
|
|
@ -407,12 +407,12 @@ class Status extends ImmutablePureComponent {
|
|||
this.props.dispatch(mentionCompose(account, router));
|
||||
};
|
||||
|
||||
handleOpenMedia = (media, index) => {
|
||||
this.props.dispatch(openModal('MEDIA', { statusId: this.props.status.get('id'), media, index }));
|
||||
handleOpenMedia = (media, index, lang) => {
|
||||
this.props.dispatch(openModal('MEDIA', { statusId: this.props.status.get('id'), media, index, lang }));
|
||||
};
|
||||
|
||||
handleOpenVideo = (media, options) => {
|
||||
this.props.dispatch(openModal('VIDEO', { statusId: this.props.status.get('id'), media, options }));
|
||||
handleOpenVideo = (media, lang, options) => {
|
||||
this.props.dispatch(openModal('VIDEO', { statusId: this.props.status.get('id'), media, lang, options }));
|
||||
};
|
||||
|
||||
handleHotkeyOpenMedia = e => {
|
||||
|
|
@ -517,9 +517,7 @@ class Status extends ImmutablePureComponent {
|
|||
};
|
||||
|
||||
handleHotkeyOpenProfile = () => {
|
||||
let state = { ...this.context.router.history.location.state };
|
||||
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
|
||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`, state);
|
||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
|
||||
};
|
||||
|
||||
handleMoveUp = id => {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component';
|
|||
import StatusContent from 'flavours/glitch/components/status_content';
|
||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||
import { RelativeTimestamp } from 'flavours/glitch/components/relative_timestamp';
|
||||
import DisplayName from 'flavours/glitch/components/display_name';
|
||||
import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||
import classNames from 'classnames';
|
||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import Button from 'flavours/glitch/components/button';
|
|||
import StatusContent from 'flavours/glitch/components/status_content';
|
||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||
import { RelativeTimestamp } from 'flavours/glitch/components/relative_timestamp';
|
||||
import DisplayName from 'flavours/glitch/components/display_name';
|
||||
import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||
import AttachmentList from 'flavours/glitch/components/attachment_list';
|
||||
import { Icon } from 'flavours/glitch/components/icon';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
|
@ -62,9 +62,7 @@ class BoostModal extends ImmutablePureComponent {
|
|||
if (e.button === 0) {
|
||||
e.preventDefault();
|
||||
this.props.onClose();
|
||||
let state = { ...this.context.router.history.location.state };
|
||||
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
|
||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`, state);
|
||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -33,11 +33,11 @@ class Bundle extends React.Component {
|
|||
forceRender: false,
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
UNSAFE_componentWillMount() {
|
||||
this.load(this.props);
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps) {
|
||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
||||
if (nextProps.fetchComponent !== this.props.fetchComponent) {
|
||||
this.load(nextProps);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class EmbedModal extends ImmutablePureComponent {
|
|||
className='embed-modal__iframe'
|
||||
frameBorder='0'
|
||||
ref={this.setIframeRef}
|
||||
sandbox='allow-same-origin'
|
||||
sandbox='allow-scripts allow-same-origin'
|
||||
title='preview'
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import Button from 'flavours/glitch/components/button';
|
|||
import StatusContent from 'flavours/glitch/components/status_content';
|
||||
import { Avatar } from 'flavours/glitch/components/avatar';
|
||||
import { RelativeTimestamp } from 'flavours/glitch/components/relative_timestamp';
|
||||
import DisplayName from 'flavours/glitch/components/display_name';
|
||||
import { DisplayName } from 'flavours/glitch/components/display_name';
|
||||
import AttachmentList from 'flavours/glitch/components/attachment_list';
|
||||
import { Icon } from 'flavours/glitch/components/icon';
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component';
|
||||
|
|
@ -43,9 +43,7 @@ class FavouriteModal extends ImmutablePureComponent {
|
|||
if (e.button === 0) {
|
||||
e.preventDefault();
|
||||
this.props.onClose();
|
||||
let state = { ...this.context.router.history.location.state };
|
||||
state.mastodonBackSteps = (state.mastodonBackSteps || 0) + 1;
|
||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`, state);
|
||||
this.context.router.history.push(`/@${this.props.status.getIn(['account', 'acct'])}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
|
|
|||
|
|
@ -52,13 +52,13 @@ class Header extends React.PureComponent {
|
|||
|
||||
if (registrationsOpen) {
|
||||
signupButton = (
|
||||
<a href='/auth/sign_up' className='button button-tertiary'>
|
||||
<a href='/auth/sign_up' className='button'>
|
||||
<FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
signupButton = (
|
||||
<button className='button button-tertiary' onClick={openClosedRegistrationsModal}>
|
||||
<button className='button' onClick={openClosedRegistrationsModal}>
|
||||
<FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
|
||||
</button>
|
||||
);
|
||||
|
|
@ -66,8 +66,8 @@ class Header extends React.PureComponent {
|
|||
|
||||
content = (
|
||||
<>
|
||||
<a href='/auth/sign_in' className='button'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Sign in' /></a>
|
||||
{signupButton}
|
||||
<a href='/auth/sign_in' className='button button-tertiary'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Login' /></a>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import ReactSwipeableViews from 'react-swipeable-views';
|
|||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import PropTypes from 'prop-types';
|
||||
import Video from 'flavours/glitch/features/video';
|
||||
import { connect } from 'react-redux';
|
||||
import classNames from 'classnames';
|
||||
import { defineMessages, injectIntl } from 'react-intl';
|
||||
import { IconButton } from 'flavours/glitch/components/icon_button';
|
||||
|
|
@ -21,10 +20,6 @@ const messages = defineMessages({
|
|||
next: { id: 'lightbox.next', defaultMessage: 'Next' },
|
||||
});
|
||||
|
||||
const mapStateToProps = (state, { statusId }) => ({
|
||||
language: state.getIn(['statuses', statusId, 'language']),
|
||||
});
|
||||
|
||||
class MediaModal extends ImmutablePureComponent {
|
||||
|
||||
static contextTypes = {
|
||||
|
|
@ -34,6 +29,7 @@ class MediaModal extends ImmutablePureComponent {
|
|||
static propTypes = {
|
||||
media: ImmutablePropTypes.list.isRequired,
|
||||
statusId: PropTypes.string,
|
||||
lang: PropTypes.string,
|
||||
index: PropTypes.number.isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
|
|
@ -135,7 +131,7 @@ class MediaModal extends ImmutablePureComponent {
|
|||
}
|
||||
|
||||
render () {
|
||||
const { media, language, statusId, intl, onClose } = this.props;
|
||||
const { media, statusId, lang, intl, onClose } = this.props;
|
||||
const { navigationHidden } = this.state;
|
||||
|
||||
const index = this.getIndex();
|
||||
|
|
@ -155,7 +151,7 @@ class MediaModal extends ImmutablePureComponent {
|
|||
width={width}
|
||||
height={height}
|
||||
alt={image.get('description')}
|
||||
lang={language}
|
||||
lang={lang}
|
||||
key={image.get('url')}
|
||||
onClick={this.toggleNavigation}
|
||||
zoomButtonHidden={this.state.zoomButtonHidden}
|
||||
|
|
@ -178,7 +174,7 @@ class MediaModal extends ImmutablePureComponent {
|
|||
onCloseVideo={onClose}
|
||||
detailed
|
||||
alt={image.get('description')}
|
||||
lang={language}
|
||||
lang={lang}
|
||||
key={image.get('url')}
|
||||
/>
|
||||
);
|
||||
|
|
@ -190,7 +186,7 @@ class MediaModal extends ImmutablePureComponent {
|
|||
height={height}
|
||||
key={image.get('url')}
|
||||
alt={image.get('description')}
|
||||
lang={language}
|
||||
lang={lang}
|
||||
onClick={this.toggleNavigation}
|
||||
/>
|
||||
);
|
||||
|
|
@ -258,4 +254,4 @@ class MediaModal extends ImmutablePureComponent {
|
|||
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, null, null, { forwardRef: true })(injectIntl(MediaModal));
|
||||
export default injectIntl(MediaModal);
|
||||
|
|
|
|||
|
|
@ -184,7 +184,7 @@ class OnboardingModal extends React.PureComponent {
|
|||
currentIndex: 0,
|
||||
};
|
||||
|
||||
componentWillMount() {
|
||||
UNSAFE_componentWillMount() {
|
||||
const { myAccount, admin, domain, intl } = this.props;
|
||||
this.pages = [
|
||||
<PageOne key='1' acct={myAccount.get('acct')} domain={domain} />,
|
||||
|
|
|
|||
|
|
@ -16,13 +16,13 @@ const SignInBanner = () => {
|
|||
|
||||
if (registrationsOpen) {
|
||||
signupButton = (
|
||||
<a href='/auth/sign_up' className='button button--block button-tertiary'>
|
||||
<a href='/auth/sign_up' className='button button--block'>
|
||||
<FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
|
||||
</a>
|
||||
);
|
||||
} else {
|
||||
signupButton = (
|
||||
<button className='button button--block button-tertiary' onClick={openClosedRegistrationsModal}>
|
||||
<button className='button button--block' onClick={openClosedRegistrationsModal}>
|
||||
<FormattedMessage id='sign_in_banner.create_account' defaultMessage='Create account' />
|
||||
</button>
|
||||
);
|
||||
|
|
@ -30,9 +30,9 @@ const SignInBanner = () => {
|
|||
|
||||
return (
|
||||
<div className='sign-in-banner'>
|
||||
<p><FormattedMessage id='sign_in_banner.text' defaultMessage='Sign in to follow profiles or hashtags, favourite, share and reply to posts. You can also interact from your account on a different server.' /></p>
|
||||
<a href='/auth/sign_in' className='button button--block'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Sign in' /></a>
|
||||
<p><FormattedMessage id='sign_in_banner.text' defaultMessage='Login to follow profiles or hashtags, favourite, share and reply to posts. You can also interact from your account on a different server.' /></p>
|
||||
{signupButton}
|
||||
<a href='/auth/sign_in' className='button button--block button-tertiary'><FormattedMessage id='sign_in_banner.sign_in' defaultMessage='Login' /></a>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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';
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ const makeMapStateToProps = () => {
|
|||
|
||||
const mapStateToProps = (state, { timelineId, regex }) => ({
|
||||
statusIds: getStatusIds(state, { type: timelineId, regex }),
|
||||
lastId: state.getIn(['timelines', timelineId, 'items'])?.last(),
|
||||
isLoading: state.getIn(['timelines', timelineId, 'isLoading'], true),
|
||||
isPartial: state.getIn(['timelines', timelineId, 'isPartial'], false),
|
||||
hasMore: state.getIn(['timelines', timelineId, 'hasMore']),
|
||||
|
|
|
|||
|
|
@ -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.' },
|
||||
|
|
@ -133,7 +133,7 @@ class SwitchingColumnsArea extends React.PureComponent {
|
|||
mobile: PropTypes.bool,
|
||||
};
|
||||
|
||||
componentWillMount () {
|
||||
UNSAFE_componentWillMount () {
|
||||
if (this.props.mobile) {
|
||||
document.body.classList.toggle('layout-single-column', true);
|
||||
document.body.classList.toggle('layout-multiple-columns', false);
|
||||
|
|
@ -438,7 +438,7 @@ class UI extends React.Component {
|
|||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
if (nextProps.layout_local_setting !== this.props.layout_local_setting) {
|
||||
const layout = layoutFromWindow(nextProps.layout_local_setting);
|
||||
|
||||
|
|
|
|||
|
|
@ -373,7 +373,7 @@ class Video extends React.PureComponent {
|
|||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
UNSAFE_componentWillReceiveProps (nextProps) {
|
||||
if (!is(nextProps.visible, this.props.visible) && nextProps.visible !== undefined) {
|
||||
this.setState({ revealed: nextProps.visible });
|
||||
}
|
||||
|
|
@ -476,7 +476,7 @@ class Video extends React.PureComponent {
|
|||
handleOpenVideo = () => {
|
||||
this.video.pause();
|
||||
|
||||
this.props.onOpenVideo({
|
||||
this.props.onOpenVideo(this.props.lang, {
|
||||
startTime: this.video.currentTime,
|
||||
autoPlay: !this.state.paused,
|
||||
defaultVolume: this.state.volume,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { supportsPassiveEvents } from 'detect-passive-events';
|
||||
|
||||
import { forceSingleColumn } from 'flavours/glitch/initial_state';
|
||||
|
||||
const LAYOUT_BREAKPOINT = 630;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
import { setupBrowserNotifications } from 'flavours/glitch/actions/notifications';
|
||||
import Mastodon from 'flavours/glitch/containers/mastodon';
|
||||
import { store } from 'flavours/glitch/store';
|
||||
|
|
@ -18,7 +18,8 @@ function main() {
|
|||
const mountNode = document.getElementById('mastodon');
|
||||
const props = JSON.parse(mountNode.getAttribute('data-props'));
|
||||
|
||||
ReactDOM.render(<Mastodon {...props} />, mountNode);
|
||||
const root = createRoot(mountNode);
|
||||
root.render(<Mastodon {...props} />);
|
||||
store.dispatch(setupBrowserNotifications());
|
||||
|
||||
if (process.env.NODE_ENV === 'production' && me && 'serviceWorker' in navigator) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import 'packs/public-path';
|
||||
import ready from 'flavours/glitch/ready';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
ready(() => {
|
||||
[].forEach.call(document.querySelectorAll('[data-admin-component]'), element => {
|
||||
|
|
@ -10,11 +10,13 @@ ready(() => {
|
|||
|
||||
import('flavours/glitch/containers/admin_component').then(({ default: AdminComponent }) => {
|
||||
return import('flavours/glitch/components/admin/' + componentName).then(({ default: Component }) => {
|
||||
ReactDOM.render((
|
||||
const root = createRoot(element);
|
||||
|
||||
root.render (
|
||||
<AdminComponent locale={locale}>
|
||||
<Component {...componentProps} />
|
||||
</AdminComponent>
|
||||
), element);
|
||||
</AdminComponent>,
|
||||
);
|
||||
});
|
||||
}).catch(error => {
|
||||
console.error(error);
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue