Progress
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
@@ -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))
|
||||
@@ -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)
|
||||
@@ -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))
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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(' ')}>
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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']))
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 />
|
||||
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user