This commit is contained in:
mgabdev
2020-04-06 21:53:23 -04:00
parent e485e2f955
commit b5e3c2a94f
58 changed files with 482 additions and 229 deletions

View File

@@ -10,10 +10,13 @@ import CalendarIcon from '../assets/calendar_icon'
import ChatIcon from '../assets/chat_icon'
import CircleIcon from '../assets/circle_icon'
import CloseIcon from '../assets/close_icon'
import CodeIcon from '../assets/code_icon'
import CommentIcon from '../assets/comment_icon'
import CopyIcon from '../assets/copy_icon'
import DissenterIcon from '../assets/dissenter_icon'
import DonorIcon from '../assets/donor_icon'
import EllipsisIcon from '../assets/ellipsis_icon'
import EmailIcon from '../assets/email_icon'
import ErrorIcon from '../assets/error_icon'
import FullscreenIcon from '../assets/fullscreen_icon'
import GabLogoIcon from '../assets/gab_logo'
@@ -31,6 +34,8 @@ import LinkIcon from '../assets/link_icon'
import ListIcon from '../assets/list_icon'
import ListAddIcon from '../assets/list_add_icon'
import LoadingIcon from '../assets/loading_icon'
import LockIcon from '../assets/lock_icon'
import LockFilledIcon from '../assets/lock_filled_icon'
import MediaIcon from '../assets/media_icon'
import MinimizeFullscreenIcon from '../assets/minimize_fullscreen_icon'
import MissingIcon from '../assets/missing_icon'
@@ -54,6 +59,7 @@ import TextSizeIcon from '../assets/text_size_icon'
import TrendsIcon from '../assets/trends_icon'
import ULListIcon from '../assets/ul_list_icon'
import UnderlineIcon from '../assets/underline_icon'
import UnlockFilledIcon from '../assets/unlock_filled_icon'
import VerifiedIcon from '../assets/verified_icon'
import WarningIcon from '../assets/warning_icon'
@@ -69,10 +75,13 @@ const ICONS = {
'calendar': CalendarIcon,
'chat': ChatIcon,
'close': CloseIcon,
'code': CodeIcon,
'comment': CommentIcon,
'copy': CopyIcon,
'dissenter': DissenterIcon,
'donor': DonorIcon,
'ellipsis': EllipsisIcon,
'email': EmailIcon,
'error': ErrorIcon,
'fullscreen': FullscreenIcon,
'gab-logo': GabLogoIcon,
@@ -90,6 +99,8 @@ const ICONS = {
'list': ListIcon,
'list-add': ListAddIcon,
'loading': LoadingIcon,
'lock': LockIcon,
'lock-filled': LockFilledIcon,
'media': MediaIcon,
'minimize-fullscreen': MinimizeFullscreenIcon,
'missing': MissingIcon,
@@ -113,6 +124,7 @@ const ICONS = {
'trends': TrendsIcon,
'ul-list': ULListIcon,
'underline': UnderlineIcon,
'unlock-filled': UnlockFilledIcon,
'verified': VerifiedIcon,
'warning': WarningIcon,
'': CircleIcon,

View File

@@ -9,7 +9,10 @@ export default class List extends ImmutablePureComponent {
items: PropTypes.array,
scrollKey: PropTypes.string,
emptyMessage: PropTypes.any,
small: PropTypes.bool,
size: PropTypes.oneOf([
'small',
'large'
]),
onLoadMore: PropTypes.func,
hasMore: PropTypes.bool,
}
@@ -20,7 +23,7 @@ export default class List extends ImmutablePureComponent {
scrollKey,
emptyMessage,
hasMore,
small,
size,
onLoadMore
} = this.props
@@ -35,7 +38,7 @@ export default class List extends ImmutablePureComponent {
{
items.map((item, i) => (
<ListItem
small={small}
size={size}
key={`list-item-${i}`}
isLast={items.size - 1 === i}
{...item}

View File

@@ -13,7 +13,9 @@ export default class ListItem extends PureComponent {
href: PropTypes.string,
title: PropTypes.string,
onClick: PropTypes.func,
small: PropTypes.bool,
size: PropTypes.oneOf([
'small', 'large'
]),
hideArrow: PropTypes.bool,
}
@@ -24,11 +26,14 @@ export default class ListItem extends PureComponent {
to,
href,
onClick,
small,
size,
icon,
hideArrow,
} = this.props
const small = size === 'small'
const large = size === 'large'
const containerClasses = cx({
default: 1,
cursorPointer: 1,
@@ -45,7 +50,14 @@ export default class ListItem extends PureComponent {
borderBottom1PX: !isLast,
})
const textSize = small ? 'small' : 'normal'
const iconClasses = cx({
mr10: !large,
mr15: large,
fillColorBlack: 1,
})
const textSize = small ? 'small' : large ? 'medium' : 'normal'
const iconSize = large ? '14px' : '10px'
return (
<Button
@@ -60,9 +72,9 @@ export default class ListItem extends PureComponent {
!!icon &&
<Icon
id={icon}
width='10px'
height='10px'
className={[_s.mr10, _s.fillColorBlack].join(' ')}
width={iconSize}
height={iconSize}
className={iconClasses}
/>
}

View File

@@ -33,6 +33,7 @@ class BlockAccountModal extends PureComponent {
static propTypes = {
account: PropTypes.object.isRequired,
onConfirm: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
}
@@ -41,7 +42,7 @@ class BlockAccountModal extends PureComponent {
}
render() {
const { account, intl } = this.props
const { account, intl, onClose } = this.props
const title = intl.formatMessage(messages.title, {
name: !!account ? account.get('acct') : '',
@@ -56,6 +57,7 @@ class BlockAccountModal extends PureComponent {
message={message}
confirm={intl.formatMessage(messages.block)}
onConfirm={this.handleClick}
onClose={onClose}
/>
)
}

View File

@@ -1,7 +1,6 @@
import { defineMessages, injectIntl } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes'
import { closeModal } from '../../actions/modal'
import { changeSetting, saveSettings } from '../../actions/settings'
import ModalLayout from './modal_layout'
import Button from '../button'
@@ -19,14 +18,14 @@ const mapStateToProps = state => ({
settings: state.getIn(['settings', 'community']),
})
const mapDispatchToProps = dispatch => {
const mapDispatchToProps = (dispatch, { onClose }) => {
return {
onChange(key, checked) {
dispatch(changeSetting(['community', ...key], checked))
},
onSave() {
dispatch(saveSettings())
dispatch(closeModal())
onClose()
},
}
}
@@ -48,7 +47,7 @@ class CommunityTimelineSettingsModal extends ImmutablePureComponent {
}
render() {
const { intl, settings, onChange } = this.props
const { intl, settings, onChange, onClose } = this.props
return (
<ModalLayout

View File

@@ -60,11 +60,14 @@ class EmbedModal extends ImmutablePureComponent {
}
render() {
const { intl } = this.props
const { intl, onClose } = this.props
const { oembed } = this.state
return (
<ModalLayout title={intl.formatMessage(messages.embed)}>
<ModalLayout
title={intl.formatMessage(messages.embed)}
onClose={onClose}
>
<div className={_s.default}>
<Text className={_s.my10}>
{intl.formatMessage(messages.instructions)}

View File

@@ -6,7 +6,6 @@ import {
setSelectedGif,
changeGifSearchText
} from '../../actions/tenor'
import { closeModal } from '../../actions/modal'
import Block from '../block'
import Button from '../button'
import ColumnIndicator from '../column_indicator'
@@ -29,12 +28,12 @@ const mapStateToProps = (state) => ({
searchText: state.getIn(['tenor', 'searchText']),
})
export const mapDispatchToProps = (dispatch) => ({
export const mapDispatchToProps = (dispatch, { onClose }) => ({
handleCloseModal() {
dispatch(changeGifSearchText(''))
dispatch(clearGifResults())
dispatch(closeModal())
onClose()
},
handleFetchCategories: () => {

View File

@@ -13,15 +13,17 @@ class GroupCreateModal extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
onClose: PropTypes.func.isRequired,
}
render() {
const { intl } = this.props
const { intl, onClose } = this.props
return (
<ModalLayout
title={intl.formatMessage(messages.title)}
width='440'
onClose={onClose}
>
<GroupCreate />
</ModalLayout>

View File

@@ -25,6 +25,7 @@ class GroupDeleteModal extends PureComponent {
static propTypes = {
group: PropTypes.object.isRequired,
onConfirm: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
}
@@ -33,7 +34,7 @@ class GroupDeleteModal extends PureComponent {
}
render() {
const { group, intl } = this.props
const { group, intl, onClose } = this.props
const title = intl.formatMessage(messages.title, {
group: !!group ? account.get('title') : '',
@@ -48,6 +49,7 @@ class GroupDeleteModal extends PureComponent {
message={message}
confirm={intl.formatMessage(messages.delete)}
onConfirm={this.handleClick}
onClose={onClose}
/>
)
}

View File

@@ -1,7 +1,6 @@
import { defineMessages, injectIntl } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes'
import { closeModal } from '../../actions/modal'
import { changeSetting, saveSettings } from '../../actions/settings'
import ModalLayout from './modal_layout'
import Button from '../button'
@@ -19,14 +18,14 @@ const mapStateToProps = state => ({
settings: state.getIn(['settings', 'community']),
})
const mapDispatchToProps = dispatch => {
const mapDispatchToProps = (dispatch, { onClose }) => {
return {
onChange(key, checked) {
dispatch(changeSetting(['community', ...key], checked))
},
onSave() {
dispatch(saveSettings())
dispatch(closeModal())
onClose()
},
}
}
@@ -41,6 +40,7 @@ class HashtagTimelineSettingsModal extends ImmutablePureComponent {
settings: ImmutablePropTypes.map.isRequired,
onChange: PropTypes.func.isRequired,
onSave: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
}
handleSaveAndClose = () => {
@@ -48,7 +48,7 @@ class HashtagTimelineSettingsModal extends ImmutablePureComponent {
}
render() {
const { intl, settings, onChange } = this.props
const { intl, settings, onChange, onClose } = this.props
// : todo :
@@ -56,8 +56,9 @@ class HashtagTimelineSettingsModal extends ImmutablePureComponent {
<ModalLayout
width='320'
title={intl.formatMessage(messages.title)}
onClose={onClose}
>
<div className={[_s.default, _s.pb10].join(' ')}>
<SettingSwitch
prefix='community_timeline'

View File

@@ -1,7 +1,6 @@
import { defineMessages, injectIntl } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes'
import { closeModal } from '../../actions/modal'
import { changeSetting, saveSettings } from '../../actions/settings'
import ModalLayout from './modal_layout'
import Button from '../button'
@@ -22,14 +21,14 @@ const mapStateToProps = state => ({
settings: state.getIn(['settings', 'home']),
})
const mapDispatchToProps = dispatch => {
const mapDispatchToProps = (dispatch, {onClose}) => {
return {
onChange(key, checked) {
dispatch(changeSetting(['home', ...key], checked))
},
onSave() {
dispatch(saveSettings())
dispatch(closeModal())
onClose()
},
}
}
@@ -43,6 +42,7 @@ class HomeTimelineSettingsModal extends ImmutablePureComponent {
intl: PropTypes.object.isRequired,
settings: ImmutablePropTypes.map.isRequired,
onChange: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
onSave: PropTypes.func.isRequired,
}
@@ -51,12 +51,13 @@ class HomeTimelineSettingsModal extends ImmutablePureComponent {
}
render() {
const { intl, settings, onChange } = this.props
const { intl, settings, onChange, onClose } = this.props
return (
<ModalLayout
width='320'
title={intl.formatMessage(messages.title)}
onClose={onClose}
>
<div className={[_s.default, _s.pb10].join(' ')}>

View File

@@ -42,13 +42,17 @@ class HotkeysModal extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
onClose: PropTypes.func.isRequired,
}
render() {
const { intl } = this.props
const { intl, onClose } = this.props
return (
<ModalLayout title={intl.formatMessage(messages.heading)}>
<ModalLayout
title={intl.formatMessage(messages.heading)}
onClose={onClose}
>
<div className={[_s.default, _s.flexRow].join(' ')}>
<table>
<thead>

View File

@@ -13,15 +13,17 @@ class ListCreateModal extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
onClose: PropTypes.func.isRequired,
}
render() {
const { intl } = this.props
const { intl, onClose } = this.props
return (
<ModalLayout
title={intl.formatMessage(messages.title)}
width='500'
onClose={onClose}
>
<ListCreate />
</ModalLayout>

View File

@@ -33,7 +33,7 @@ class ListDeleteModal extends PureComponent {
}
render() {
const { list, intl } = this.props
const { list, intl, onClose } = this.props
const title = intl.formatMessage(messages.title, {
list: !!list ? account.get('title') : '',
@@ -48,6 +48,7 @@ class ListDeleteModal extends PureComponent {
message={message}
confirm={intl.formatMessage(messages.delete)}
onConfirm={this.handleClick}
onClose={onClose}
/>
)
}

View File

@@ -1,7 +1,6 @@
import { defineMessages, injectIntl } from 'react-intl'
import ImmutablePureComponent from 'react-immutable-pure-component'
import ImmutablePropTypes from 'react-immutable-proptypes'
import { closeModal } from '../../actions/modal'
import { changeSetting, saveSettings } from '../../actions/settings'
import ModalLayout from './modal_layout'
import Button from '../button'
@@ -22,14 +21,14 @@ const mapStateToProps = state => ({
settings: state.getIn(['settings', 'list']),
})
const mapDispatchToProps = dispatch => {
const mapDispatchToProps = (dispatch, { onClose }) => {
return {
onChange(key, checked) {
dispatch(changeSetting(['list', ...key], checked))
},
onSave() {
dispatch(saveSettings())
dispatch(closeModal())
onClose()
},
}
}
@@ -43,6 +42,7 @@ class ListTimelineSettingsModal extends ImmutablePureComponent {
intl: PropTypes.object.isRequired,
settings: ImmutablePropTypes.map.isRequired,
onChange: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
onSave: PropTypes.func.isRequired,
}
@@ -51,12 +51,13 @@ class ListTimelineSettingsModal extends ImmutablePureComponent {
}
render() {
const { intl, settings, onChange } = this.props
const { intl, settings, onChange, onClose } = this.props
return (
<ModalLayout
width='320'
title={intl.formatMessage(messages.title)}
onClose={onClose}
>
<div className={[_s.default, _s.pb10].join(' ')}>

View File

@@ -54,9 +54,11 @@ class ModalBase extends PureComponent {
}
}
handleOnClose = () => {
handleOnClose = (e) => {
const { onOpenModal, composeText, composeId, onClose, intl, type, onCancelReplyCompose } = this.props
if (this.dialog !== e.target) return
if (!composeId && composeText && type == 'COMPOSE') {
onOpenModal('CONFIRM', {
message: intl.formatMessage(messages.delete),
@@ -108,8 +110,12 @@ class ModalBase extends PureComponent {
return Array(...this.node.parentElement.childNodes).filter(node => node !== this.node)
}
setRef = ref => {
this.node = ref
setRef = (n) => {
this.node = n
}
setDialog = (n) => {
this.dialog = n
}
render () {
@@ -133,10 +139,11 @@ class ModalBase extends PureComponent {
<div
role='presentation'
className={[_s.default, _s.backgroundColorOpaque, _s.positionFixed, _s.z3, _s.top0, _s.right0, _s.bottom0, _s.left0].join(' ')}
onClick={this.handleOnClose}
/>
<div
ref={this.setDialog}
role='dialog'
onClick={this.handleOnClose}
className={[_s.default, _s.positionFixed, _s.alignItemsCenter, _s.justifyContentCenter, _s.z4, _s.width100PC, _s.height100PC, _s.top0, _s.rightAuto, _s.bottomAuto, _s.left0].join(' ')}
>
{children}

View File

@@ -1,6 +1,5 @@
import { defineMessages, injectIntl } from 'react-intl'
import classNames from 'classnames/bind'
import { closeModal } from '../../actions/modal'
import Button from '../button'
import Block from '../block'
import Heading from '../heading'
@@ -11,16 +10,7 @@ const messages = defineMessages({
close: { id: 'lightbox.close', defaultMessage: 'Close' },
})
const mapDispatchToProps = dispatch => {
return {
handleCloseModal() {
dispatch(closeModal())
},
}
}
export default
@connect(null, mapDispatchToProps)
@injectIntl
class ModalLayout extends PureComponent {
static propTypes = {
@@ -38,11 +28,7 @@ class ModalLayout extends PureComponent {
}
onHandleCloseModal = () => {
if (this.props.onClose) {
this.props.onClose();
} else {
this.props.handleCloseModal()
}
this.props.onClose()
}
render() {

View File

@@ -114,8 +114,7 @@ class ModalRoot extends PureComponent {
}
onClickClose = () => {
const { onClose, type } = this.props
onClose(type)
this.props.onClose(this.props.type)
}
render() {

View File

@@ -34,6 +34,7 @@ class MuteModal extends PureComponent {
account: PropTypes.object.isRequired,
onConfirm: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
onClose: PropTypes.func.isRequired,
}
handleClick = () => {
@@ -41,7 +42,7 @@ class MuteModal extends PureComponent {
}
render() {
const { account, intl } = this.props
const { account, intl, onClose } = this.props
const title = intl.formatMessage(messages.title, {
name: !!account ? account.get('acct') : '',
@@ -56,6 +57,7 @@ class MuteModal extends PureComponent {
message={message}
confirm={intl.formatMessage(messages.mute)}
onConfirm={this.handleClick}
onClose={onClose}
/>
)
}

View File

@@ -16,13 +16,18 @@ class ProUpgradeModal extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
onClose: PropTypes.func.isRequired,
}
render() {
const { intl } = this.props
const { intl, onClose } = this.props
return (
<ModalLayout title={intl.formatMessage(messages.title)} width='460'>
<ModalLayout
title={intl.formatMessage(messages.title)}
width='460'
onClose={onClose}
>
<Text>
{intl.formatMessage(messages.text)}
</Text>

View File

@@ -20,13 +20,13 @@ const messages = defineMessages({
forwardHint: { id: 'report.forward_hint', defaultMessage: 'The account is from another server. Send an anonymized copy of the report there as well?' },
forward: { id: 'report.forward', defaultMessage: 'Forward to {target}' },
target: { id: 'report.target', defaultMessage: 'Report {target}' },
});
})
const makeMapStateToProps = () => {
const getAccount = makeGetAccount();
const getAccount = makeGetAccount()
const mapStateToProps = state => {
const accountId = state.getIn(['reports', 'new', 'account_id']);
const accountId = state.getIn(['reports', 'new', 'account_id'])
return {
isSubmitting: state.getIn(['reports', 'new', 'isSubmitting']),
@@ -34,11 +34,11 @@ const makeMapStateToProps = () => {
comment: state.getIn(['reports', 'new', 'comment']),
forward: state.getIn(['reports', 'new', 'forward']),
statusIds: OrderedSet(state.getIn(['timelines', `account:${accountId}:with_replies`, 'items'])).union(state.getIn(['reports', 'new', 'status_ids'])),
};
};
}
}
return mapStateToProps;
};
return mapStateToProps
}
export default
@connect(makeMapStateToProps)
@@ -53,33 +53,34 @@ class ReportModal extends ImmutablePureComponent {
forward: PropTypes.bool,
dispatch: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
};
onClose: PropTypes.func.isRequired,
}
handleCommentChange = e => {
this.props.dispatch(changeReportComment(e.target.value));
this.props.dispatch(changeReportComment(e.target.value))
}
handleForwardChange = e => {
this.props.dispatch(changeReportForward(e.target.checked));
this.props.dispatch(changeReportForward(e.target.checked))
}
handleSubmit = () => {
this.props.dispatch(submitReport());
this.props.dispatch(submitReport())
}
handleKeyDown = e => {
if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) {
this.handleSubmit();
this.handleSubmit()
}
}
componentDidMount () {
this.props.dispatch(expandAccountTimeline(this.props.account.get('id'), { withReplies: true }));
this.props.dispatch(expandAccountTimeline(this.props.account.get('id'), { withReplies: true }))
}
componentWillReceiveProps (nextProps) {
if (this.props.account !== nextProps.account && nextProps.account) {
this.props.dispatch(expandAccountTimeline(nextProps.account.get('id'), { withReplies: true }));
this.props.dispatch(expandAccountTimeline(nextProps.account.get('id'), { withReplies: true }))
}
}
@@ -96,7 +97,7 @@ class ReportModal extends ImmutablePureComponent {
if (!account) return null
const domain = account.get('acct').split('@')[1];
const domain = account.get('acct').split('@')[1]
return (
<ModalLayout
@@ -104,6 +105,7 @@ class ReportModal extends ImmutablePureComponent {
title={intl.formatMessage(messages.target, {
target: account.get('acct')
})}
onClose={onClose}
>
<div className={[_s.default, _s.flexRow].join(' ')}>
@@ -168,7 +170,7 @@ class ReportModal extends ImmutablePureComponent {
</div>
</div>
</ModalLayout>
);
)
}
}

View File

@@ -39,6 +39,7 @@ class StatusRevisionsModal extends ImmutablePureComponent {
loading: PropTypes.bool.isRequired,
error: PropTypes.bool,
revisions: ImmutablePropTypes.list.isRequired,
onClose: PropTypes.func.isRequired,
}
componentDidMount() {
@@ -49,14 +50,16 @@ class StatusRevisionsModal extends ImmutablePureComponent {
const {
intl,
status,
revisions
revisions,
onClose
} = this.props
console.log("revisions:", revisions)
console.log("revisions.size:", revisions.size)
return (
<ModalLayout title={intl.formatMessage(messages.title)} width='480'>
<ModalLayout
title={intl.formatMessage(messages.title)}
width='480'
onClose={onClose}
>
<div className={[_s.default]}>
<ScrollableList>
{

View File

@@ -19,13 +19,17 @@ class UnauthorizedModal extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
onClose: PropTypes.func.isRequired,
}
render() {
const { intl } = this.props
return (
<ModalLayout title={intl.formatMessage(messages.signup)}>
<ModalLayout
title={intl.formatMessage(messages.signup)}
onClose={onClose}
>
<div className={[_s.default, _s.px10, _s.py10].join(' ')}>
<Text className={_s.mb15}>
{intl.formatMessage(messages.text)}

View File

@@ -31,6 +31,7 @@ class UnfollowModal extends PureComponent {
isSubmitting: PropTypes.bool.isRequired,
account: PropTypes.object.isRequired,
onConfirm: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
intl: PropTypes.object.isRequired,
}
@@ -61,6 +62,7 @@ class UnfollowModal extends PureComponent {
title={`Mute @${account.get('acct')}`}
message={<FormattedMessage id='confirmations.mute.message' defaultMessage='Are you sure you want to mute @{name}?' values={{ name: account.get('acct') }} />}
confirm={<FormattedMessage id='mute' defaultMessage='Mute' />}
onClose={onClose}
onConfirm={() => {
// dispatch(blockDomain(domain))
// dispatch(blockDomain(domain))

View File

@@ -37,13 +37,13 @@ class MediaGalleryPanel extends ImmutablePureComponent {
const { accountId } = this.props
if (accountId) {
this.props.dispatch(expandAccountMediaTimeline(accountId, {limit: 8}))
this.props.dispatch(expandAccountMediaTimeline(accountId, { limit: 8 }))
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.accountId && nextProps.accountId !== this.props.accountId) {
this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId, {limit: 8}))
this.props.dispatch(expandAccountMediaTimeline(nextProps.accountId, { limit: 8 }))
}
}

View File

@@ -1,33 +1,59 @@
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 PanelLayout from './panel_layout'
import Switch from '../switch'
import SettingSwitch from '../setting_switch'
const messages = defineMessages({
title: { id: 'notification_filters', defaultMessage: 'Notification Filters' },
onlyVerified: { id: 'notification_only_verified', defaultMessage: 'Only Verified Users' },
onlyFollowing: { id: 'notification_only_following', defaultMessage: 'Only People I Follow' },
})
const mapStateToProps = state => ({
settings: state.getIn(['settings', 'notifications']),
})
const mapDispatchToProps = (dispatch) => {
return {
onChange(key, checked) {
dispatch(changeSetting(['notifications', ...key], checked))
dispatch(saveSettings())
},
}
}
export default
@injectIntl
@connect(mapStateToProps, mapDispatchToProps)
class NotificationFilterPanel extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
onChange: PropTypes.func.isRequired,
settings: ImmutablePropTypes.map.isRequired,
}
render() {
const { intl } = this.props
const { intl, onChange, settings } = this.props
return (
<PanelLayout title={intl.formatMessage(messages.title)}>
<Switch
id='notifications-verified'
label='Only Verified Users'
<SettingSwitch
prefix='notification'
settings={settings}
settingPath={['quickFilter', 'onlyVerifed']}
onChange={onChange}
label={intl.formatMessage(messages.onlyVerified)}
/>
<Switch
id='notifications-verified'
label='Only People I Follow'
<SettingSwitch
prefix='notification'
settings={settings}
settingPath={['quickFilter', 'onlyFollowing']}
onChange={onChange}
label={intl.formatMessage(messages.onlyFollowing)}
/>
</PanelLayout>
)

View File

@@ -7,7 +7,7 @@ import ColumnIndicator from '../column_indicator'
import TrendingItem from '../trends_item'
const messages = defineMessages({
title: { id:'trends.title', defaultMessage: 'Trending right now' },
title: { id: 'trends.title', defaultMessage: 'Trending right now' },
})
const mapStateToProps = state => ({
@@ -31,7 +31,7 @@ class TrendsPanel extends ImmutablePureComponent {
onFetchGabTrends: PropTypes.func.isRequired,
}
componentWillMount () {
componentWillMount() {
this.props.onFetchGabTrends()
}
@@ -52,7 +52,7 @@ class TrendsPanel extends ImmutablePureComponent {
gabtrends && gabtrends.slice(0, 8).map((trend, i) => (
<TrendingItem
key={`gab-trend-${i}`}
index={i+1}
index={i + 1}
isLast={i === 7}
url={trend.get('url')}
title={trend.get('title')}

View File

@@ -4,13 +4,18 @@ export default class PopoverLayout extends PureComponent {
static propTypes = {
children: PropTypes.node,
className: PropTypes.string,
width: PropTypes.number,
}
static defaultProps = {
width: 250,
}
render() {
const { children, className } = this.props
const { children, className, width } = this.props
return (
<div className={className}>
<div className={className} style={{width: `${width}px`}}>
<Block>
{children}
</Block>

View File

@@ -310,7 +310,7 @@ class ProfileOptionsPopover extends PureComponent {
<List
scrollKey='profile_options'
items={listItems}
small
size='large'
/>
</PopoverLayout>
)

View File

@@ -6,6 +6,7 @@ export default class SidebarMorePopover extends PureComponent {
return (
<PopoverLayout className={_s.width240PX}>
<List
size='large'
scrollKey='profile_options'
items={[
{
@@ -21,7 +22,6 @@ export default class SidebarMorePopover extends PureComponent {
href: '/auth/log_out',
},
]}
small
/>
</PopoverLayout>
)

View File

@@ -142,9 +142,9 @@ class StatusOptionsPopover extends ImmutablePureComponent {
return (
<PopoverLayout className={_s.width240PX}>
<List
size='large'
scrollKey='profile_options'
items={items}
small
/>
</PopoverLayout>
)

View File

@@ -24,6 +24,8 @@ const messages = defineMessages({
// });
// : todo :
export default
@injectIntl
// @connect(makeMapStateToProps, mapDispatchToProps)
@@ -60,8 +62,9 @@ class StatusSharePopover extends ImmutablePureComponent {
const { intl } = this.props
return (
<PopoverLayout className={_s.width250PX}>
<PopoverLayout width={220}>
<List
size='large'
scrollKey='status_share_options'
items={[
{
@@ -71,13 +74,13 @@ class StatusSharePopover extends ImmutablePureComponent {
onClick: this.handleCopy,
},
{
icon: 'envelope',
icon: 'email',
hideArrow: true,
title: intl.formatMessage(messages.email),
href: 'mailto:',
},
{
icon: 'embed',
icon: 'code',
hideArrow: true,
title: intl.formatMessage(messages.embed),
onClick: this.handleEmbed,

View File

@@ -58,13 +58,13 @@ class StatusVisibilityDropdown extends PureComponent {
subtitle: intl.formatMessage(messages.public_long)
},
{
icon: 'unlock',
icon: 'unlock-filled',
value: 'unlisted',
title: intl.formatMessage(messages.unlisted_short),
subtitle: intl.formatMessage(messages.unlisted_long)
},
{
icon: 'lock',
icon: 'lock-filled',
value: 'private',
title: intl.formatMessage(messages.private_short),
subtitle: intl.formatMessage(messages.private_long)

View File

@@ -14,11 +14,12 @@ import { initReport } from '../actions/reports'
import { openModal } from '../actions/modal'
import { unfollowModal, me } from '../initial_state'
import Avatar from './avatar'
import Image from './image'
import Text from './text'
import Button from './button'
import DisplayName from './display_name'
import Icon from './icon'
import Image from './image'
import TabBar from './tab_bar'
import Text from './text'
const cx = classNames.bind(_s)
@@ -240,6 +241,7 @@ class ProfileHeader extends ImmutablePureComponent {
}
console.log("buttonOptions:", buttonText, buttonOptions)
console.log("account: ", account)
// : todo : "follows you", "mutual follow"
@@ -264,8 +266,12 @@ class ProfileHeader extends ImmutablePureComponent {
<Avatar size={avatarSize} account={account} />
</div>
<div className={[_s.default, _s.px15, _s.py10].join(' ')}>
<div className={[_s.default, _s.flexRow, _s.px15, _s.py10].join(' ')}>
<DisplayName account={account} multiline large />
{
account && account.get('locked') &&
<Icon id='lock-filled' height='14px' width='14px' className={[_s.mt10, _s.ml10].join(' ')} />
}
</div>
</div>

View File

@@ -37,7 +37,7 @@ const mapStateToProps = state => {
return {
account: getAccount(state, me),
sidebarOpen: state.get('sidebar').sidebarOpen,
moreOpen: state.get('popover').popoverType === 'SIDEBAR_MORE',
notificationCount: state.getIn(['notifications', 'unread']),
homeItemsQueueCount: state.getIn(['timelines', 'home', 'totalQueuedItemsCount']),
showCommunityTimeline: state.getIn(['settings', 'community', 'shows', 'inSidebar']),
@@ -64,8 +64,8 @@ class Sidebar extends ImmutablePureComponent {
static propTypes = {
intl: PropTypes.object.isRequired,
account: ImmutablePropTypes.map,
sidebarOpen: PropTypes.bool,
showCommunityTimeline: PropTypes.bool,
moreOpen: PropTypes.bool,
onClose: PropTypes.func.isRequired,
onOpenComposeModal: PropTypes.func.isRequired,
openSidebarMorePopover: PropTypes.func.isRequired,
@@ -73,39 +73,11 @@ class Sidebar extends ImmutablePureComponent {
homeItemsQueueCount: PropTypes.number.isRequired,
}
state = {
moreOpen: false,
}
componentDidUpdate() {
if (!me) return
if (this.props.sidebarOpen) {
document.body.classList.add('with-modals--active')
} else {
document.body.classList.remove('with-modals--active')
}
}
toggleMore = () => {
this.setState({
moreOpen: !this.state.moreOpen
})
}
handleSidebarClose = () => {
this.props.onClose()
this.setState({
moreOpen: false,
})
}
handleOpenComposeModal = () => {
this.props.onOpenComposeModal()
}
handleOpenSidebarMorePopover =() => {
console.log("handleOpenSidebarMorePopover")
this.props.openSidebarMorePopover({
targetRef: this.moreBtnRef,
position: 'top',
@@ -118,14 +90,13 @@ class Sidebar extends ImmutablePureComponent {
render() {
const {
sidebarOpen,
intl,
account,
notificationCount,
homeItemsQueueCount,
showCommunityTimeline
showCommunityTimeline,
moreOpen
} = this.props
const { moreOpen } = this.state
// : todo :
if (!me || !account) return null
@@ -133,9 +104,6 @@ class Sidebar extends ImmutablePureComponent {
const acct = account.get('acct')
const isPro = account.get('is_pro')
const moreIcon = moreOpen ? 'minus' : 'plus'
const moreContainerStyle = { display: moreOpen ? 'block' : 'none' }
console.log("showCommunityTimeline:", showCommunityTimeline)
const menuItems = [
@@ -182,7 +150,8 @@ class Sidebar extends ImmutablePureComponent {
title: 'More',
icon: 'more',
onClick: this.handleOpenSidebarMorePopover,
buttonRef: this.setMoreButtonRef
buttonRef: this.setMoreButtonRef,
active: moreOpen,
},
]
@@ -243,7 +212,7 @@ class Sidebar extends ImmutablePureComponent {
)
})
}
<SidebarSectionTitle>Shortcuts</SidebarSectionTitle>
{ /* <SidebarSectionTitle>Shortcuts</SidebarSectionTitle> */ }
{
shortcutItems.map((shortcutItem, i) => (
<SidebarSectionItem {...shortcutItem} key={`sidebar-item-shortcut-${i}`} />

View File

@@ -28,16 +28,15 @@ class SidebarHeader extends ImmutablePureComponent {
const { account } = this.props
const isPro = account.get('is_pro')
const gabLogoClasses = isPro ? _s.fillColorGabPro : _s.fillColorBrand
return (
<Fragment>
<h1 className={[_s.default].join(' ')}>
<NavLink to='/' aria-label='Gab' className={[_s.default, _s.flexRow, _s.noSelect, _s.noUnderline, _s.height50PX, _s.cursorPointer, _s.px10].join(' ')}>
<Icon id='gab-logo' className={gabLogoClasses} />
<Icon id='gab-logo' className={_s.fillColorBrand} />
{
isPro &&
<Text weight='bold' color='pro' size='extraSmall' className={[_s.pb5].join(' ')}>
<Text weight='bold' color='brand' size='extraSmall' className={[_s.pb5].join(' ')}>
PRO
</Text>
}

View File

@@ -77,6 +77,7 @@ export default class SidebarSectionItem extends PureComponent {
fontSize15PX: 1,
text: 1,
textOverflowEllipsis: 1,
outlineNone: 1,
colorSecondary: !hovering && !active && !me && !shouldShowActive,
colorPrimary: shouldShowActive || me,
})

View File

@@ -144,17 +144,8 @@ class StatusActionBar extends ImmutablePureComponent {
const publicStatus = ['public', 'unlisted'].includes(status.get('visibility'))
const replyCount = status.get('replies_count')
const replyIcon = (status.get('in_reply_to_id', null) === null) ? 'reply' : 'reply-all'
const replyTitle = (status.get('in_reply_to_id', null) === null) ? formatMessage(messages.reply) : formatMessage(messages.replyAll)
const repostCount = status.get('reblogs_count')
const repostTitle = !publicStatus ? formatMessage(messages.cannot_repost) : formatMessage(messages.repost)
const favoriteCount = status.get('favourites_count') // : todo :
const shareButton = ('share' in navigator) && status.get('visibility') === 'public' && (
<Button className='status-action-bar-button' title={formatMessage(messages.share)} icon='share-alt' onClick={this.handleShareClick} />
)
const favoriteCount = status.get('favourites_count')
const hasInteractions = favoriteCount > 0 || replyCount > 0 || repostCount > 0
const shouldCondense = (
@@ -240,8 +231,9 @@ class StatusActionBar extends ImmutablePureComponent {
onClick={this.handleReplyClick}
/>
<StatusActionBarItem
title={repostTitle}
icon={(status.get('visibility') === 'private') ? 'lock' : 'repost'}
title={formatMessage(messages.repost)}
altTitle={!publicStatus ? formatMessage(messages.cannot_repost) : ''}
icon={!publicStatus ? 'lock' : 'repost'}
disabled={!publicStatus}
active={!!status.get('reblogged')}
onClick={this.handleRepostClick}

View File

@@ -8,6 +8,7 @@ const cx = classNames.bind(_s)
export default class StatusActionBarItem extends PureComponent {
static propTypes = {
title: PropTypes.string.isRequired,
altTitle: PropTypes.string,
onClick: PropTypes.func.isRequired,
icon: PropTypes.string.isRequired,
active: PropTypes.bool,
@@ -22,14 +23,15 @@ export default class StatusActionBarItem extends PureComponent {
icon,
active,
disabled,
buttonRef
buttonRef,
altTitle
} = this.props
const btnClasses = cx({
justifyContentCenter: 1,
alignItemsCenter: 1,
px10: 1,
backgroundSubtle_onHover: 1,
backgroundSubtle_onHover: !disabled,
})
const color = active ? 'brand' : 'secondary'
@@ -41,6 +43,7 @@ export default class StatusActionBarItem extends PureComponent {
block
radiusSmall
backgroundColor='none'
title={altTitle}
color={color}
buttonRef={buttonRef}
className={btnClasses}

View File

@@ -138,6 +138,7 @@ class StatusHeader extends ImmutablePureComponent {
})
const avatarSize = reduced ? 20 : 46
const visibilityIcon = 'globe'
return (
<div className={containerClasses}>
@@ -197,7 +198,7 @@ class StatusHeader extends ImmutablePureComponent {
<DotTextSeperator />
<Icon id='globe' width='12px' height='12px' className={[_s.default, _s.displayInline, _s.ml5, _s.fillColorSecondary].join(' ')} />
<Icon id={visibilityIcon} width='12px' height='12px' className={[_s.default, _s.displayInline, _s.ml5, _s.fillColorSecondary].join(' ')} />
{
!!status.get('group') &&

View File

@@ -20,17 +20,15 @@ class TabBarItem extends PureComponent {
}
state = {
active: -1,
isCurrent: -1,
}
componentDidUpdate(prevProps) {
if (this.props.location !== prevProps.location) {
const isCurrent = this.props.to === this.props.location.pathname
if (this.state.active !== isCurrent) {
this.setState({
active: isCurrent,
})
if (this.state.isCurrent !== isCurrent) {
this.setState({ isCurrent })
}
}
}
@@ -43,11 +41,11 @@ class TabBarItem extends PureComponent {
location,
large,
icon,
// active
active
} = this.props
const { active } = this.state
const { isCurrent } = this.state
const isCurrent = active === -1 ? to === location.pathname : active
const isActive = active || (isCurrent === -1 ? to === location.pathname : false)
const containerClasses = cx({
default: 1,
@@ -61,8 +59,8 @@ class TabBarItem extends PureComponent {
py5: 1,
cursorPointer: 1,
backgroundTransparent: 1,
borderColorTransparent: !isCurrent,
borderColorBrand: isCurrent,
borderColorTransparent: !isActive,
borderColorBrand: isActive,
mr5: large,
})
@@ -74,13 +72,13 @@ class TabBarItem extends PureComponent {
radiusSmall: 1,
px10: !large,
px15: large,
backgroundSubtle2Dark_onHover: !isCurrent,
backgroundSubtle2Dark_onHover: !isActive,
})
const textOptions = {
size: !!large ? 'normal' : 'small',
color: isCurrent ? 'brand' : large ? 'secondary' : 'primary',
weight: isCurrent ? 'bold' : large ? 'medium' : 'normal',
color: isActive ? 'brand' : large ? 'secondary' : 'primary',
weight: isActive ? 'bold' : large ? 'medium' : 'normal',
}
const iconOptions = {
@@ -92,8 +90,8 @@ class TabBarItem extends PureComponent {
return (
<Button
onClick={onClick}
to={to}
className={containerClasses}
to={to || undefined}
noClasses
>
<span className={textParentClasses}>

View File

@@ -18,6 +18,13 @@ export default class TrendingItem extends PureComponent {
author: PropTypes.string,
publishDate: PropTypes.string,
isLast: PropTypes.bool,
wide: PropTypes.bool,
}
static defaultProps = {
title: '',
description: '',
author: '',
}
state = {
@@ -41,7 +48,8 @@ export default class TrendingItem extends PureComponent {
imageUrl,
author,
publishDate,
isLast
isLast,
wide
} = this.props
const { hovering } = this.state
@@ -62,23 +70,31 @@ export default class TrendingItem extends PureComponent {
})
const correctedAuthor = author.replace('www.', '')
const correctedDescription = description.length > 120 ? `${description.substring(0, 120)}...` : description
const correctedDescription = description.length > 120 ? `${description.substring(0, 120).trim()}...` : description
const image = (
<Image
nullable
width='116px'
height='78px'
src={imageUrl}
className={[_s.radiusSmall, _s.overflowHidden, _s.mb10].join(' ')}
/>
)
return (
<Button
noClasses
href={url}
target='_blank'
className={containerClasses}
onMouseEnter={() => this.handleOnMouseEnter()}
onMouseLeave={() => this.handleOnMouseLeave()}
>
<Image
nullable
width='116px'
height='78px'
src={imageUrl}
className={[_s.radiusSmall, _s.overflowHidden, _s.mb10].join(' ')}
/>
{
!wide && image
}
<div className={[_s.default, _s.flexNormal, _s.pb5].join(' ')}>
<div className={_s.default}>
<Text size='medium' color='primary' weight='bold'>
@@ -86,11 +102,14 @@ export default class TrendingItem extends PureComponent {
</Text>
</div>
<div className={[_s.default, _s.heightMax56PX, _s.overflowHidden, _s.py5].join(' ')}>
<Text size='small' color='secondary'>
{correctedDescription}
</Text>
</div>
{
!!correctedDescription &&
<div className={[_s.default, _s.heightMax60PX, _s.overflowHidden, _s.py5].join(' ')}>
<Text size='small' color='secondary'>
{correctedDescription}
</Text>
</div>
}
<div className={[_s.default, _s.flexRow].join(' ')}>
<Text color='secondary' size='small'>
{index}
@@ -103,8 +122,10 @@ export default class TrendingItem extends PureComponent {
<Text color='secondary' size='small' className={subtitleClasses}>
<RelativeTimestamp timestamp={publishDate} />
</Text>
<DotTextSeperator />
<Text color='secondary' size='small' className={_s.ml5}></Text>
{
hovering &&
<Text color='secondary' size='small' className={_s.ml10}></Text>
}
</div>
</div>
</Button>