[Proposal] Make able to write React in Typescript (#16210)
Co-authored-by: berlysia <berlysia@gmail.com> Co-authored-by: fusagiko / takayamaki <takayamaki@users.noreply.github.com>
This commit is contained in:
parent
2f7c3cb628
commit
4520e6473a
26 changed files with 1099 additions and 211 deletions
|
@ -1,62 +0,0 @@
|
|||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { autoPlayGif } from '../initial_state';
|
||||
import classNames from 'classnames';
|
||||
|
||||
export default class Avatar extends React.PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
size: PropTypes.number.isRequired,
|
||||
style: PropTypes.object,
|
||||
inline: PropTypes.bool,
|
||||
animate: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
animate: autoPlayGif,
|
||||
size: 20,
|
||||
inline: false,
|
||||
};
|
||||
|
||||
state = {
|
||||
hovering: false,
|
||||
};
|
||||
|
||||
handleMouseEnter = () => {
|
||||
if (this.props.animate) return;
|
||||
this.setState({ hovering: true });
|
||||
};
|
||||
|
||||
handleMouseLeave = () => {
|
||||
if (this.props.animate) return;
|
||||
this.setState({ hovering: false });
|
||||
};
|
||||
|
||||
render () {
|
||||
const { account, size, animate, inline } = this.props;
|
||||
const { hovering } = this.state;
|
||||
|
||||
const style = {
|
||||
...this.props.style,
|
||||
width: `${size}px`,
|
||||
height: `${size}px`,
|
||||
};
|
||||
|
||||
let src;
|
||||
|
||||
if (hovering || animate) {
|
||||
src = account?.get('avatar');
|
||||
} else {
|
||||
src = account?.get('avatar_static');
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classNames('account__avatar', { 'account__avatar-inline': inline })} onMouseEnter={this.handleMouseEnter} onMouseLeave={this.handleMouseLeave} style={style}>
|
||||
{src && <img src={src} alt={account?.get('acct')} />}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
}
|
40
app/javascript/mastodon/components/avatar.tsx
Normal file
40
app/javascript/mastodon/components/avatar.tsx
Normal file
|
@ -0,0 +1,40 @@
|
|||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { autoPlayGif } from '../initial_state';
|
||||
import { useHovering } from '../../hooks/useHovering';
|
||||
import type { Account } from '../../types/resources';
|
||||
|
||||
type Props = {
|
||||
account: Account;
|
||||
size: number;
|
||||
style?: React.CSSProperties;
|
||||
inline?: boolean;
|
||||
animate?: boolean;
|
||||
}
|
||||
|
||||
export const Avatar: React.FC<Props> = ({
|
||||
account,
|
||||
animate = autoPlayGif,
|
||||
size = 20,
|
||||
inline = false,
|
||||
style: styleFromParent,
|
||||
}) => {
|
||||
|
||||
const { hovering, handleMouseEnter, handleMouseLeave } = useHovering(animate);
|
||||
|
||||
const style = {
|
||||
...styleFromParent,
|
||||
width: `${size}px`,
|
||||
height: `${size}px`,
|
||||
};
|
||||
|
||||
const src = (hovering || animate) ? account?.get('avatar') : account?.get('avatar_static');
|
||||
|
||||
return (
|
||||
<div className={classNames('account__avatar', { 'account__avatar-inline': inline })} onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} style={style}>
|
||||
{src && <img src={src} alt={account?.get('acct')} />}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Avatar;
|
|
@ -44,6 +44,7 @@ function Blurhash({
|
|||
const ctx = canvas.getContext('2d');
|
||||
const imageData = new ImageData(pixels, width, height);
|
||||
|
||||
// @ts-expect-error
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
} catch (err) {
|
||||
console.error('Blurhash decoding failure', { err, hash });
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// @ts-check
|
||||
import React from 'react';
|
||||
// @ts-expect-error
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
// @ts-check
|
||||
import React from 'react';
|
||||
import { Sparklines, SparklinesCurve } from 'react-sparklines';
|
||||
// @ts-expect-error
|
||||
import { FormattedMessage } from 'react-intl';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import { Link } from 'react-router-dom';
|
||||
// @ts-expect-error
|
||||
import ShortNumber from 'mastodon/components/short_number';
|
||||
// @ts-expect-error
|
||||
import Skeleton from 'mastodon/components/skeleton';
|
||||
import classNames from 'classnames';
|
||||
|
||||
|
@ -19,11 +22,11 @@ class SilentErrorBoundary extends React.Component {
|
|||
error: false,
|
||||
};
|
||||
|
||||
componentDidCatch () {
|
||||
componentDidCatch() {
|
||||
this.setState({ error: true });
|
||||
}
|
||||
|
||||
render () {
|
||||
render() {
|
||||
if (this.state.error) {
|
||||
return null;
|
||||
}
|
||||
|
@ -50,11 +53,13 @@ export const accountsCountRenderer = (displayNumber, pluralReady) => (
|
|||
/>
|
||||
);
|
||||
|
||||
// @ts-expect-error
|
||||
export const ImmutableHashtag = ({ hashtag }) => (
|
||||
<Hashtag
|
||||
name={hashtag.get('name')}
|
||||
to={`/tags/${hashtag.get('name')}`}
|
||||
people={hashtag.getIn(['history', 0, 'accounts']) * 1 + hashtag.getIn(['history', 1, 'accounts']) * 1}
|
||||
// @ts-expect-error
|
||||
history={hashtag.get('history').reverse().map((day) => day.get('uses')).toArray()}
|
||||
/>
|
||||
);
|
||||
|
@ -63,6 +68,7 @@ ImmutableHashtag.propTypes = {
|
|||
hashtag: ImmutablePropTypes.map.isRequired,
|
||||
};
|
||||
|
||||
// @ts-expect-error
|
||||
const Hashtag = ({ name, to, people, uses, history, className, description, withGraph }) => (
|
||||
<div className={classNames('trends__item', className)}>
|
||||
<div className='trends__item__name'>
|
||||
|
@ -86,7 +92,9 @@ const Hashtag = ({ name, to, people, uses, history, className, description, with
|
|||
{withGraph && (
|
||||
<div className='trends__item__sparkline'>
|
||||
<SilentErrorBoundary>
|
||||
{/* @ts-expect-error */}
|
||||
<Sparklines width={50} height={28} data={history ? history : Array.from(Array(7)).map(() => 0)}>
|
||||
{/* @ts-expect-error */}
|
||||
<SparklinesCurve style={{ fill: 'none' }} />
|
||||
</Sparklines>
|
||||
</SilentErrorBoundary>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue