Merge pull request #2236 from ClearlyClaire/glitch-soc/merge-upstream
Merge upstream changes up to e387175fc9
local
commit
0222df6047
335 changed files with 3902 additions and 1517 deletions
@ -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,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> |
||||
); |
||||
} |
||||
|
||||
} |
@ -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,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; |
@ -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> |
||||
); |
@ -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; |
@ -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> |
||||
); |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue