Progress
This commit is contained in:
@@ -1,41 +0,0 @@
|
||||
import { length } from 'stringz'
|
||||
|
||||
export default class CharacterCounter extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
text: PropTypes.string.isRequired,
|
||||
max: PropTypes.number.isRequired,
|
||||
small: PropTypes.bool,
|
||||
}
|
||||
|
||||
render () {
|
||||
const { text, max, small } = this.props
|
||||
const actualRadius = small ? '10' : '16'
|
||||
const radius = small ? 8 : 12
|
||||
const circumference = 2 * Math.PI * radius
|
||||
const diff = length(text) / max
|
||||
const dashoffset = circumference * (1 - diff)
|
||||
|
||||
return (
|
||||
<div className={[_s.default, _s.mr10, _s.justifyContentCenter, _s.alignItemsCenter].join(' ')}>
|
||||
<svg width={actualRadius * 2} height={actualRadius * 2} viewBox={`0 0 ${actualRadius * 2} ${actualRadius * 2}`}>
|
||||
<circle fill='none' cx={actualRadius} cy={actualRadius} r={radius} fill="none" stroke="#e6e6e6" strokeWidth="2" />
|
||||
<circle style={{
|
||||
// transform: 'rotate(-90deg)',
|
||||
strokeDashoffset: dashoffset,
|
||||
strokeDasharray: circumference,
|
||||
}}
|
||||
fill='none'
|
||||
cx={actualRadius}
|
||||
cy={actualRadius}
|
||||
r={radius}
|
||||
strokeWidth="2"
|
||||
strokeLinecap='round'
|
||||
stroke='#21cf7a'
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,19 +3,19 @@ import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import { length } from 'stringz'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import classNames from 'classnames/bind'
|
||||
import CharacterCounter from '../character_counter'
|
||||
import CharacterCounter from '../../../../components/character_counter'
|
||||
import UploadForm from '../upload_form'
|
||||
import ReplyIndicatorContainer from '../../containers/reply_indicator_container'
|
||||
import AutosuggestTextbox from '../../../../components/autosuggest_textbox'
|
||||
import PollButton from '../../components/poll_button'
|
||||
import UploadButton from '../../components/upload_button'
|
||||
import UploadButton from '../media_upload_button'
|
||||
import SpoilerButton from '../../components/spoiler_button'
|
||||
import RichTextEditorButton from '../../components/rich_text_editor_button'
|
||||
import GifSelectorButton from '../../components/gif_selector_button'
|
||||
import StatusVisibilityButton from '../../components/status_visibility_button'
|
||||
import EmojiPickerButton from '../../components/emoji_picker_button'
|
||||
import PollFormContainer from '../../containers/poll_form_container'
|
||||
import SchedulePostDropdown from '../../components/schedule_post_dropdown'
|
||||
import SchedulePostButton from '../schedule_post_button'
|
||||
import QuotedStatusPreviewContainer from '../../containers/quoted_status_preview_container'
|
||||
import Icon from '../../../../components/icon'
|
||||
import Button from '../../../../components/button'
|
||||
@@ -347,11 +347,13 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
<StatusVisibilityButton small={shouldCondense} />
|
||||
}
|
||||
<SpoilerButton small={shouldCondense} />
|
||||
<SchedulePostDropdown small={shouldCondense} position={isModalOpen ? 'top' : undefined} />
|
||||
<SchedulePostButton small={shouldCondense} />
|
||||
<GifSelectorButton small={shouldCondense} />
|
||||
<EmojiPickerButton small={shouldCondense} />
|
||||
</div>
|
||||
|
||||
<CharacterCounter max={maxPostCharacterCount} text={text} small={shouldCondense} />
|
||||
|
||||
{
|
||||
!shouldCondense &&
|
||||
<Button
|
||||
|
||||
@@ -42,7 +42,7 @@ class SpoilerButton extends PureComponent {
|
||||
return (
|
||||
<ComposeExtraButton
|
||||
title={intl.formatMessage(messages.title)}
|
||||
icon='letter-t'
|
||||
icon='rich-text'
|
||||
onClick={this.handleClick}
|
||||
small={small}
|
||||
active={active}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import { openModal } from '../../../actions/modal'
|
||||
import { openPopover } from '../../../actions/popover'
|
||||
import { me } from '../../../initial_state'
|
||||
import ComposeExtraButton from './compose_extra_button'
|
||||
|
||||
// import 'react-datepicker/dist/react-datepicker.css'
|
||||
|
||||
const messages = defineMessages({
|
||||
schedule_status: { id: 'schedule_status.title', defaultMessage: 'Schedule' },
|
||||
})
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
isPro: state.getIn(['accounts', me, 'is_pro']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
onOpenDatePickerPopover(targetRef) {
|
||||
dispatch(openPopover('DATE_PICKER', {
|
||||
targetRef,
|
||||
}))
|
||||
},
|
||||
|
||||
onOpenProUpgradeModal() {
|
||||
dispatch(openModal('PRO_UPGRADE'))
|
||||
},
|
||||
})
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
class SchedulePostDropdown extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
isPro: PropTypes.bool,
|
||||
onOpenProUpgradeModal: PropTypes.func.isRequired,
|
||||
onOpenDatePickerPopover: PropTypes.func.isRequired,
|
||||
small: PropTypes.bool,
|
||||
}
|
||||
|
||||
handleToggle = () => {
|
||||
if (!this.props.isPro) {
|
||||
this.props.onOpenProUpgradeModal()
|
||||
} else {
|
||||
this.props.onOpenDatePickerPopover(this.button)
|
||||
}
|
||||
}
|
||||
|
||||
setButton = (n) => {
|
||||
this.button = n
|
||||
}
|
||||
|
||||
render () {
|
||||
const { intl, small } = this.props
|
||||
|
||||
return (
|
||||
<ComposeExtraButton
|
||||
icon='calendar'
|
||||
title={intl.formatMessage(messages.schedule_status)}
|
||||
onClick={this.handleToggle}
|
||||
small={small}
|
||||
buttonRef={this.setButton}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
import { injectIntl, defineMessages } from 'react-intl'
|
||||
import DatePicker from 'react-datepicker'
|
||||
import { changeScheduledAt } from '../../../actions/compose'
|
||||
import { openModal } from '../../../actions/modal'
|
||||
import { me } from '../../../initial_state'
|
||||
import { isMobile } from '../../../utils/is_mobile'
|
||||
import ComposeExtraButton from './compose_extra_button'
|
||||
|
||||
// import 'react-datepicker/dist/react-datepicker.css'
|
||||
|
||||
const messages = defineMessages({
|
||||
schedule_status: { id: 'schedule_status.title', defaultMessage: 'Schedule' },
|
||||
})
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
date: state.getIn(['compose', 'scheduled_at']),
|
||||
isPro: state.getIn(['accounts', me, 'is_pro']),
|
||||
})
|
||||
|
||||
const mapDispatchToProps = dispatch => ({
|
||||
setScheduledAt (date) {
|
||||
dispatch(changeScheduledAt(date))
|
||||
},
|
||||
|
||||
onOpenProUpgradeModal() {
|
||||
dispatch(openModal('PRO_UPGRADE'))
|
||||
},
|
||||
})
|
||||
|
||||
class DatePickerWrapper extends PureComponent {
|
||||
static propTypes = {
|
||||
value: PropTypes.string,
|
||||
onClick: PropTypes.func,
|
||||
}
|
||||
|
||||
render() {
|
||||
const { value, onClick } = this.props
|
||||
|
||||
return (
|
||||
<button className='schedule-post-dropdown-wrapper' onClick={onClick}>
|
||||
{value}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
@connect(mapStateToProps, mapDispatchToProps)
|
||||
class SchedulePostDropdown extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
date: PropTypes.instanceOf(Date),
|
||||
setScheduledAt: PropTypes.func.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
isPro: PropTypes.bool,
|
||||
onOpenProUpgradeModal: PropTypes.func.isRequired,
|
||||
position: PropTypes.string,
|
||||
small: PropTypes.bool,
|
||||
}
|
||||
|
||||
handleToggle = () => {
|
||||
if (!this.props.isPro) {
|
||||
return this.props.onOpenProUpgradeModal()
|
||||
}
|
||||
|
||||
const { date } = this.props
|
||||
const value = date ? null : new Date()
|
||||
this.handleSetDate(value)
|
||||
}
|
||||
|
||||
handleSetDate = (date) => {
|
||||
this.props.setScheduledAt(date)
|
||||
}
|
||||
|
||||
render () {
|
||||
const { intl, date, isPro, position, small } = this.props
|
||||
|
||||
const open = !!date
|
||||
const datePickerDisabled = !isPro
|
||||
const withPortal = isMobile(window.innerWidth)
|
||||
const popperPlacement = position || undefined
|
||||
|
||||
return (
|
||||
<div className={[].join(' ')}>
|
||||
<div className={[].join(' ')}>
|
||||
<ComposeExtraButton
|
||||
icon='calendar'
|
||||
title={intl.formatMessage(messages.schedule_status)}
|
||||
onClick={this.handleToggle}
|
||||
small={small}
|
||||
/>
|
||||
</div>
|
||||
{
|
||||
open &&
|
||||
<DatePicker
|
||||
target={this}
|
||||
className='schedule-post-dropdown__datepicker'
|
||||
minDate={new Date()}
|
||||
selected={date}
|
||||
onChange={date => this.handleSetDate(date)}
|
||||
timeFormat='p'
|
||||
timeIntervals={15}
|
||||
timeCaption='Time'
|
||||
dateFormat='MMM d, yyyy h:mm aa'
|
||||
disabled={datePickerDisabled}
|
||||
showTimeSelect
|
||||
customInput={<DatePickerWrapper />}
|
||||
withPortal={withPortal}
|
||||
popperPlacement={popperPlacement}
|
||||
popperModifiers={{
|
||||
offset: {
|
||||
enabled: true,
|
||||
offset: '0px, 5px'
|
||||
},
|
||||
preventOverflow: {
|
||||
enabled: true,
|
||||
escapeWithReference: false,
|
||||
boundariesElement: 'viewport'
|
||||
}
|
||||
}}
|
||||
/>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ProgressBar from '../../../../components/progress_bar'
|
||||
import Upload from '../upload'
|
||||
import Upload from '../media_upload_item'
|
||||
import SensitiveMediaButton from '../sensitive_media_button'
|
||||
|
||||
const mapStateToProps = state => ({
|
||||
|
||||
Reference in New Issue
Block a user