This commit is contained in:
mgabdev 2020-05-06 00:33:54 -04:00
parent 01bb440385
commit e1e26afe11
23 changed files with 501 additions and 292 deletions

View File

@ -40,7 +40,6 @@ export const fetchGifResults = (expand) => {
const pos = 0 //expand ? getState().getIn(['tenor', 'results'], []).length
api(getState).get('/api/v1/gifs/search', { search, pos }).then((response) => {
console.log("response.data:", response.data)
dispatch(fetchGifResultsSuccess(response.data))
}).catch(function (error) {
dispatch(fetchGifResultsFail(error))

View File

@ -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}

View File

@ -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'

View File

@ -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>
);
}
}

View 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>
)
}
}

View File

@ -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>
)
}

View File

@ -253,6 +253,7 @@ class MediaGallery extends PureComponent {
visible: PropTypes.bool,
onToggleVisibility: PropTypes.func,
reduced: PropTypes.bool,
isComment: PropTypes.bool,
};
static defaultProps = {

View File

@ -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>

View File

@ -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 &&

View File

@ -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>
)

View File

@ -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>
)

View File

@ -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

View File

@ -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}
/>
)
}

View File

@ -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>
)
}

View File

@ -80,11 +80,13 @@ const makeMapStateToProps = () => {
username: username,
})
let fetchedContext = false
let descendantsIds = ImmutableList()
let ancestorStatus
let fetchedContext = false
if (status && status.get('in_reply_to_account_id')) {
//
if (status && status.get('in_reply_to_account_id') && !props.isChild) {
fetchedContext = true
let inReplyTos = state.getIn(['contexts', 'inReplyTos'])
@ -100,12 +102,16 @@ const makeMapStateToProps = () => {
})
const ancestorStatusId = ancestorsIds.get(0)
ancestorStatus = getStatus(state, {
id: ancestorStatusId,
})
descendantsIds = getDescendants(state, ancestorStatus, statusId)
if (ancestorStatusId !== statusId) {
ancestorStatus = getStatus(state, {
id: ancestorStatusId,
})
descendantsIds = getDescendants(state, ancestorStatus, statusId)
}
}
//
if (status && status.get('replies_count') > 0 && !fetchedContext) {
descendantsIds = getDescendants(state, status)
}

View File

@ -277,8 +277,6 @@ class ComposeForm extends ImmutablePureComponent {
displayNone: length(this.props.text) === 0 || anyMedia,
})
console.log("reduxReplyToId:", reduxReplyToId, shouldCondense, isModalOpen)
return (
<div className={parentContainerClasses}>
<div className={[_s.default, _s.flexRow, _s.width100PC].join(' ')}>

View File

@ -52,7 +52,6 @@ const mapDispatchToProps = (dispatch) => ({
dispatch(changeGroupDescription(value))
},
onCoverImageChange: (imageData) => {
console.log("imageData:", imageData)
dispatch(changeGroupCoverImage(imageData))
},
onResetEditor: () => {

View File

@ -0,0 +1,76 @@
import {
BREAKPOINT_EXTRA_LARGE,
BREAKPOINT_LARGE,
BREAKPOINT_MEDIUM,
BREAKPOINT_SMALL,
BREAKPOINT_EXTRA_SMALL,
} from '../../../constants'
import { getWindowDimension } from '../../../utils/is_mobile'
const initialState = getWindowDimension()
export default class ResponsiveClassesComponent extends PureComponent {
static propTypes = {
classNames: PropTypes.string,
classNamesXL: PropTypes.string,
classNamesLarge: PropTypes.string,
classNamesMedium: PropTypes.string,
classNamesSmall: PropTypes.string,
classNamesXS: PropTypes.string,
}
state = {
width: initialState.width,
}
componentDidMount() {
this.handleResize()
window.addEventListener('resize', this.handleResize, false)
}
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize, false)
}
handleResize = () => {
const { width } = getWindowDimension()
this.setState({ width })
}
render() {
const {
children,
classNames,
classNamesXL,
classNamesLarge,
classNamesMedium,
classNamesSmall,
classNamesXS,
} = this.props
const { width } = this.state
let classes;
if (width >= BREAKPOINT_EXTRA_LARGE) {
classes = classNamesXL || classNames
} else if (width < BREAKPOINT_EXTRA_LARGE && width >= BREAKPOINT_LARGE) {
classes = classNames //default
} else if (width < BREAKPOINT_LARGE && width >= BREAKPOINT_MEDIUM) {
classes = classNamesLarge || classNames
} else if (width < BREAKPOINT_MEDIUM && width >= BREAKPOINT_SMALL) {
classes = classNamesMedium || classNamesLarge || classNames
} else if (width < BREAKPOINT_SMALL && width >= BREAKPOINT_EXTRA_SMALL) {
classes = classNamesSmall || classNamesMedium || classNamesLarge || classNames
} else {
classes = classNamesXS || classNamesSmall || classNamesMedium || classNamesLarge || classNames
}
return (
<div className={classes}>
{children}
</div>
)
}
}

View File

@ -3,6 +3,7 @@ import { getWindowDimension } from '../../../utils/is_mobile'
const initialState = getWindowDimension()
export default class Responsive extends PureComponent {
static propTypes = {
min: PropTypes.number,
max: PropTypes.number,
@ -18,6 +19,7 @@ export default class Responsive extends PureComponent {
}
componentDidMount() {
this.handleResize()
window.addEventListener('resize', this.handleResize, false)
}
@ -43,4 +45,5 @@ export default class Responsive extends PureComponent {
return shouldRender ? children : null
}
}

View File

@ -2,10 +2,10 @@ import Sticky from 'react-stickynode'
import Sidebar from '../components/sidebar'
import { BREAKPOINT_EXTRA_SMALL } from '../constants'
import NavigationBar from '../components/navigation_bar'
// : todo :
// import Footer from '../components/footer'
import FooterBar from '../components/footer_bar'
import FloatingActionButton from '../components/floating_action_button'
import Responsive from '../features/ui/util/responsive_component'
import ResponsiveClassesComponent from '../features/ui/util/responsive_classes_component'
export default class Layout extends PureComponent {
@ -55,48 +55,57 @@ export default class Layout extends PureComponent {
/>
</Responsive>
}
<ResponsiveClassesComponent
classNames={[_s.default, _s.flexShrink1, _s.flexGrow1].join(' ')}
classNamesSmall={[_s.default, _s.width100PC].join(' ')}
>
<main role='main'>
<main role='main' className={[_s.default, _s.flexShrink1, _s.flexGrow1].join(' ')}>
<div className={[_s.default, _s.width1015PX, _s.flexRow, _s.justifyContentEnd, _s.py15].join(' ')}>
<div className={[_s.default, _s.width1015PX, _s.flexRow, _s.justifyContentEnd, _s.py15].join(' ')}>
{
noRightSidebar && children
}
{
noRightSidebar && children
}
{
!noRightSidebar &&
<div className={[_s.default, _s.width645PX, _s.z1].join(' ')}>
<div className={_s.default}>
{children}
{
!noRightSidebar &&
<div className={[_s.default, _s.width645PX, _s.z1].join(' ')}>
<div className={_s.default}>
{children}
</div>
</div>
</div>
}
}
{
!noRightSidebar &&
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
<div className={[_s.default, _s.width340PX, _s.ml15].join(' ')}>
<Sticky top={73} enabled>
<div className={[_s.default, _s.width340PX].join(' ')}>
{layout}
</div>
</Sticky>
</div>
</Responsive>
}
{
!noRightSidebar &&
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
<div className={[_s.default, _s.width340PX, _s.ml15].join(' ')}>
<Sticky top={73} enabled>
<div className={[_s.default, _s.width340PX].join(' ')}>
{layout}
</div>
</Sticky>
</div>
</Responsive>
}
{
!noComposeButton &&
<Responsive max={BREAKPOINT_EXTRA_SMALL}>
<FloatingActionButton />
</Responsive>
}
{
!noComposeButton &&
<Responsive max={BREAKPOINT_EXTRA_SMALL}>
<FloatingActionButton />
</Responsive>
}
</div>
</div>
</main>
</main>
</ResponsiveClassesComponent>
</div>
<Responsive max={BREAKPOINT_EXTRA_SMALL}>
<FooterBar title={title} />
</Responsive>
</div>
)
}

View File

@ -78,16 +78,13 @@ export const makeGetStatus = () => {
],
(state, statusBase, quotedStatus, statusRepost, accountBase, accountQuoted, accountRepost, username, filters) => {
console.log("statusBase:", statusBase)
if (!statusBase) {
console.log("return null 1")
return null
}
const accountUsername = accountBase.get('acct');
//Must be owner of status if username exists
if (accountUsername !== username && username !== undefined) {
console.log("return null 2")
return null
}

View File

@ -1,12 +1,13 @@
'use strict'
import detectPassiveEvents from 'detect-passive-events'
const BREAKPOINT_EXTRA_LARGE = 1480
const BREAKPOINT_LARGE = 1280
const BREAKPOINT_MEDIUM = 1160
const BREAKPOINT_SMALL = 1080
const BREAKPOINT_EXTRA_SMALL = 992
import {
BREAKPOINT_EXTRA_LARGE,
BREAKPOINT_LARGE,
BREAKPOINT_MEDIUM,
BREAKPOINT_SMALL,
BREAKPOINT_EXTRA_SMALL,
} from '../constants'
const LAYOUT_BREAKPOINT = 630
@ -34,20 +35,6 @@ export function breakpointExtraSmall(width) {
return width < BREAKPOINT_EXTRA_SMALL
}
export function getScreenBreakpoint(width) {
if (width > BREAKPOINT_EXTRA_LARGE) {
return 'BREAKPOINT_EXTRA_LARGE'
} else if (width > BREAKPOINT_MEDIUM && width < BREAKPOINT_LARGE) {
return 'BREAKPOINT_LARGE'
} else if (width > BREAKPOINT_SMALL && width < BREAKPOINT_MEDIUM) {
return 'BREAKPOINT_MEDIUM'
} else if (width > BREAKPOINT_EXTRA_SMALL && width < BREAKPOINT_SMALL) {
return 'BREAKPOINT_SMALL'
} else {
return 'BREAKPOINT_EXTRA_SMALL'
}
}
export const getWindowDimension = () => {
const width = window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth
const height = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight

View File

@ -228,6 +228,7 @@ body {
.alignItemsCenter { align-items: center; }
.justifyContentSpaceBetween { justify-content: space-between; }
.justifyContentSpaceAround { justify-content: space-around; }
.justifyContentCenter { justify-content: center; }
.justifyContentEnd { justify-content: flex-end; }
@ -390,6 +391,7 @@ body {
.top50PC { top: 50%; }
.bottom0 { bottom: 0; }
.bottom50PX { bottom: 50px; }
.bottomAuto { bottom: auto; }
.left0 { left: 0px; }
@ -504,6 +506,10 @@ body {
.width240PX {
width: 230px;
}
.width1255PX {
width: 1140px;
}
}
@media (min-width: 1080px) and (max-width: 1160px) {
@ -522,6 +528,10 @@ body {
.width240PX {
width: 210px;
}
.width1255PX {
width: 1060px;
}
}
@media (min-width: 992px) and (max-width: 1080px) {
@ -540,6 +550,10 @@ body {
.width240PX {
width: 100px;
}
.width1255PX {
width: 950px;
}
}
@media (min-width: 0px) and (max-width: 992px) {
@ -562,6 +576,10 @@ body {
.width240PX {
width: 0px;
}
.width1255PX {
width: 100%;
}
}
.textAlignLeft { text-align: left; }