This commit is contained in:
mgabdev
2020-12-16 02:39:07 -05:00
parent d1ff39bb81
commit 8f94ffad9c
64 changed files with 958 additions and 870 deletions

View File

@@ -0,0 +1,39 @@
import React from 'react'
import PropTypes from 'prop-types'
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { CX } from '../constants'
import Button from './button'
import Icon from './icon'
import Image from './image'
import Text from './text'
class Album extends React.PureComponent {
handleOnClick = (e) => {
//
}
render() {
const { album } = this.props
return (
<Button
to={to}
href={href}
onClick={this.handleOnClick}
noClasses
>
</Button>
)
}
}
Album.propTypes = {
album: ImmutablePropTypes.map,
isAddable: PropTypes.bool,
}
export default Album

View File

@@ -0,0 +1,29 @@
import React from 'react'
import PropTypes from 'prop-types'
import { defineMessages, injectIntl } from 'react-intl'
import ModalLayout from './modal_layout'
import BookmarkCollectionCreate from '../../features/bookmark_collection_create'
class BookmarkCollectionCreateModal extends React.PureComponent {
render() {
const { onClose } = this.props
return (
<ModalLayout
title='Create Bookmark Collection'
width={500}
onClose={onClose}
>
<BookmarkCollectionCreate isModal />
</ModalLayout>
)
}
}
BookmarkCollectionCreateModal.propTypes = {
onClose: PropTypes.func.isRequired,
}
export default BookmarkCollectionCreateModal

View File

@@ -1,88 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { defineMessages, injectIntl } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes'
import { changeSetting, saveSettings } from '../../actions/settings'
import ModalLayout from './modal_layout'
import Button from '../button'
import SettingSwitch from '../setting_switch'
import Text from '../text'
class CommunityTimelineSettingsModal extends ImmutablePureComponent {
handleSaveAndClose = () => {
this.props.onSave()
}
render() {
const {
intl,
settings,
onChange,
onClose,
} = this.props
return (
<ModalLayout
onClose={onClose}
width={320}
title={intl.formatMessage(messages.title)}
>
<div className={[_s.d, _s.pb10].join(' ')}>
<SettingSwitch
prefix='community_timeline'
settings={settings}
settingPath={['shows', 'onlyMedia']}
onChange={onChange}
label={intl.formatMessage(messages.onlyMedia)}
/>
</div>
<Button
backgroundColor='brand'
color='white'
className={_s.jcCenter}
onClick={this.handleSaveAndClose}
>
<Text color='inherit' weight='bold' align='center'>
{intl.formatMessage(messages.saveAndClose)}
</Text>
</Button>
</ModalLayout>
)
}
}
const messages = defineMessages({
title: { id: 'community_timeline_settings', defaultMessage: 'Community Feed Settings' },
saveAndClose: { id: 'saveClose', defaultMessage: 'Save & Close' },
onlyMedia: { id: 'community.column_settings.media_only', defaultMessage: 'Media Only' },
})
const mapStateToProps = (state) => ({
settings: state.getIn(['settings', 'community']),
})
const mapDispatchToProps = (dispatch, { onClose }) => ({
onChange(key, checked) {
dispatch(changeSetting(['community', ...key], checked))
},
onSave() {
dispatch(saveSettings())
onClose()
},
})
CommunityTimelineSettingsModal.propTypes = {
intl: PropTypes.object.isRequired,
settings: ImmutablePropTypes.map.isRequired,
onChange: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
onSave: PropTypes.func.isRequired,
}
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(CommunityTimelineSettingsModal))

View File

@@ -1,36 +1,138 @@
import React from 'react'
import PropTypes from 'prop-types'
import ImmutablePropTypes from 'react-immutable-proptypes'
import ImmutablePureComponent from 'react-immutable-pure-component'
import { connect } from 'react-redux'
import { openModal } from '../../actions/modal'
import { setDeckColumnAtIndex } from '../../actions/deck'
import { getOrderedLists, getListOfGroups } from '../../selectors'
import { fetchLists } from '../../actions/lists'
import { fetchGroupsByTab } from '../../actions/groups'
import { MODAL_DECK_COLUMN_ADD } from '../../constants'
import Heading from '../heading'
import Button from '../button'
import Block from '../block'
import Input from '../input'
import List from '../list'
class DeckColumnAddOptionsModal extends React.PureComponent {
class DeckColumnAddOptionsModal extends ImmutablePureComponent {
state = {
selectedItem: null,
hashtagValue: '',
usernameValue: '',
}
componentDidMount() {
switch (this.props.column) {
case 'list':
this.props.onFetchLists()
break
case 'group':
this.props.onFetchMemberGroups()
break
default:
break
}
}
onClickClose = () => {
this.props.onClose()
this.props.dispatch(openModal(MODAL_DECK_COLUMN_ADD))
this.props.onOpenDeckColumnAddModal()
}
handleAdd = () => {
//
handleAdd = (id) => {
this.props.onSetDeckColumn(id)
this.props.onClose()
}
handleAddHashtag = () => {
this.handleAdd(`hashtag.${this.state.hashtagValue}`)
this.setState({ hashtagValue: '' })
}
onChangeHashtagValue = (hashtagValue) => {
this.setState({ hashtagValue })
}
onChangeUsernameValue = (usernameValue) => {
this.setState({ usernameValue })
}
getContentForColumn = () => {
const { column, lists, groups, accounts } = this.props
const { hashtagValue } = this.state
if (column === 'hashtag') {
return (
<div className={[_s.d, _s.px15, _s.py10].join(' ')}>
<Input
type='text'
value={hashtagValue}
placeholder='gabfam'
id='hashtag-deck'
title='Enter hashtag'
onChange={this.onChangeHashtagValue}
/>
</div>
)
} else if (column === 'list') {
const listItems = lists.map((list) => ({
onClick: () => this.handleAdd(`list.${list.get('id')}`),
title: list.get('title'),
}))
return (
<div className={[_s.d, _s.maxH340PX, _s.overflowYScroll].join(' ')}>
<List
scrollKey='lists-deck-add'
showLoading={lists.size === 0}
emptyMessage="You don't have any lists yet."
items={listItems}
/>
</div>
)
} else if (column === 'group') {
const listItems = groups.map((group) => ({
onClick: () => this.handleAdd(`group.${group.get('id')}`),
title: group.get('title'),
}))
return (
<div className={[_s.d, _s.maxH340PX, _s.overflowYScroll].join(' ')}>
<List
scrollKey='groups-deck-add'
showLoading={groups.size === 0}
emptyMessage="You are not a member of any groups yet."
items={listItems}
/>
</div>
)
} else if (column === 'group') {
return (
<div className={[_s.d, _s.px15, _s.py10].join(' ')}>
<Input
type='text'
value={usernameValue}
placeholder=''
id='user-deck'
title='Enter username'
onChange={this.onChangeUsernameValue}
/>
</div>
)
}
}
render() {
const { column } = this.props
const { selectedItem } = this.state
// user, hashtag, list, groups
const { hashtagValue } = this.state
if (!column) return <div />
const title = `Select a ${column}`
const content = this.getContentForColumn()
return (
<div style={{width: '520px'}} className={[_s.d, _s.modal].join(' ')}>
<Block>
@@ -49,16 +151,19 @@ class DeckColumnAddOptionsModal extends React.PureComponent {
{title}
</Heading>
<div className={[_s.d, _s.w115PX, _s.aiEnd, _s.jcCenter, _s.mlAuto].join(' ')}>
<Button
isDisabled={!selectedItem}
onClick={this.handleAdd}
>
Add
</Button>
{
column === 'hashtag' &&
<Button
isDisabled={!hashtagValue}
onClick={this.handleAddHashtag}
>
Add
</Button>
}
</div>
</div>
<div className={[_s.d].join(' ')}>
test
{content}
</div>
</Block>
</div>
@@ -67,9 +172,33 @@ class DeckColumnAddOptionsModal extends React.PureComponent {
}
const mapStateToProps = (state) => ({
lists: getOrderedLists(state),
groups: getListOfGroups(state, { type: 'member' }),
accounts: [],
})
const mapDispatchToProps = (dispatch) => ({
onFetchLists() {
dispatch(fetchLists())
},
onFetchMemberGroups() {
dispatch(fetchGroupsByTab('member'))
},
onSetDeckColumn(id) {
dispatch(setDeckColumnAtIndex(id))
},
onOpenDeckColumnAddModal() {
dispatch(openModal(MODAL_DECK_COLUMN_ADD))
},
})
DeckColumnAddOptionsModal.propTypes = {
groupIds: ImmutablePropTypes.list,
onClose: PropTypes.func.isRequired,
onFetchLists: PropTypes.func.isRequired,
onSetDeckColumn: PropTypes.func.isRequired,
column: PropTypes.string.isRequired,
}
export default connect()(DeckColumnAddOptionsModal)
export default connect(mapStateToProps, mapDispatchToProps)(DeckColumnAddOptionsModal)

View File

@@ -1,88 +0,0 @@
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { defineMessages, injectIntl } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes'
import { changeSetting, saveSettings } from '../../actions/settings'
import ModalLayout from './modal_layout'
import Button from '../button'
import SettingSwitch from '../setting_switch'
import Text from '../text'
class HashtagTimelineSettingsModal extends ImmutablePureComponent {
handleSaveAndClose = () => {
this.props.onSave()
}
render() {
const { intl, settings, onChange, onClose } = this.props
// : todo :
return (
<ModalLayout
width={320}
title={intl.formatMessage(messages.title)}
onClose={onClose}
>
<div className={[_s.d, _s.pb10].join(' ')}>
<SettingSwitch
prefix='community_timeline'
settings={settings}
settingPath={['shows', 'inSidebar']}
onChange={onChange}
label={intl.formatMessage(messages.showInSidebar)}
/>
</div>
<Button
backgroundColor='brand'
color='white'
className={_s.jcCenter}
onClick={this.handleSaveAndClose}
>
<Text color='inherit' weight='bold' align='center'>
{intl.formatMessage(messages.saveAndClose)}
</Text>
</Button>
</ModalLayout>
)
}
}
const messages = defineMessages({
title: { id: 'hashtag_timeline_settings', defaultMessage: 'Hashtag Timeline Settings' },
saveAndClose: { id: 'saveClose', defaultMessage: 'Save & Close' },
onlyMedia: { id: 'community.column_settings.media_only', defaultMessage: 'Media Only' },
showInSidebar: { id: 'show_in_sidebar', defaultMessage: 'Show in Sidebar' },
})
const mapStateToProps = (state) => ({
settings: state.getIn(['settings', 'community']),
})
const mapDispatchToProps = (dispatch, { onClose }) => {
return {
onChange(key, checked) {
dispatch(changeSetting(['community', ...key], checked))
},
onSave() {
dispatch(saveSettings())
onClose()
},
}
}
HasttagTimelineSettingsModal.propTypes = {
intl: PropTypes.object.isRequired,
settings: ImmutablePropTypes.map.isRequired,
onChange: PropTypes.func.isRequired,
onSave: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
}
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(HashtagTimelineSettingsModal))

View File

@@ -8,11 +8,12 @@ import ModalBase from './modal_base'
import BundleErrorModal from './bundle_error_modal'
import LoadingModal from './loading_modal'
import {
MODAL_ALBUM_CREATE,
MODAL_BLOCK_ACCOUNT,
MODAL_BOOKMARK_COLLECTION_CREATE,
MODAL_BOOST,
MODAL_CHAT_CONVERSATION_CREATE,
MODAL_CHAT_CONVERSATION_DELETE,
MODAL_COMMUNITY_TIMELINE_SETTINGS,
MODAL_COMPOSE,
MODAL_CONFIRM,
MODAL_DECK_COLUMN_ADD,
@@ -24,7 +25,6 @@ import {
MODAL_GROUP_CREATE,
MODAL_GROUP_DELETE,
MODAL_GROUP_PASSWORD,
MODAL_HASHTAG_TIMELINE_SETTINGS,
MODAL_HOME_TIMELINE_SETTINGS,
MODAL_HOTKEYS,
MODAL_LIST_ADD_USER,
@@ -44,11 +44,12 @@ import {
MODAL_VIDEO,
} from '../../constants'
import {
AlbumCreateModal,
BlockAccountModal,
BookmarkCollectionCreateModal,
BoostModal,
ChatConversationCreateModal,
ChatConversationDeleteModal,
CommunityTimelineSettingsModal,
ComposeModal,
ConfirmationModal,
DeckColumnAddModal,
@@ -62,7 +63,6 @@ import {
GroupMembersModal,
GroupPasswordModal,
GroupRemovedAccountsModal,
HashtagTimelineSettingsModal,
HomeTimelineSettingsModal,
HotkeysModal,
ListAddUserModal,
@@ -83,11 +83,12 @@ import {
} from '../../features/ui/util/async_components'
const MODAL_COMPONENTS = {
[MODAL_ALBUM_CREATE]: AlbumCreateModal,
[MODAL_BLOCK_ACCOUNT]: BlockAccountModal,
[MODAL_BOOKMARK_COLLECTION_CREATE]: BookmarkCollectionCreateModal,
[MODAL_BOOST]: BoostModal,
[MODAL_CHAT_CONVERSATION_CREATE]: ChatConversationCreateModal,
[MODAL_CHAT_CONVERSATION_DELETE]: ChatConversationDeleteModal,
[MODAL_COMMUNITY_TIMELINE_SETTINGS]: CommunityTimelineSettingsModal,
[MODAL_COMPOSE]: ComposeModal,
[MODAL_CONFIRM]: ConfirmationModal,
[MODAL_DECK_COLUMN_ADD]: DeckColumnAddModal,
@@ -99,7 +100,6 @@ const MODAL_COMPONENTS = {
[MODAL_GROUP_CREATE]: GroupCreateModal,
[MODAL_GROUP_DELETE]: GroupDeleteModal,
[MODAL_GROUP_PASSWORD]: GroupPasswordModal,
[MODAL_HASHTAG_TIMELINE_SETTINGS]: HashtagTimelineSettingsModal,
[MODAL_HOME_TIMELINE_SETTINGS]: HomeTimelineSettingsModal,
[MODAL_HOTKEYS]: HotkeysModal,
[MODAL_LIST_ADD_USER]: ListAddUserModal,

View File

@@ -1,6 +1,7 @@
import React from 'react'
import PropTypes from 'prop-types'
import BackButton from '../back_button'
import Button from '../button'
import Heading from '../heading'
class ProfileNavigationBar extends React.PureComponent {
@@ -28,6 +29,19 @@ class ProfileNavigationBar extends React.PureComponent {
</Heading>
</div>
<div className={[_s.d, _s.minH53PX, _s.jcCenter, _s.mr15].join(' ')}>
<Button
icon='ellipsis'
iconSize='26px'
iconClassName={_s.inheritFill}
color='brand'
backgroundColor='none'
className={[_s.jcCenter, _s.aiCenter, _s.ml10, _s.px10].join(' ')}
onClick={this.handleOpenMore}
buttonRef={this.setOpenMoreNodeRef}
/>
</div>
</div>
</div>

View File

@@ -61,7 +61,7 @@ class MediaGalleryPanel extends ImmutablePureComponent {
noPadding
title={intl.formatMessage(messages.title)}
headerButtonTitle={!!account ? intl.formatMessage(messages.show_all) : undefined}
headerButtonTo={!!account ? `/${account.get('acct')}/photos` : undefined}
headerButtonTo={!!account ? `/${account.get('acct')}/albums` : undefined}
>
<div className={[_s.d, _s.flexRow, _s.flexWrap, _s.px10, _s.py10].join(' ')}>
{

View File

@@ -32,35 +32,27 @@ class ProfileStatsPanel extends ImmutablePureComponent {
!!account &&
<ResponsiveClassesComponent
classNames={[_s.d, _s.flexRow].join(' ')}
classNamesXS={[_s.d, _s.flexRow, _s.mt15, _s.pt10].join(' ')}
classNamesXS={[_s.d, _s.flexRow, _s.mt15, _s.flexWrap].join(' ')}
>
<UserStat
title={intl.formatMessage(messages.gabs)}
value={shortNumberFormat(account.get('statuses_count'))}
to={`/${account.get('acct')}`}
isCentered={noPanel}
isInline={noPanel}
/>
<UserStat
title={intl.formatMessage(messages.followers)}
value={shortNumberFormat(account.get('followers_count'))}
to={`/${account.get('acct')}/followers`}
isCentered={noPanel}
isInline={noPanel}
/>
<UserStat
isLast
title={intl.formatMessage(messages.follows)}
value={shortNumberFormat(account.get('following_count'))}
to={`/${account.get('acct')}/following`}
isCentered={noPanel}
isInline={noPanel}
/>
{
account.get('id') === me &&
<UserStat
title={intl.formatMessage(messages.likes)}
value={shortNumberFormat(0)}
to={`/${account.get('acct')}/likes`}
isCentered={noPanel}
/>
}
</ResponsiveClassesComponent>
}
</Wrapper>

View File

@@ -53,6 +53,12 @@ class ChatConversationOptionsPopover extends ImmutablePureComponent {
subtitle: 'Hide until next message',
onClick: () => this.handleOnHide(),
},
{
hideArrow: true,
title: 'Mute Conversation',
subtitle: "Don't get notified of new messages",
onClick: () => this.handleOnHide(),
},
{},
{
hideArrow: true,

View File

@@ -4,14 +4,11 @@ import { connect } from 'react-redux'
import { closePopover } from '../../actions/popover'
import { deleteChatMessage } from '../../actions/chat_messages'
import {
isChatMessengerBlocked,
isChatMessengerMuted,
blockChatMessenger,
unblockChatMessenger,
muteChatMessenger,
unmuteChatMessenger,
reportChatMessage,
} from '../../actions/chat_conversation_accounts'
import { fetchRelationships } from '../../actions/accounts'
import { makeGetChatMessage } from '../../selectors'
import { me } from '../../initial_state'
import PopoverLayout from './popover_layout'
@@ -21,6 +18,12 @@ import Text from '../text'
class ChatMessageOptionsPopover extends React.PureComponent {
componentDidMount() {
if (!this.props.isMine) {
this.props.onFetchRelationships(this.props.fromAccountId)
}
}
handleOnDelete = () => {
this.props.onDeleteChatMessage(this.props.chatMessageId)
}
@@ -31,17 +34,9 @@ class ChatMessageOptionsPopover extends React.PureComponent {
handleOnBlock = () => {
if (this.props.isBlocked) {
this.props.unblockChatMessenger(this.props.fromAccountId)
this.props.onUnblock(this.props.fromAccountId)
} else {
this.props.blockChatMessenger(this.props.fromAccountId)
}
}
handleOnMute = () => {
if (this.props.isMuted) {
this.props.unmuteChatMessenger(this.props.fromAccountId)
} else {
this.props.muteChatMessenger(this.props.fromAccountId)
this.props.onBlock(this.props.fromAccountId)
}
}
@@ -53,7 +48,6 @@ class ChatMessageOptionsPopover extends React.PureComponent {
const {
isXS,
isMine,
isMuted,
isBlocked,
} = this.props
@@ -76,12 +70,6 @@ class ChatMessageOptionsPopover extends React.PureComponent {
subtitle: isBlocked ? '' : 'The messenger will not be able to message you.',
onClick: () => this.handleOnBlock(),
},
{
hideArrow: true,
title: isMuted ? 'Unmute Messenger' : 'Mute Messenger',
subtitle: isMuted ? '' : 'You will not be notified of new messsages',
onClick: () => this.handleOnMute(),
},
]
return (
@@ -96,12 +84,15 @@ class ChatMessageOptionsPopover extends React.PureComponent {
}
}
const mapStateToProps = (state, { chatMessageId }) => ({
isMine: state.getIn(['chat_messages', chatMessageId, 'from_account_id']) === me,
fromAccountId: state.getIn(['chat_messages', chatMessageId, 'from_account_id']),
isBlocked: state.getIn(['chat_messages', chatMessageId, 'from_account_id']),
isMuted: state.getIn(['chat_messages', chatMessageId, 'from_account_id']),
})
const mapStateToProps = (state, { chatMessageId }) => {
const fromAccountId = state.getIn(['chat_messages', chatMessageId, 'from_account_id'])
return {
fromAccountId,
isMine: fromAccountId === me,
isBlocked: state.getIn(['relationships', fromAccountId, 'chat_blocked_by'], false),
}
}
const mapDispatchToProps = (dispatch) => ({
onDeleteChatMessage(chatMessageId) {
@@ -114,15 +105,12 @@ const mapDispatchToProps = (dispatch) => ({
onUnblock(accountId) {
dispatch(unblockChatMessenger(accountId))
},
onMute(accountId) {
dispatch(muteChatMessenger(accountId))
},
onUnmute(accountId) {
dispatch(unmuteChatMessenger(accountId))
},
onReportChatMessage(chatMessageId) {
dispatch(reportChatMessage(chatMessageId))
},
onFetchRelationships(accountId) {
// dispatch(fetchRelationships(accountId))
},
onClosePopover() {
dispatch(closePopover())
},
@@ -130,9 +118,9 @@ const mapDispatchToProps = (dispatch) => ({
ChatMessageOptionsPopover.propTypes = {
isXS: PropTypes.bool,
isMine: PropTypes.bool,
chatMessageId: PropTypes.string.isRequired,
isBlocked: PropTypes.bool.isRequired,
isMuted: PropTypes.bool.isRequired,
onDeleteChatMessage: PropTypes.func.isRequired,
}

View File

@@ -4,6 +4,7 @@ import { connect } from 'react-redux'
import { closePopover } from '../../actions/popover'
import PopoverLayout from './popover_layout'
import List from '../list'
import Button from '../button'
import Text from '../text'
class ComposePostDesinationPopover extends React.PureComponent {
@@ -38,8 +39,20 @@ class ComposePostDesinationPopover extends React.PureComponent {
isXS={isXS}
onClose={this.handleOnClosePopover}
>
<Text className={[_s.d, _s.px15, _s.py10, _s.bgSecondary].join(' ')}>Post to:</Text>
<List items={items} />
<div className={[_s.d]}>
<Text className={[_s.d, _s.px15, _s.py10, _s.bgSecondary].join(' ')}>Post to:</Text>
<List items={items} />
</div>
<div>
<Text className={[_s.d, _s.px15, _s.py10, _s.bgSecondary].join(' ')}>
<Button
isText
icon='back'
/>
Select group:
</Text>
<List items={items} />
</div>
</PopoverLayout>
)
}

View File

@@ -78,6 +78,7 @@ class StatusOptionsPopover extends ImmutablePureComponent {
handleGroupRemoveAccount = () => {
const { status } = this.props
// : todo : check
this.props.onGroupRemoveAccount(status.getIn(['group', 'id']), status.getIn(['account', 'id']))
}

View File

@@ -107,7 +107,7 @@ class ProfileHeader extends ImmutablePureComponent {
title: intl.formatMessage(messages.comments),
},
{
to: `/${account.get('acct')}/photos`,
to: `/${account.get('acct')}/albums`,
title: intl.formatMessage(messages.photos),
},
{
@@ -119,7 +119,11 @@ class ProfileHeader extends ImmutablePureComponent {
const isMyProfile = !account ? false : account.get('id') === me
if (isMyProfile) {
tabs.push({
to: `/${account.get('acct')}/bookmarks`,
to: `/${account.get('acct')}/likes`,
title: 'Likes',
})
tabs.push({
to: `/${account.get('acct')}/bookmark_collections`,
title: intl.formatMessage(messages.bookmarks),
})
}
@@ -149,21 +153,12 @@ class ProfileHeader extends ImmutablePureComponent {
displayNone: stickied,
})
const mobileAvatarContainerClasses = CX({
d: 1,
circle: 1,
boxShadowProfileAvatar: 1,
mtNeg50PX: !headerMissing,
})
const mobileDescriptionContainerClasses = CX({
d: 1,
w100PC: 1,
px15: 1,
mt5: !!me,
mb10: 1,
pt15: !!me,
pb10: 1,
})
return (
@@ -174,10 +169,10 @@ class ProfileHeader extends ImmutablePureComponent {
<div className={[_s.d, _s.w100PC].join(' ')}>
{
!headerMissing &&
<div className={[_s.d, _s.h200PX, _s.px10, _s.w100PC, _s.mt10, _s.overflowHidden].join(' ')}>
<div className={[_s.d, _s.h172PX, _s.w100PC, _s.overflowHidden].join(' ')}>
<Image
alt={intl.formatMessage(messages.headerPhoto)}
className={[_s.topRightRadiusSmall, _s.topLeftRadiusSmall, _s.h100PC].join(' ')}
className={_s.h100PC}
src={headerSrc}
expandOnClick
/>
@@ -185,85 +180,80 @@ class ProfileHeader extends ImmutablePureComponent {
}
{
headerMissing &&
<div className={[_s.d, _s.h20PX, _s.w100PC].join(' ')} />
<div className={[_s.d, _s.h122PX, _s.w100PC, _s.bgSecondary].join(' ')} />
}
<div className={[_s.d, _s.w100PC].join(' ')}>
<div className={[_s.d, _s.aiCenter, _s.px15, _s.mb5].join(' ')}>
<div className={mobileAvatarContainerClasses}>
<Avatar size={100} account={account} noHover expandOnClick />
<div className={[_s.d, _s.px15].join(' ')}>
<div class={[_s.d, _s.flexRow].join(' ')}>
<div className={[_s.d, _s.circle, _s.boxShadowProfileAvatar, _s.mtNeg32PX].join(' ')}>
<Avatar size={88} account={account} noHover expandOnClick />
</div>
{
account && account.get('id') === me &&
<div className={[_s.d, _s.flexRow, _s.pt10, _s.flexGrow1, _s.h40PX, _s.jcEnd].join(' ')}>
<Button
isOutline
backgroundColor='none'
color='brand'
className={[_s.jcCenter, _s.aiCenter, _s.h40PX].join(' ')}
onClick={this.handleOnEditProfile}
>
<Text color='inherit' weight='bold' size='medium' className={_s.px15}>
{intl.formatMessage(messages.editProfile)}
</Text>
</Button>
</div>
}
{
account && account.get('id') !== me && !!me &&
<div className={[_s.d, _s.flexRow, _s.aiCenter, _s.pt15, _s.flexGrow1, _s.h40PX, _s.jcEnd].join(' ')}>
<Button
icon={isShortcut ? 'star' : 'star-outline'}
iconSize='18px'
color='brand'
backgroundColor='none'
className={[_s.jcCenter, _s.aiCenter, _s.px10, _s.mr10].join(' ')}
onClick={this.handleToggleShortcut}
/>
<div className={[_s.d, _s.flexRow, _s.h40PX].join(' ')}>
<Button
isOutline
icon='chat'
iconSize='18px'
iconClassName={_s.inheritFill}
color='brand'
backgroundColor='none'
className={[_s.jcCenter, _s.aiCenter, _s.mr10, _s.px10].join(' ')}
onClick={this.handleOpenMore}
buttonRef={this.setOpenMoreNodeRef}
/>
</div>
<div className={[_s.d, _s.flexRow, _s.h40PX].join(' ')}>
<AccountActionButton account={account} />
</div>
</div>
}
</div>
<div className={[_s.d, _s.flexRow, _s.flexNormal, _s.py10].join(' ')}>
<div className={[_s.d, _s.flexRow, _s.flexNormal, _s.pt10].join(' ')}>
<DisplayName
account={account}
isMultiline
isLarge
isCentered
noHover
/>
</div>
</div>
<div className={[_s.d, _s.bgPrimary, _s.aiCenter].join(' ')}>
{
account && account.get('id') === me &&
<div className={[_s.d,_s.py5].join(' ')}>
<Button
isOutline
backgroundColor='none'
color='brand'
className={[_s.jcCenter, _s.aiCenter].join(' ')}
onClick={this.handleOnEditProfile}
>
<Text color='inherit' weight='bold' size='medium' className={_s.px15}>
{intl.formatMessage(messages.editProfile)}
</Text>
</Button>
</div>
}
{
account && account.get('id') !== me && !!me &&
<div className={[_s.d, _s.flexRow, _s.py5].join(' ')}>
<Button
icon={isShortcut ? 'star' : 'star-outline'}
iconSize='18px'
color='brand'
backgroundColor='none'
className={[_s.jcCenter, _s.aiCenter, _s.px10, _s.mr15].join(' ')}
onClick={this.handleToggleShortcut}
/>
<div className={[_s.d, _s.flexRow, _s.mr15].join(' ')}>
<AccountActionButton account={account} />
</div>
<div>
<Button
isOutline
icon='ellipsis'
iconSize='18px'
iconClassName={_s.inheritFill}
color='brand'
backgroundColor='none'
className={[_s.jcCenter, _s.aiCenter, _s.ml10, _s.px10].join(' ')}
onClick={this.handleOpenMore}
buttonRef={this.setOpenMoreNodeRef}
/>
</div>
</div>
}
<div className={mobileDescriptionContainerClasses}>
{children}
</div>
<div className={[_s.d, _s.mt10, _s.mb10, _s.pt5, _s.w100PC, _s.pr10].join(' ')}>
<div className={[_s.d, _s.mt10, _s.mb10, _s.pt5, _s.w100PC].join(' ')}>
<Pills pills={tabs} />
</div>
</div>

View File

@@ -89,18 +89,12 @@ class DeckSidebar extends ImmutablePureComponent {
<div className={[_s.d, _s.aiCenter, _s.jcCenter].join(' ')}>
{
/*
!!gabDeckOrder && gabDeckOrder.map((item, i) => (
<Button
isText
key={`gab-deck-sidebar-dot-${i}`}
onClick={this.scrollToItem}
backgroundColor='secondary'
className={[_s.mt5, _s.mb5, _s.px10, _s.py10, _s.circle].join(' ')}
icon='notifications'
iconClassName={_s.cPrimary}
/>
))
}
*/
}
</div>
<Divider isSmall />

View File

@@ -3,6 +3,7 @@ import PropTypes from 'prop-types'
import { NavLink } from 'react-router-dom'
import { CX } from '../constants'
import Text from './text'
import DotTextSeperator from './dot_text_seperator'
/**
* Renders a user stat component
@@ -30,17 +31,29 @@ class UserStat extends React.PureComponent {
title,
value,
isCentered,
isInline,
isLast,
} = this.props
const { hovering } = this.state
const align = isCentered ? 'center' : 'left'
const titleSize = isInline ? 'normal' : 'extraLarge'
const subtitleSize = isInline ? 'normal' : 'small'
const containerClasses = CX({
d: 1,
cursorPointer: 1,
noUnderline: 1,
flexNormal: isCentered,
flexGrow1: !isCentered,
pr15: !isCentered,
flexGrow1: !isCentered && !isInline,
flexRow: isInline,
aiCenter: isInline,
pr15: !isCentered && !isInline,
pr10: !isCentered && isInline,
})
const subtitleClasses = CX({
pr5: isInline,
pl5: isInline,
})
return (
@@ -51,12 +64,13 @@ class UserStat extends React.PureComponent {
onMouseEnter={this.handleOnMouseEnter}
onMouseLeave={this.handleOnMouseLeave}
>
<Text size='extraLarge' weight='bold' color='brand' align={align}>
<Text size={titleSize} weight='bold' color='brand' align={align}>
{value}
</Text>
<Text size='small' weight='medium' color='secondary' hasUnderline={hovering} align={align}>
<Text size={subtitleSize} weight='medium' color='secondary' hasUnderline={hovering} align={align} className={subtitleClasses}>
{title}
</Text>
{ !isLast && isInline && <DotTextSeperator /> }
</NavLink>
)
}
@@ -72,6 +86,8 @@ UserStat.propTypes = {
PropTypes.object,
]).isRequired,
isCentered: PropTypes.bool,
isInline: PropTypes.bool,
isLast: PropTypes.bool,
}
export default UserStat