This commit is contained in:
mgabdev
2020-05-14 02:03:22 -04:00
parent ef880dec76
commit 4acc21944c
26 changed files with 452 additions and 69 deletions

View File

@@ -60,7 +60,7 @@ class CommentHeader extends ImmutablePureComponent {
return (
<div className={[_s.default, _s.alignItemsStart, _s.py2, _s.maxWidth100PC, _s.flexGrow1].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.overflowHidden, _s.width100PC, _s.maxWidth100PC, _s.alignItemsCenter].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.flexWrap, _s.overflowHidden, _s.width100PC, _s.maxWidth100PC, _s.alignItemsCenter].join(' ')}>
<NavLink
className={[_s.default, _s.flexRow, _s.alignItemsStart, _s.noUnderline].join(' ')}
to={`/${status.getIn(['account', 'acct'])}`}

View File

@@ -196,6 +196,7 @@ class Composer extends PureComponent {
default: 1,
cursorText: 1,
text: 1,
colorPrimary: 1,
fs16PX: !small,
fs14PX: small,
pt15: !small,

View File

@@ -35,7 +35,7 @@ export default class LoggedOutNavigationBar extends PureComponent {
/>
<div className={[_s.default, _s.flexGrow1, _s.mr10].join(' ')}>
<Search />
<Search isInNav />
</div>
</ResponsiveClassesComponent>

View File

@@ -1,10 +1,10 @@
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { openSidebar } from '../actions/sidebar'
import { BREAKPOINT_EXTRA_SMALL } from '../constants'
import { me } from '../initial_state'
import { makeGetAccount } from '../selectors'
import Responsive from '../features/ui/util/responsive_component'
import ResponsiveClassesComponent from '../features/ui/util/responsive_classes_component'
import { CX } from '../constants'
import Avatar from './avatar'
import BackButton from './back_button'
@@ -18,8 +18,14 @@ const mapStateToProps = (state) => ({
account: makeGetAccount()(state, me),
})
const mapDispatchToProps = (dispatch) => ({
onOpenSidebar() {
dispatch(openSidebar())
}
})
export default
@connect(mapStateToProps)
@connect(mapStateToProps, mapDispatchToProps)
class NavigationBar extends ImmutablePureComponent {
static propTypes = {
@@ -28,10 +34,7 @@ class NavigationBar extends ImmutablePureComponent {
tabs: PropTypes.array,
title: PropTypes.string,
showBackBtn: PropTypes.bool,
}
handleProfileClick = () => {
onOpenSidebar: PropTypes.func.isRequired,
}
render() {
@@ -41,6 +44,7 @@ class NavigationBar extends ImmutablePureComponent {
actions,
tabs,
account,
onOpenSidebar,
} = this.props
@@ -70,7 +74,7 @@ class NavigationBar extends ImmutablePureComponent {
</h1>
<div className={[_s.default, _s.width340PX].join(' ')}>
<Search />
<Search isInNav />
</div>
</div>
@@ -109,7 +113,7 @@ class NavigationBar extends ImmutablePureComponent {
!!account && !showBackBtn &&
<button
title={account.get('display_name')}
onClick={this.handleProfileClick}
onClick={onOpenSidebar}
className={[_s.height53PX, _s.bgTransparent, _s.outlineNone, _s.cursorPointer, _s.default, _s.justifyContentCenter].join(' ')}
>
<Avatar account={account} size={32} noHover />
@@ -135,26 +139,34 @@ class NavigationBar extends ImmutablePureComponent {
</div>
<div className={[_s.default, _s.width84PX, _s.pr15].join(' ')}>
{
!!actions &&
<div className={[_s.default, _s.bgTransparent, _s.flexRow, _s.alignItemsCenter, _s.justifyContentCenter, _s.mlAuto].join(' ')}>
{
actions.map((action, i) => (
<Button
isNarrow
backgroundColor='none'
color='primary'
onClick={() => action.onClick()}
key={`action-btn-${i}`}
className={[_s.ml5, _s.height53PX, _s.justifyContentCenter, _s.px5].join(' ')}
icon={action.icon}
iconClassName={_s.fillNavigation}
iconSize='18px'
/>
))
}
</div>
}
<div className={[_s.default, _s.bgTransparent, _s.flexRow, _s.alignItemsCenter, _s.justifyContentCenter, _s.mlAuto].join(' ')}>
{
actions && actions.map((action, i) => (
<Button
isNarrow
backgroundColor='none'
color='primary'
onClick={() => action.onClick()}
key={`action-btn-${i}`}
className={[_s.ml5, _s.height53PX, _s.justifyContentCenter, _s.px5].join(' ')}
icon={action.icon}
iconClassName={_s.fillNavigation}
iconSize='18px'
/>
))
}
<Button
isNarrow
backgroundColor='none'
color='primary'
to='/search'
key={`action-btn-search`}
className={[_s.ml5, _s.height53PX, _s.justifyContentCenter, _s.px5].join(' ')}
icon='search'
iconClassName={_s.fillNavigation}
iconSize='18px'
/>
</div>
</div>
</Responsive>

View File

@@ -147,6 +147,7 @@ class Notification extends ImmutablePureComponent {
contextType='notification'
id={statusId}
isChild
isNotification
/>
</div>
}

View File

@@ -61,7 +61,7 @@ class GroupInfoPanel extends ImmutablePureComponent {
<div className={[_s.default, _s.flexRow, _s.justifyContentCenter].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter].join(' ')}>
<Icon id='group' size='14px' />
<Icon id='group' size='14px' className={_s.fillPrimary} />
<Text size='small' className={_s.ml5}>
{intl.formatMessage(messages.members)}
</Text>

View File

@@ -0,0 +1,51 @@
import { injectIntl, defineMessages } from 'react-intl'
import { URL_GAB_PRO } from '../../constants'
import PanelLayout from './panel_layout';
import Button from '../button'
import Text from '../text'
const messages = defineMessages({
title: { id: 'promo.gab_pro', defaultMessage: 'Upgrade to GabPRO' },
text: { id: 'pro_upgrade_modal.text_sm', defaultMessage: 'Please consider supporting us on our mission to defend free expression online for all people.' },
})
export default
@injectIntl
class ProPanel extends PureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
isPro: PropTypes.bool.isRequired,
}
render() {
const { intl, isPro } = this.props
// if (isPro) return null
return (
<PanelLayout
title={intl.formatMessage(messages.title)}
subtitle={intl.formatMessage(messages.text)}
>
<Button
isBlock
href={URL_GAB_PRO}
icon='arrow-up'
className={[_s.justifyContentCenter].join(' ')}
>
<Text
color='inherit'
weight='medium'
size='medium'
align='center'
className={_s.ml5}
>
{intl.formatMessage(messages.title)}
</Text>
</Button>
</PanelLayout>
)
}
}

View File

@@ -93,19 +93,19 @@ class ProfileInfoPanel extends ImmutablePureComponent {
{
isPro &&
<div className={[_s.mr5, _s.radiusSmall, _s.bgPro, _s.py2, _s.px5].join(' ')}>
<Text weight='bold' size='small' color='white' isBadge>PRO</Text>
<Text weight='bold' size='small' className={_s.colorBGPrimary} isBadge>PRO</Text>
</div>
}
{
isInvestor &&
<div className={[_s.mr5, _s.radiusSmall, _s.bgInvestor, _s.py2, _s.px5].join(' ')}>
<Text weight='bold' size='small' color='white' isBadge>INVESTOR</Text>
<Text weight='bold' size='small' className={_s.colorBGPrimary} isBadge>INVESTOR</Text>
</div>
}
{
isDonor &&
<div className={[_s.mr5, _s.radiusSmall, _s.bgDonor, _s.py2, _s.px5].join(' ')}>
<Text weight='bold' size='small' color='white' isBadge>DONOR</Text>
<Text weight='bold' size='small' className={_s.colorBGPrimary} isBadge>DONOR</Text>
</div>
}
</div>

View File

@@ -24,7 +24,7 @@ export default class PopoverLayout extends PureComponent {
if (isXS) {
return (
<div className={[_s.default, _s.bgPrimary, _s.overflowHidden, _s.modal, _s.topRightRadiusSmall, _s.topLeftRadiusSmall].join(' ')}>
<div className={[_s.default, _s.bgPrimary, _s.modal, _s.topRightRadiusSmall, _s.topLeftRadiusSmall].join(' ')}>
{
!!title &&
<div className={[_s.default, _s.flexRow, _s.alignItemsCenter, _s.justifyContentCenter, _s.borderBottom1PX, _s.borderColorSecondary, _s.height53PX, _s.px15].join(' ')}>
@@ -33,7 +33,7 @@ export default class PopoverLayout extends PureComponent {
</Heading>
</div>
}
<div className={[_s.default, _s.heightMax80VH, _s.overflowYScroll].join(' ')}>
<div className={[_s.default, _s.heightMax80VH, _s.topRightRadiusSmall, _s.topLeftRadiusSmall, _s.overflowYScroll].join(' ')}>
{children}
</div>
</div>

View File

@@ -79,6 +79,17 @@ class PopoverRoot extends PureComponent {
window.removeEventListener('resize', this.handleResize, false)
}
componentDidUpdate() {
const { type } = this.props
const { width } = this.state
if (width <= BREAKPOINT_EXTRA_SMALL && !!type) {
document.body.classList.add(_s.overflowYHidden)
} else {
document.body.classList.remove(_s.overflowYHidden)
}
}
handleResize = () => {
const { width } = getWindowDimension()

View File

@@ -55,7 +55,7 @@ class SidebarMorePopover extends PureComponent {
},
{
title: intl.formatMessage(messages.settings),
href: '/settings',
href: '/settings/preferences',
},
{
title: intl.formatMessage(messages.logout),

View File

@@ -13,6 +13,7 @@ import Button from './button'
const mapStateToProps = (state) => ({
value: state.getIn(['search', 'value']),
submitted: state.getIn(['search', 'submitted']),
theme: state.getIn(['settings', 'displayOptions', 'theme']),
})
const mapDispatchToProps = (dispatch) => ({
@@ -39,6 +40,8 @@ class Search extends PureComponent {
withOverlay: PropTypes.bool,
onClear: PropTypes.func.isRequired,
onSubmit: PropTypes.func.isRequired,
isInNav: PropTypes.bool.isRequired,
theme: PropTypes.string,
}
state = {
@@ -99,6 +102,8 @@ class Search extends PureComponent {
value,
submitted,
onClear,
isInNav,
theme,
} = this.props
const { focused } = this.state
const highlighted = focused || `${value}`.length > 0
@@ -110,7 +115,7 @@ class Search extends PureComponent {
lineHeight125: 1,
displayBlock: 1,
py7: 1,
bgTransparent: !highlighted,
bgTransparent: 1,
colorPrimary: 1,
fs14PX: 1,
flexGrow1: 1,
@@ -121,8 +126,8 @@ class Search extends PureComponent {
const containerClasses = CX({
default: 1,
bgBrandLight: !highlighted,
bgWhite: highlighted,
searchNavigation: (!highlighted && isInNav && theme === 'light') || (isInNav && theme !== 'light'),
bgWhite: (highlighted && isInNav && theme === 'light'),
flexRow: 1,
radiusSmall: 1,
alignItemsCenter: 1,
@@ -159,7 +164,7 @@ class Search extends PureComponent {
color={prependIconColor}
onClick={this.handleSubmit}
icon='search'
iconClassName={_s.inheritFill}
iconClassName={_s.fillInherit}
iconSize='16px'
/>
</div>

View File

@@ -0,0 +1,265 @@
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { Link, NavLink } from 'react-router-dom'
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { injectIntl, defineMessages } from 'react-intl'
import { CX } from '../constants'
import Avatar from './avatar'
import DisplayName from './display_name'
import Button from './button'
import Heading from './heading'
import Text from './text'
import List from './list'
import { closeSidebar } from '../actions/sidebar'
import { shortNumberFormat } from '../utils/numbers'
import { me } from '../initial_state'
import { makeGetAccount } from '../selectors'
import ProgressPanel from './panel/progress_panel'
const messages = defineMessages({
followers: { id: 'account.followers', defaultMessage: 'Followers' },
follows: { id: 'account.follows', defaultMessage: 'Follows' },
profile: { id: 'account.profile', defaultMessage: 'Profile' },
preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' },
follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' },
blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' },
domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' },
mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' },
filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' },
logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' },
lists: { id: 'column.lists', defaultMessage: 'Lists', },
apps: { id: 'tabs_bar.apps', defaultMessage: 'Apps' },
more: { id: 'sidebar.more', defaultMessage: 'More' },
pro: { id: 'promo.gab_pro', defaultMessage: 'Upgrade to GabPRO' },
trends: { id: 'promo.trends', defaultMessage: 'Trends' },
search: { id: 'tabs_bar.search', defaultMessage: 'Search' },
shop: { id: 'tabs_bar.shop', defaultMessage: 'Store - Buy Merch' },
chat: { id: 'tabs_bar.chat', defaultMessage: 'Chat' },
})
const mapStateToProps = (state) => ({
account: makeGetAccount()(state, me),
sidebarOpen: state.get('sidebar').open,
})
const mapDispatchToProps = (dispatch) => ({
onCloseSidebar: () => dispatch(closeSidebar()),
})
export default @connect(mapStateToProps, mapDispatchToProps)
@injectIntl
class SidebarXS extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
account: ImmutablePropTypes.map,
sidebarOpen: PropTypes.bool,
onCloseSidebar: PropTypes.func.isRequired,
}
state = {
moreOpen: false,
}
componentDidUpdate () {
if (!me) return
if (this.props.sidebarOpen) {
document.body.classList.add(_s.overflowYHidden)
} else {
document.body.classList.remove(_s.overflowYHidden)
}
}
toggleMore = () => {
this.setState({ moreOpen: !this.state.moreOpen })
}
handleSidebarClose = () => {
this.props.onCloseSidebar()
this.setState({ moreOpen: false })
}
render () {
const { sidebarOpen, intl, account } = this.props
const { moreOpen } = this.state
if (!me || !account) return null
const acct = account.get('acct')
const isPro = account.get('is_pro')
const moreIcon = moreOpen ? 'minus' : 'plus'
const moreContainerStyle = { display: moreOpen ? 'block' : 'none' }
const mainItems = [
{
icon: 'user',
to: `/${acct}`,
onClick: this.handleSidebarClose,
title: intl.formatMessage(messages.profile),
},
{
icon: 'arrow-up',
href: 'https://pro.gab.com',
onClick: this.handleSidebarClose,
title: intl.formatMessage(messages.pro),
},
{
icon: 'shop',
href: 'https://shop.gab.com',
onClick: this.handleSidebarClose,
title: intl.formatMessage(messages.shop),
},
{
icon: 'trends',
href: 'https://trends.gab.com',
onClick: this.handleSidebarClose,
title: intl.formatMessage(messages.trends),
},
{
icon: 'chat',
href: 'https://chat.gab.com',
onClick: this.handleSidebarClose,
title: intl.formatMessage(messages.chat),
},
{
icon: 'search',
to: '/search',
onClick: this.handleSidebarClose,
title: intl.formatMessage(messages.search),
},
{
icon: 'cog',
href: '/settings/preferences',
onClick: this.handleSidebarClose,
title: intl.formatMessage(messages.preferences),
},
{
icon: 'list',
to: '/lists',
onClick: this.handleSidebarClose,
title: intl.formatMessage(messages.lists),
},
{
icon: 'user',
to: '/follow_requests',
onClick: this.handleSidebarClose,
title: intl.formatMessage(messages.follow_requests),
},
{
icon: 'user',
to: '/blocks',
onClick: this.handleSidebarClose,
title: intl.formatMessage(messages.blocks),
},
{
icon: 'user',
to: '/domain_blocks',
onClick: this.handleSidebarClose,
title: intl.formatMessage(messages.domain_blocks),
},
{
icon: 'user',
to: '/mutes',
onClick: this.handleSidebarClose,
title: intl.formatMessage(messages.mutes),
},
{
icon: 'user',
to: '/filters',
onClick: this.handleSidebarClose,
title: intl.formatMessage(messages.filters),
},
{
icon: 'user',
href: '/auth/sign_out',
title: intl.formatMessage(messages.logout),
},
]
const containerClasses = CX({
default: 1,
posFixed: 1,
top0: 1,
left0: 1,
right0: 1,
bottom0: 1,
z5: 1,
displayNone: !sidebarOpen,
})
return (
<div className={containerClasses}>
<div className={[_s.default, _s.posFixed, _s.top0, _s.left0, _s.right0, _s.bgBlackOpaque, _s.bottom0].join(' ')} role='button' onClick={this.handleSidebarClose} />
<div className={[_s.defaut, _s.posFixed, _s.left0, _s.top0, _s.bottom0, _s.bgPrimary, _s.width330PX, _s.borderRight1PX, _s.borderColorSecondary, _s.maxWidth80PC].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.px15, _s.height53PX, _s.width100PC, _s.borderBottom1PX, _s.borderColorSecondary, _s.alignItemsCenter, _s.justifyContentCenter].join(' ')}>
<Heading size='h2'>Account Info</Heading>
<Button
title='close'
color='secondary'
backgroundColor='none'
onClick={this.handleSidebarClose}
icon='close'
iconSize='12px'
className={_s.mlAuto}
/>
</div>
<div className={[_s.default, _s.width100PC, _s.overflowYScroll, _s.heightCalc53PX].join(' ')}>
<div className={[_s.default, _s.width100PC, _s.px15, _s.py10].join(' ')}>
<div className={[_s.default, _s.mt5].join(' ')}>
<Link
to={`/${acct}`}
title={acct}
onClick={this.handleSidebarClose}
>
<Avatar account={account} size={60} />
</Link>
</div>
<div className={[_s.default, _s.my10, _s.width100PC].join(' ')}>
<DisplayName account={account} isMultiline />
</div>
<div className={[_s.default, _s.flexRow, _s.flexWrap].join(' ')}>
<NavLink
to={`/${acct}/followers`}
onClick={this.handleSidebarClose}
title={intl.formatNumber(account.get('followers_count'))}
className={[_s.text, _s.noUnderline, _s.underline_onHover, _s.mr15].join(' ')}
>
<Text weight='bold'>{shortNumberFormat(account.get('followers_count'))}&nbsp;</Text>
<Text>{intl.formatMessage(messages.followers)}</Text>
</NavLink>
<NavLink
to={`/${acct}/following`}
onClick={this.handleSidebarClose}
title={intl.formatNumber(account.get('following_count'))}
className={[_s.text, _s.noUnderline, _s.underline_onHover].join(' ')}
>
<Text weight='bold'>{shortNumberFormat(account.get('following_count'))}&nbsp;</Text>
<Text>{intl.formatMessage(messages.follows)}</Text>
</NavLink>
</div>
</div>
<div className={[_s.default, _s.my10, _s.px15].join(' ')}>
<ProgressPanel />
</div>
<div className={[_s.default, _s.mb15, _s.boxShadowNone].join(' ')}>
<List items={mainItems} />
</div>
</div>
</div>
</div>
)
}
}

View File

@@ -66,6 +66,7 @@ class Status extends ImmutablePureComponent {
status: ImmutablePropTypes.map,
descendantsIds: ImmutablePropTypes.list,
ancestorStatus: ImmutablePropTypes.map,
isNotification: PropTypes.bool,
isChild: PropTypes.bool,
isPromoted: PropTypes.bool,
isFeatured: PropTypes.bool,
@@ -247,6 +248,8 @@ class Status extends ImmutablePureComponent {
}
handleClick = () => {
// : todo : if clicked on isNotification statusactionbaritem do not go to new page
if (this.props.onClick) {
this.props.onClick()
return
@@ -363,6 +366,7 @@ class Status extends ImmutablePureComponent {
isPromoted,
isChild,
isHidden,
isNotification,
descendantsIds,
commentsLimited,
ancestorStatus,
@@ -437,8 +441,8 @@ class Status extends ImmutablePureComponent {
radiusSmall: isChild,
borderColorSecondary: isChild,
border1PX: isChild,
pb10: isChild && status.get('media_attachments').size === 0,
pb5: isChild && status.get('media_attachments').size > 1,
pb10: isChild && status.get('media_attachments').size === 0 && !isNotification,
pb5: isChild && status.get('media_attachments').size > 1 && !isNotification,
cursorPointer: isChild,
bgSubtle_onHover: isChild,
})
@@ -521,7 +525,7 @@ class Status extends ImmutablePureComponent {
}
{
!isChild &&
(!isChild || isNotification) &&
<StatusActionBar
status={status}
onFavorite={this.props.onFavorite}

View File

@@ -42,6 +42,7 @@ export default class Textarea extends PureComponent {
flexGrow1: 1,
heightMax100VH: 1,
resizeVertical: 1,
colorPrimary: 1,
px5: !!prependIcon,
pl15: !prependIcon,
})