Progress
This commit is contained in:
@@ -175,7 +175,7 @@ class Comment extends ImmutablePureComponent {
|
||||
isComment
|
||||
collapsable
|
||||
/>
|
||||
<div className={[_s.default].join(' ')}>
|
||||
<div className={[_s.default, _s.mt5].join(' ')}>
|
||||
<StatusMedia
|
||||
isComment
|
||||
status={status}
|
||||
|
||||
@@ -31,7 +31,7 @@ class FloatingActionButton extends PureComponent {
|
||||
return (
|
||||
<Button
|
||||
onClick={onOpenCompose}
|
||||
className={[_s.posFixed, _s.z4, _s.py15, _s.mb15, _s.mr15, _s.bottom0, _s.right0].join(' ')}
|
||||
className={[_s.posFixed, _s.z4, _s.py15, _s.mb15, _s.mr15, _s.bottom50PX, _s.right0].join(' ')}
|
||||
title={message}
|
||||
aria-label={message}
|
||||
icon='pencil'
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
import { NavLink, withRouter } from 'react-router-dom';
|
||||
import { FormattedMessage, injectIntl } from 'react-intl';
|
||||
import NotificationCounter from '../notification_counter';
|
||||
|
||||
// : todo :
|
||||
|
||||
const links = [
|
||||
<NavLink key='pr1' className='footer-bar__link' to='/home' data-preview-title-id='column.home'>
|
||||
<i className='tabs-bar__link__icon home' />
|
||||
<FormattedMessage id='tabs_bar.home' defaultMessage='Home' />
|
||||
</NavLink>,
|
||||
<NavLink key='pr2' className='footer-bar__link' to='/notifications' data-preview-title-id='column.notifications'>
|
||||
<i className='tabs-bar__link__icon notifications'/>
|
||||
<NotificationCounter />
|
||||
<FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' />
|
||||
</NavLink>,
|
||||
<a key='pl5' className='footer-bar__link footer-bar__link--chat' href='https://chat.gab.com' data-preview-title-id='tabs_bar.chat'>
|
||||
<Icon id='comments' className='tabs-bar__link__icon chat' />
|
||||
<FormattedMessage id='tabs_bar.chat' defaultMessage='Chat' />
|
||||
</a>,
|
||||
<a key='pl4' className='footer-bar__link footer-bar__link--trends' href='https://trends.gab.com' data-preview-title-id='tabs_bar.trends'>
|
||||
<i className='tabs-bar__link__icon trends' />
|
||||
<FormattedMessage id='tabs_bar.trends' defaultMessage='Trends' />
|
||||
</a>,
|
||||
<NavLink key='pr3' className='footer-bar__link' to='/groups' data-preview-title-id='column.groups'>
|
||||
<i className='tabs-bar__link__icon groups' />
|
||||
<FormattedMessage id='tabs_bar.groups' defaultMessage='Groups' />
|
||||
</NavLink>,
|
||||
]
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
@withRouter
|
||||
class FooterBar extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl: { formatMessage } } = this.props;
|
||||
|
||||
return (
|
||||
<div className='footer-bar'>
|
||||
<div className='footer-bar__container'>
|
||||
{
|
||||
links.map((link) =>
|
||||
React.cloneElement(link, {
|
||||
key: link.props.to,
|
||||
'aria-label': formatMessage({
|
||||
id: link.props['data-preview-title-id']
|
||||
})
|
||||
}))
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
88
app/javascript/gabsocial/components/footer_bar.js
Normal file
88
app/javascript/gabsocial/components/footer_bar.js
Normal file
@@ -0,0 +1,88 @@
|
||||
import { NavLink, withRouter } from 'react-router-dom';
|
||||
import { FormattedMessage, injectIntl } from 'react-intl';
|
||||
import Button from './button'
|
||||
import Icon from './icon'
|
||||
|
||||
const links = [
|
||||
<NavLink key='pr1' className='footer-bar__link' to='/home' data-preview-title-id='column.home'>
|
||||
<i className='tabs-bar__link__icon home' />
|
||||
<FormattedMessage id='tabs_bar.home' defaultMessage='Home' />
|
||||
</NavLink>,
|
||||
<NavLink key='pr2' className='footer-bar__link' to='/notifications' data-preview-title-id='column.notifications'>
|
||||
<i className='tabs-bar__link__icon notifications' />
|
||||
<FormattedMessage id='tabs_bar.notifications' defaultMessage='Notifications' />
|
||||
</NavLink>,
|
||||
<a key='pl5' className='footer-bar__link footer-bar__link--chat' href='https://chat.gab.com' data-preview-title-id='tabs_bar.chat'>
|
||||
<FormattedMessage id='tabs_bar.chat' defaultMessage='Chat' />
|
||||
</a>,
|
||||
<a key='pl4' className='footer-bar__link footer-bar__link--trends' href='https://trends.gab.com' data-preview-title-id='tabs_bar.trends'>
|
||||
<i className='tabs-bar__link__icon trends' />
|
||||
<FormattedMessage id='tabs_bar.trends' defaultMessage='Trends' />
|
||||
</a>,
|
||||
<NavLink key='pr3' className='footer-bar__link' to='/groups' data-preview-title-id='column.groups'>
|
||||
<i className='tabs-bar__link__icon groups' />
|
||||
<FormattedMessage id='tabs_bar.groups' defaultMessage='Groups' />
|
||||
</NavLink>,
|
||||
]
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
@withRouter
|
||||
class FooterBar extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
}
|
||||
|
||||
handleSettings = () => {
|
||||
//
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl } = this.props
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.z4, _s.height53PX, _s.width100PC].join(' ')}>
|
||||
<div className={[_s.default, _s.posFixed, _s.left0, _s.right0, _s.bottom0, _s.height53PX, _s.width100PC, _s.bgPrimary, _s.borderTop1PX, _s.borderColorSecondary].join(' ')}>
|
||||
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter, _s.justifyContentSpaceAround].join(' ')}>
|
||||
<Button
|
||||
backgroundColor='none'
|
||||
color='secondary'
|
||||
to='/home'
|
||||
icon='home'
|
||||
iconSize='20px'
|
||||
/>
|
||||
<Button
|
||||
backgroundColor='none'
|
||||
color='secondary'
|
||||
to='/search'
|
||||
icon='search'
|
||||
iconSize='20px'
|
||||
/>
|
||||
<Button
|
||||
backgroundColor='none'
|
||||
color='secondary'
|
||||
to='/notifications'
|
||||
icon='notifications'
|
||||
iconSize='20px'
|
||||
/>
|
||||
<Button
|
||||
backgroundColor='none'
|
||||
color='secondary'
|
||||
to='/groups'
|
||||
icon='group'
|
||||
iconSize='20px'
|
||||
/>
|
||||
<Button
|
||||
backgroundColor='none'
|
||||
color='secondary'
|
||||
onClick={this.handleSettings}
|
||||
icon='hamburger'
|
||||
iconSize='20px'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,7 @@ class IntersectionObserverArticle extends React.Component {
|
||||
|
||||
state = {
|
||||
isIntersecting: false,
|
||||
isHidden: true,
|
||||
isHidden: false,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
@@ -142,7 +142,7 @@ class IntersectionObserverArticle extends React.Component {
|
||||
data-id={id}
|
||||
tabIndex='0'
|
||||
>
|
||||
{React.cloneElement(children, { isHidden: true })}
|
||||
{React.cloneElement(children, { isHidden: true, cachedHeight })}
|
||||
</article>
|
||||
)
|
||||
}
|
||||
@@ -155,7 +155,7 @@ class IntersectionObserverArticle extends React.Component {
|
||||
data-id={id}
|
||||
tabIndex='0'
|
||||
>
|
||||
{React.cloneElement(children, { isHidden: false, isIntersecting })}
|
||||
{React.cloneElement(children, { isHidden: false, isIntersecting, cachedHeight })}
|
||||
</article>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -253,6 +253,7 @@ class MediaGallery extends PureComponent {
|
||||
visible: PropTypes.bool,
|
||||
onToggleVisibility: PropTypes.func,
|
||||
reduced: PropTypes.bool,
|
||||
isComment: PropTypes.bool,
|
||||
};
|
||||
|
||||
static defaultProps = {
|
||||
|
||||
@@ -7,6 +7,7 @@ import Responsive from '../features/ui/util/responsive_component'
|
||||
import { CX } from '../constants'
|
||||
import Avatar from './avatar'
|
||||
import Button from './button'
|
||||
import Heading from './heading'
|
||||
import Icon from './icon'
|
||||
import Search from './search'
|
||||
import Text from './text'
|
||||
@@ -48,11 +49,31 @@ class NavigationBar extends ImmutablePureComponent {
|
||||
|
||||
<div className={[_s.default, _s.flexRow].join(' ')}>
|
||||
|
||||
<h1 className={[_s.default, _s.mr15].join(' ')}>
|
||||
<Button to='/' isText title='Gab' aria-label='Gab' className={[_s.default, _s.justifyContentCenter, _s.noSelect, _s.noUnderline, _s.height53PX, _s.cursorPointer, _s.px10, _s.mr15].join(' ')}>
|
||||
<Icon id='gab-logo' className={_s.fillWhite} />
|
||||
</Button>
|
||||
</h1>
|
||||
<Responsive max={BREAKPOINT_EXTRA_SMALL}>
|
||||
{
|
||||
!!account &&
|
||||
<button
|
||||
title={account.get('display_name')}
|
||||
onClick={this.handleProfileClick}
|
||||
className={[_s.height53PX, _s.bgTransparent, _s.outlineNone, _s.cursorPointer, _s.default, _s.justifyContentCenter, _s.ml15].join(' ')}
|
||||
>
|
||||
<Avatar account={account} size={32} noHover />
|
||||
</button>
|
||||
}
|
||||
<div className={[_s.default, _s.height53PX, _s.justifyContentCenter, _s.mlAuto, _s.mrAuto].join(' ')}>
|
||||
<Heading size='h1'>
|
||||
{title}
|
||||
</Heading>
|
||||
</div>
|
||||
</Responsive>
|
||||
|
||||
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
|
||||
<h1 className={[_s.default, _s.mr15].join(' ')}>
|
||||
<Button to='/' isText title='Gab' aria-label='Gab' className={[_s.default, _s.justifyContentCenter, _s.noSelect, _s.noUnderline, _s.height53PX, _s.cursorPointer, _s.px10, _s.mr15].join(' ')}>
|
||||
<Icon id='gab-logo' className={_s.fillWhite} />
|
||||
</Button>
|
||||
</h1>
|
||||
</Responsive>
|
||||
|
||||
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
|
||||
<div className={[_s.default, _s.width340PX].join(' ')}>
|
||||
@@ -64,25 +85,34 @@ class NavigationBar extends ImmutablePureComponent {
|
||||
|
||||
<div className={[_s.default, _s.mlAuto].join(' ')}>
|
||||
<div className={[_s.default, _s.height53PX, _s.pl15, _s.flexRow, _s.alignItemsCenter, _s.justifyContentSpaceBetween].join(' ')}>
|
||||
<NavigationBarButton title='Home' icon='home' to='/home' />
|
||||
|
||||
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
|
||||
<div>
|
||||
{ /** actions */}
|
||||
</div>
|
||||
</Responsive>
|
||||
|
||||
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
|
||||
<NavigationBarButton title='Home' icon='home' to='/home' />
|
||||
|
||||
<NavigationBarButtonDivider />
|
||||
|
||||
<NavigationBarButton attrTitle='Notifications' icon='notifications' to='/notifications' />
|
||||
<NavigationBarButton attrTitle='Settings' icon='cog' href='/settings/preferences' />
|
||||
|
||||
<NavigationBarButtonDivider />
|
||||
|
||||
<NavigationBarButtonDivider />
|
||||
|
||||
<NavigationBarButton attrTitle='Notifications' icon='notifications' to='/notifications' />
|
||||
<NavigationBarButton attrTitle='Settings' icon='cog' href='/settings/preferences' />
|
||||
|
||||
<NavigationBarButtonDivider />
|
||||
|
||||
{
|
||||
!!account &&
|
||||
<button
|
||||
title={account.get('display_name')}
|
||||
onClick={this.handleProfileClick}
|
||||
className={[_s.height53PX, _s.bgTransparent, _s.outlineNone, _s.cursorPointer, _s.default, _s.justifyContentCenter, _s.ml15].join(' ')}
|
||||
>
|
||||
<Avatar account={account} size={32} noHover />
|
||||
</button>
|
||||
}
|
||||
{
|
||||
!!account &&
|
||||
<button
|
||||
title={account.get('display_name')}
|
||||
onClick={this.handleProfileClick}
|
||||
className={[_s.height53PX, _s.bgTransparent, _s.outlineNone, _s.cursorPointer, _s.default, _s.justifyContentCenter, _s.ml15].join(' ')}
|
||||
>
|
||||
<Avatar account={account} size={32} noHover />
|
||||
</button>
|
||||
}
|
||||
</Responsive>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import classNames from 'classnames/bind'
|
||||
import {
|
||||
CX,
|
||||
BREAKPOINT_SMALL
|
||||
} from '../constants'
|
||||
import Button from './button'
|
||||
import Icon from './icon'
|
||||
import Image from './image'
|
||||
|
||||
const cx = classNames.bind(_s)
|
||||
import Responsive from '../features/ui/util/responsive_component'
|
||||
|
||||
export default class SidebarSectionItem extends PureComponent {
|
||||
|
||||
@@ -57,7 +59,7 @@ export default class SidebarSectionItem extends PureComponent {
|
||||
const shouldShowActive = hovering || active || currentPathname === to || currentPathname === href
|
||||
const isNotifications = to === '/notifications'
|
||||
|
||||
const containerClasses = cx({
|
||||
const containerClasses = CX({
|
||||
default: 1,
|
||||
maxWidth100PC: 1,
|
||||
width100PC: 1,
|
||||
@@ -74,7 +76,7 @@ export default class SidebarSectionItem extends PureComponent {
|
||||
bgPrimary: shouldShowActive,
|
||||
})
|
||||
|
||||
const textClasses = cx({
|
||||
const textClasses = CX({
|
||||
default: 1,
|
||||
fontWeightNormal: 1,
|
||||
fs15PX: 1,
|
||||
@@ -83,11 +85,11 @@ export default class SidebarSectionItem extends PureComponent {
|
||||
colorPrimary: 1,
|
||||
})
|
||||
|
||||
const iconClasses = cx({
|
||||
const iconClasses = CX({
|
||||
fillPrimary: 1,
|
||||
})
|
||||
|
||||
const countClasses = cx({
|
||||
const countClasses = CX({
|
||||
default: 1,
|
||||
text: 1,
|
||||
mlAuto: 1,
|
||||
@@ -130,9 +132,11 @@ export default class SidebarSectionItem extends PureComponent {
|
||||
/>
|
||||
}
|
||||
|
||||
<div className={[_s.default, _s.flexNormal, _s.px10, _s.textOverflowEllipsis, _s.overflowWrapBreakWord, _s.flexRow, _s.width100PC].join(' ')}>
|
||||
<span className={textClasses}>{title}</span>
|
||||
</div>
|
||||
<Responsive min={BREAKPOINT_SMALL}>
|
||||
<div className={[_s.default, _s.flexNormal, _s.px10, _s.textOverflowEllipsis, _s.overflowWrapBreakWord, _s.flexRow, _s.width100PC].join(' ')}>
|
||||
<span className={textClasses}>{title}</span>
|
||||
</div>
|
||||
</Responsive>
|
||||
|
||||
{
|
||||
count > 0 &&
|
||||
|
||||
@@ -4,7 +4,10 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { HotKeys } from 'react-hotkeys'
|
||||
import classNames from 'classnames/bind'
|
||||
import { me, displayMedia, compactMode } from '../initial_state'
|
||||
import scheduleIdleTask from '../utils/schedule_idle_task'
|
||||
import ComposeFormContainer from '../features/compose/containers/compose_form_container'
|
||||
import ResponsiveClassesComponent from '../features/ui/util/responsive_classes_component'
|
||||
import ColumnIndicator from './column_indicator'
|
||||
import StatusContent from './status_content'
|
||||
import StatusPrepend from './status_prepend'
|
||||
import StatusActionBar from './status_action_bar'
|
||||
@@ -133,12 +136,14 @@ class Status extends ImmutablePureComponent {
|
||||
if (nextProps.isChild) return null
|
||||
|
||||
if (!nextProps.isHidden && (nextProps.isIntersecting || !nextProps.commentsLimited) && !prevState.loadedComments) {
|
||||
console.log("111111111111111111111111111111111111", nextProps.isHidden, nextProps.isIntersecting)
|
||||
return {
|
||||
loadedComments: true
|
||||
}
|
||||
}
|
||||
|
||||
if (nextProps.status && nextProps.status.get('id') !== prevState.statusId) {
|
||||
console.log("2222222222222222222222222222222222222")
|
||||
return {
|
||||
loadedComments: false, //reset
|
||||
showMedia: defaultMediaVisibility(nextProps.status),
|
||||
@@ -154,12 +159,14 @@ class Status extends ImmutablePureComponent {
|
||||
// timeline lazy loading comments
|
||||
if (!prevState.loadedComments && this.state.loadedComments && this.props.status && !this.props.isChild) {
|
||||
const commentCount = this.props.status.get('replies_count')
|
||||
if (commentCount > 0 && !this.props.isComment) {
|
||||
this.props.onFetchComments(this.props.status.get('id'))
|
||||
// this._measureHeight(prevState.height !== this.state.height)
|
||||
} else {
|
||||
console.log("before fetch:", this.props.status)
|
||||
if (this.props.isComment) {
|
||||
this.props.onFetchContext(this.props.status.get('id'))
|
||||
this._measureHeight(prevState.height !== this.state.height)
|
||||
} else {
|
||||
if (commentCount > 0) {
|
||||
this._measureHeight(prevState.height !== this.state.height)
|
||||
this.props.onFetchComments(this.props.status.get('id'))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,6 +177,7 @@ class Status extends ImmutablePureComponent {
|
||||
|
||||
if (snapshot !== null && this.props.updateScrollBottom) {
|
||||
if (this.node && this.node.offsetTop < snapshot.top) {
|
||||
console.log("updateScrollBottom")
|
||||
this.props.updateScrollBottom(snapshot.height - snapshot.top)
|
||||
}
|
||||
}
|
||||
@@ -332,15 +340,15 @@ class Status extends ImmutablePureComponent {
|
||||
return status
|
||||
}
|
||||
|
||||
_measureHeight (heightJustChanged) {
|
||||
_measureHeight(heightJustChanged) {
|
||||
try {
|
||||
scheduleIdleTask(() => this.node && this.setState({ height: Math.ceil(this.node.scrollHeight) + 1 }))
|
||||
|
||||
|
||||
if (heightJustChanged) {
|
||||
this.props.onHeightChange()
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
@@ -360,12 +368,18 @@ class Status extends ImmutablePureComponent {
|
||||
commentsLimited,
|
||||
ancestorStatus,
|
||||
isComment,
|
||||
contextType,
|
||||
} = this.props
|
||||
|
||||
// const { height } = this.state
|
||||
|
||||
let { status } = this.props
|
||||
|
||||
if (!status) return null
|
||||
|
||||
if (isComment && !ancestorStatus && !isChild) {
|
||||
return <ColumnIndicator type='loading' />
|
||||
}
|
||||
|
||||
let reblogContent, rebloggedByText = null
|
||||
|
||||
if (ancestorStatus) {
|
||||
@@ -394,35 +408,27 @@ class Status extends ImmutablePureComponent {
|
||||
toggleSensitive: this.handleHotkeyToggleSensitive,
|
||||
}
|
||||
|
||||
if (isHidden) {
|
||||
return (
|
||||
<HotKeys handlers={handlers}>
|
||||
<div ref={this.handleRef} className={classNames({ focusable: !this.props.muted })} tabIndex='0'>
|
||||
{status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])}
|
||||
{status.get('content')}
|
||||
</div>
|
||||
</HotKeys>
|
||||
)
|
||||
}
|
||||
|
||||
if (status.get('filtered') || status.getIn(['reblog', 'filtered'])) {
|
||||
return null
|
||||
}
|
||||
const parentClasses = cx({
|
||||
pb15: !isChild && !compactMode,
|
||||
})
|
||||
|
||||
const containerClasses = cx({
|
||||
default: 1,
|
||||
pb15: isFeatured,
|
||||
radiusSmall: !isChild && !compactMode,
|
||||
bgPrimary: !isChild,
|
||||
boxShadowBlock: !isChild && !compactMode,
|
||||
outlineNone: 1,
|
||||
mb15: !isChild && !compactMode,
|
||||
borderRight1PX: !isChild && compactMode,
|
||||
borderLeft1PX: !isChild && compactMode,
|
||||
borderBottom1PX: !isChild && compactMode,
|
||||
borderColorSecondary: !isChild && compactMode,
|
||||
})
|
||||
|
||||
const containerClassesXS = cx({
|
||||
bgPrimary: !isChild,
|
||||
boxShadowBlock: !isChild && !compactMode,
|
||||
borderBottom1PX: !isChild && compactMode,
|
||||
borderColorSecondary: !isChild && compactMode,
|
||||
})
|
||||
|
||||
const innerContainerClasses = cx({
|
||||
default: 1,
|
||||
overflowHidden: 1,
|
||||
@@ -435,95 +441,117 @@ class Status extends ImmutablePureComponent {
|
||||
bgSubtle_onHover: isChild,
|
||||
})
|
||||
|
||||
if (status.get('filtered') || status.getIn(['reblog', 'filtered'])) {
|
||||
return null
|
||||
}
|
||||
|
||||
if (isHidden) {
|
||||
return (
|
||||
<HotKeys handlers={handlers}>
|
||||
<div ref={this.handleRef} className={parentClasses} tabIndex='0'>
|
||||
{status.getIn(['account', 'display_name']) || status.getIn(['account', 'username'])}
|
||||
{status.get('content')}
|
||||
</div>
|
||||
</HotKeys>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<HotKeys handlers={handlers}>
|
||||
<div
|
||||
className={containerClasses}
|
||||
tabIndex={this.props.isMuted ? null : 0}
|
||||
data-featured={isFeatured ? 'true' : null}
|
||||
aria-label={textForScreenReader(intl, status, rebloggedByText)}
|
||||
ref={this.handleRef}
|
||||
onClick={isChild ? this.handleClick : undefined}
|
||||
>
|
||||
<div className={innerContainerClasses}>
|
||||
<div className={parentClasses}>
|
||||
<ResponsiveClassesComponent
|
||||
classNames={containerClasses}
|
||||
classNamesXS={containerClassesXS}
|
||||
>
|
||||
<div
|
||||
className={[_s.default, _s.outlineNone].join(' ')}
|
||||
tabIndex={this.props.isMuted ? null : 0}
|
||||
data-featured={isFeatured ? 'true' : null}
|
||||
aria-label={textForScreenReader(intl, status, rebloggedByText)}
|
||||
ref={this.handleRef}
|
||||
onClick={isChild ? this.handleClick : undefined}
|
||||
>
|
||||
<div className={innerContainerClasses}>
|
||||
|
||||
<div data-id={status.get('id')}>
|
||||
<div data-id={status.get('id')}>
|
||||
|
||||
<StatusPrepend
|
||||
status={this.props.status}
|
||||
isPromoted={isPromoted}
|
||||
isFeatured={isFeatured}
|
||||
isComment={isComment}
|
||||
/>
|
||||
<StatusPrepend
|
||||
status={this.props.status}
|
||||
isPromoted={isPromoted}
|
||||
isFeatured={isFeatured}
|
||||
isComment={isComment && !isChild}
|
||||
/>
|
||||
|
||||
<StatusHeader status={status} reduced={isChild} />
|
||||
<StatusHeader status={status} reduced={isChild} />
|
||||
|
||||
<div className={_s.default}>
|
||||
<StatusContent
|
||||
status={status}
|
||||
reblogContent={reblogContent}
|
||||
onClick={this.handleClick}
|
||||
expanded={!status.get('hidden')}
|
||||
onExpandedToggle={this.handleExpandedToggle}
|
||||
collapsable
|
||||
/>
|
||||
<div className={_s.default}>
|
||||
<StatusContent
|
||||
status={status}
|
||||
reblogContent={reblogContent}
|
||||
onClick={this.handleClick}
|
||||
expanded={!status.get('hidden')}
|
||||
onExpandedToggle={this.handleExpandedToggle}
|
||||
collapsable={contextType !== 'feature'}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<StatusMedia
|
||||
isChild={isChild}
|
||||
status={status}
|
||||
onOpenMedia={this.props.onOpenMedia}
|
||||
cacheWidth={this.props.cacheMediaWidth}
|
||||
defaultWidth={this.props.cachedMediaWidth}
|
||||
visible={this.state.showMedia}
|
||||
onToggleVisibility={this.handleToggleMediaVisibility}
|
||||
width={this.props.cachedMediaWidth}
|
||||
onOpenVideo={this.handleOpenVideo}
|
||||
/>
|
||||
|
||||
{
|
||||
!!status.get('quote') && !isChild &&
|
||||
<div className={[_s.default, _s.mt10, _s.px10].join(' ')}>
|
||||
<Status status={status.get('quoted_status')} isChild intl={intl} />
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
!isChild &&
|
||||
<StatusActionBar
|
||||
status={status}
|
||||
onFavorite={this.props.onFavorite}
|
||||
onReply={this.props.onReply}
|
||||
onRepost={this.props.onRepost}
|
||||
onShare={this.props.onShare}
|
||||
onOpenLikes={this.props.onOpenLikes}
|
||||
onOpenReposts={this.props.onOpenReposts}
|
||||
/>
|
||||
}
|
||||
|
||||
{
|
||||
!isChild && !compactMode && !!me &&
|
||||
<div className={[_s.default, _s.borderTop1PX, _s.borderColorSecondary, _s.pt10, _s.px15, _s.mb10].join(' ')}>
|
||||
<ComposeFormContainer replyToId={status.get('id')} shouldCondense />
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
descendantsIds && !compactMode && !isChild && descendantsIds.size > 0 &&
|
||||
<div className={[_s.default, _s.mr10, _s.ml10, _s.mb10, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')} />
|
||||
}
|
||||
|
||||
{
|
||||
descendantsIds && !compactMode && !isChild && descendantsIds.size > 0 &&
|
||||
<CommentList
|
||||
ancestorAccountId={status.getIn(['account', 'id'])}
|
||||
commentsLimited={commentsLimited}
|
||||
descendants={descendantsIds}
|
||||
onViewComments={this.handleClick}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<StatusMedia
|
||||
isChild={isChild}
|
||||
status={status}
|
||||
onOpenMedia={this.props.onOpenMedia}
|
||||
cacheWidth={this.props.cacheMediaWidth}
|
||||
defaultWidth={this.props.cachedMediaWidth}
|
||||
visible={this.state.showMedia}
|
||||
onToggleVisibility={this.handleToggleMediaVisibility}
|
||||
width={this.props.cachedMediaWidth}
|
||||
onOpenVideo={this.handleOpenVideo}
|
||||
/>
|
||||
|
||||
{
|
||||
!!status.get('quote') && !isChild &&
|
||||
<div className={[_s.default, _s.mt10, _s.px10].join(' ')}>
|
||||
<Status status={status.get('quoted_status')} isChild intl={intl} />
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
!isChild &&
|
||||
<StatusActionBar
|
||||
status={status}
|
||||
onFavorite={this.props.onFavorite}
|
||||
onReply={this.props.onReply}
|
||||
onRepost={this.props.onRepost}
|
||||
onShare={this.props.onShare}
|
||||
onOpenLikes={this.props.onOpenLikes}
|
||||
onOpenReposts={this.props.onOpenReposts}
|
||||
/>
|
||||
}
|
||||
|
||||
{
|
||||
!isChild && !compactMode && !!me &&
|
||||
<div className={[_s.default, _s.borderTop1PX, _s.borderColorSecondary, _s.pt10, _s.px15, _s.mb10].join(' ')}>
|
||||
<ComposeFormContainer replyToId={status.get('id')} shouldCondense />
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
descendantsIds && !compactMode && !isChild && descendantsIds.size > 0 &&
|
||||
<div className={[_s.default, _s.mr10, _s.ml10, _s.mb10, _s.borderColorSecondary, _s.borderBottom1PX].join(' ')}/>
|
||||
}
|
||||
|
||||
{
|
||||
descendantsIds && !compactMode && !isChild && descendantsIds.size > 0 &&
|
||||
<CommentList
|
||||
ancestorAccountId={status.getIn(['account', 'id'])}
|
||||
commentsLimited={commentsLimited}
|
||||
descendants={descendantsIds}
|
||||
onViewComments={this.handleClick}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
</ResponsiveClassesComponent>
|
||||
</div>
|
||||
</HotKeys>
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import punycode from 'punycode'
|
||||
import { DEFAULT_REL } from '../constants'
|
||||
import ResponsiveClassesComponent from '../features/ui/util/responsive_classes_component'
|
||||
import Icon from './icon'
|
||||
|
||||
const IDNA_PREFIX = 'xn--'
|
||||
@@ -67,7 +68,7 @@ export default class Card extends ImmutablePureComponent {
|
||||
embedded: false,
|
||||
}
|
||||
|
||||
componentWillReceiveProps (nextProps) {
|
||||
componentWillReceiveProps(nextProps) {
|
||||
if (!Immutable.is(this.props.card, nextProps.card)) {
|
||||
this.setState({ embedded: false })
|
||||
}
|
||||
@@ -111,12 +112,12 @@ export default class Card extends ImmutablePureComponent {
|
||||
}
|
||||
}
|
||||
|
||||
renderVideo () {
|
||||
const { card } = this.props
|
||||
const content = { __html: addAutoPlay(card.get('html')) }
|
||||
renderVideo() {
|
||||
const { card } = this.props
|
||||
const content = { __html: addAutoPlay(card.get('html')) }
|
||||
const { width } = this.state
|
||||
const ratio = card.get('width') / card.get('height')
|
||||
const height = width / ratio
|
||||
const ratio = card.get('width') / card.get('height')
|
||||
const height = width / ratio
|
||||
|
||||
return (
|
||||
<div
|
||||
@@ -127,7 +128,7 @@ export default class Card extends ImmutablePureComponent {
|
||||
)
|
||||
}
|
||||
|
||||
render () {
|
||||
render() {
|
||||
const { card } = this.props
|
||||
const { width, embedded } = this.state
|
||||
|
||||
@@ -175,7 +176,14 @@ export default class Card extends ImmutablePureComponent {
|
||||
const thumbnail = interactive ?
|
||||
<img alt={''} src={cardImg} className={[_s.default, _s.objectFitCover, _s.posAbs, _s.width100PC, _s.height100PC, _s.top0, _s.right0, _s.bottom0, _s.left0].join(' ')} />
|
||||
:
|
||||
<img alt={''} src={cardImg} className={[_s.default, _s.objectFitCover, _s.width330PX, _s.height220PX].join(' ')} />
|
||||
(
|
||||
<ResponsiveClassesComponent
|
||||
classNames={[_s.default, _s.height220PX, _s.width330PX].join(' ')}
|
||||
classNamesSmall={[_s.default, _s.height260PX, _s.width100PC].join(' ')}
|
||||
>
|
||||
<img alt={''} src={cardImg} className={[_s.default, _s.objectFitCover, _s.width100PC, _s.height100PC].join(' ')} />
|
||||
</ResponsiveClassesComponent>
|
||||
)
|
||||
|
||||
if (interactive) {
|
||||
if (embedded) {
|
||||
@@ -193,9 +201,9 @@ export default class Card extends ImmutablePureComponent {
|
||||
<div className={[_s.default, _s.overflowHidden, _s.width100PC, _s.borderColorSecondary, _s.border1PX, _s.radiusSmall].join(' ')}>
|
||||
<div className={[_s.default, _s.width100PC].join(' ')}>
|
||||
<div className={[_s.default, _s.width100PC, _s.pt5625PC].join(' ')}>
|
||||
{ !!embed && embed}
|
||||
{ !embed && thumbnail}
|
||||
{ !embed &&
|
||||
{!!embed && embed}
|
||||
{!embed && thumbnail}
|
||||
{!embed &&
|
||||
<div className={[_s.default, _s.posAbs, _s.top0, _s.right0, _s.left0, _s.bottom0, _s.alignItemsCenter, _s.justifyContentCenter].join(' ')}>
|
||||
<button
|
||||
className={[_s.default, _s.cursorPointer, _s.bgBlackOpaque, _s.radiusSmall, _s.py15, _s.px15].join(' ')}
|
||||
@@ -229,12 +237,17 @@ export default class Card extends ImmutablePureComponent {
|
||||
<div className={[_s.default, _s.width100PC, _s.px10].join(' ')}>
|
||||
<a
|
||||
href={card.get('url')}
|
||||
className={[_s.default, _s.cursorPointer, _s.flexRow, _s.overflowHidden, _s.noUnderline, _s.width100PC, _s.bgSubtle_onHover, _s.borderColorSecondary, _s.border1PX, _s.radiusSmall].join(' ')}
|
||||
rel={DEFAULT_REL}
|
||||
ref={this.setRef}
|
||||
className={[_s.default, _s.cursorPointer, _s.overflowHidden, _s.noUnderline, _s.width100PC, _s.bgSubtle_onHover, _s.borderColorSecondary, _s.border1PX, _s.radiusSmall].join(' ')}
|
||||
>
|
||||
{embed}
|
||||
{description}
|
||||
<ResponsiveClassesComponent
|
||||
classNames={[_s.default, _s.flexRow, _s.width100PC].join(' ')}
|
||||
classNamesSmall={!cardImg ? undefined : [_s.default, _s.width100PC].join(' ')}
|
||||
>
|
||||
{embed}
|
||||
{description}
|
||||
</ResponsiveClassesComponent>
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -169,7 +169,12 @@ class StatusContent extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { status, intl, isComment } = this.props
|
||||
const {
|
||||
collapsable,
|
||||
intl,
|
||||
isComment,
|
||||
status,
|
||||
} = this.props
|
||||
const { collapsed } = this.state
|
||||
|
||||
if (status.get('content').length === 0) return null
|
||||
@@ -302,7 +307,7 @@ class StatusContent extends ImmutablePureComponent {
|
||||
onMouseUp={this.handleMouseUp}
|
||||
/>
|
||||
{
|
||||
this.state.collapsed &&
|
||||
this.state.collapsed && collapsable &&
|
||||
<Button
|
||||
isText
|
||||
underlineOnHover
|
||||
|
||||
@@ -69,6 +69,7 @@ export default class StatusMedia extends ImmutablePureComponent {
|
||||
{Component => (
|
||||
<Component
|
||||
inline
|
||||
isComment={isComment}
|
||||
preview={video.get('preview_url')}
|
||||
blurhash={video.get('blurhash')}
|
||||
src={video.get('url')}
|
||||
@@ -90,6 +91,7 @@ export default class StatusMedia extends ImmutablePureComponent {
|
||||
<Bundle fetchComponent={MediaGallery} loading={this.renderLoadingMedia}>
|
||||
{Component => (
|
||||
<Component
|
||||
isComment={isComment}
|
||||
reduced={isChild}
|
||||
media={status.get('media_attachments')}
|
||||
sensitive={status.get('sensitive')}
|
||||
@@ -110,6 +112,7 @@ export default class StatusMedia extends ImmutablePureComponent {
|
||||
onOpenMedia={onOpenMedia}
|
||||
cacheWidth={cacheWidth}
|
||||
defaultWidth={defaultWidth}
|
||||
isComment={isComment}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { me } from '../initial_state'
|
||||
import ComposeFormContainer from '../features/compose/containers/compose_form_container'
|
||||
import ResponsiveClassesComponent from '../features/ui/util/responsive_classes_component'
|
||||
import Avatar from './avatar'
|
||||
import Block from './block'
|
||||
import Heading from './heading'
|
||||
@@ -52,7 +53,10 @@ class TimelineComposeBlock extends ImmutablePureComponent {
|
||||
|
||||
return (
|
||||
<section className={[_s.default, _s.mb15].join(' ')}>
|
||||
<Block>
|
||||
<ResponsiveClassesComponent
|
||||
classNames={[_s.default, _s.boxShadowBlock, _s.bgPrimary, _s.overflowHidden, _s.radiusSmall].join(' ')}
|
||||
classNamesXS={[_s.default, _s.boxShadowBlock, _s.bgPrimary, _s.overflowHidden].join(' ')}
|
||||
>
|
||||
<div className={[_s.default, _s.bgSubtle, _s.borderTop1PX, _s.borderBottom1PX, _s.borderColorSecondary, _s.px15, _s.py2, _s.alignItemsCenter, _s.flexRow].join(' ')}>
|
||||
<div className={_s.mr10}>
|
||||
<Avatar account={account} size={20} noHover />
|
||||
@@ -62,7 +66,7 @@ class TimelineComposeBlock extends ImmutablePureComponent {
|
||||
</Heading>
|
||||
</div>
|
||||
<ComposeFormContainer {...rest} />
|
||||
</Block>
|
||||
</ResponsiveClassesComponent>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user