Progress on Gab Deck, Updates on Compose
• Progress on Gab Deck, Updates on Compose
This commit is contained in:
@@ -0,0 +1,75 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import ImmutablePureComponent from 'react-immutable-pure-component'
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes'
|
||||
import { length } from 'stringz'
|
||||
import { isMobile } from '../../../utils/is_mobile'
|
||||
import { countableText } from '../../ui/util/counter'
|
||||
import {
|
||||
CX,
|
||||
MAX_POST_CHARACTER_COUNT,
|
||||
ALLOWED_AROUND_SHORT_CODE,
|
||||
BREAKPOINT_EXTRA_SMALL,
|
||||
BREAKPOINT_EXTRA_EXTRA_SMALL,
|
||||
BREAKPOINT_MEDIUM,
|
||||
} from '../../../constants'
|
||||
import AutosuggestTextbox from '../../../components/autosuggest_textbox'
|
||||
import Responsive from '../../ui/util/responsive_component'
|
||||
import ResponsiveClassesComponent from '../../ui/util/responsive_classes_component'
|
||||
import Avatar from '../../../components/avatar'
|
||||
import Button from '../../../components/button'
|
||||
import EmojiPickerButton from './emoji_picker_button'
|
||||
import PollButton from './poll_button'
|
||||
import PollForm from './poll_form'
|
||||
import SchedulePostButton from './schedule_post_button'
|
||||
import SpoilerButton from './spoiler_button'
|
||||
import ExpiresPostButton from './expires_post_button'
|
||||
import RichTextEditorButton from './rich_text_editor_button'
|
||||
import StatusContainer from '../../../containers/status_container'
|
||||
import StatusVisibilityButton from './status_visibility_button'
|
||||
import UploadButton from './media_upload_button'
|
||||
import UploadForm from './upload_form'
|
||||
import Input from '../../../components/input'
|
||||
import Text from '../../../components/text'
|
||||
import Icon from '../../../components/icon'
|
||||
import ComposeExtraButtonList from './compose_extra_button_list'
|
||||
|
||||
class ComposeDestinationHeader extends ImmutablePureComponent {
|
||||
|
||||
handleOnClick = () => {
|
||||
|
||||
}
|
||||
|
||||
render() {
|
||||
const { account } = this.props
|
||||
|
||||
const title = 'Post to timeline'
|
||||
|
||||
return (
|
||||
<div className={[_s.d, _s.flexRow, _s.aiCenter, _s.bgPrimary, _s.borderBottom1PX, _s.borderTop1PX, _s.borderColorSecondary, _s.mb5, _s.mt5, _s.px15, _s.w100PC, _s.h40PX].join(' ')}>
|
||||
<Avatar account={account} size={28} />
|
||||
<div className={[_s.ml15].join(' ')}>
|
||||
<Button
|
||||
isNarrow
|
||||
radiusSmall
|
||||
backgroundColor='tertiary'
|
||||
color='primary'
|
||||
onClick={this.handleOnClick}
|
||||
>
|
||||
<Text color='inherit' size='small' className={_s.jcCenter}>
|
||||
{title}
|
||||
<Icon id='caret-down' size='8px' className={_s.ml5} />
|
||||
</Text>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ComposeDestinationHeader.propTypes = {
|
||||
account: ImmutablePropTypes.map,
|
||||
}
|
||||
|
||||
export default ComposeDestinationHeader
|
||||
@@ -2,6 +2,7 @@ import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import { CX } from '../../../constants'
|
||||
import Button from '../../../components/button'
|
||||
import Text from '../../../components/text'
|
||||
|
||||
class ComposeExtraButton extends React.PureComponent {
|
||||
|
||||
@@ -12,11 +13,19 @@ class ComposeExtraButton extends React.PureComponent {
|
||||
onClick,
|
||||
icon,
|
||||
children,
|
||||
small,
|
||||
active,
|
||||
buttonRef
|
||||
buttonRef,
|
||||
isLast,
|
||||
small,
|
||||
} = this.props
|
||||
|
||||
const containerClasses = CX({
|
||||
d: 1,
|
||||
mr5: 1,
|
||||
jcCenter: 1,
|
||||
h40PX: 1,
|
||||
})
|
||||
|
||||
const btnClasses = CX({
|
||||
d: 1,
|
||||
circle: 1,
|
||||
@@ -26,45 +35,46 @@ class ComposeExtraButton extends React.PureComponent {
|
||||
textAlignCenter: 1,
|
||||
outlineNone: 1,
|
||||
bgTransparent: 1,
|
||||
flexRow: 1,
|
||||
bgSubtle_onHover: !active,
|
||||
bgBrandLight: active,
|
||||
py10: !small,
|
||||
px10: !small,
|
||||
py5: small,
|
||||
px5: small,
|
||||
mr2: !children,
|
||||
py10: 1,
|
||||
px10: 1,
|
||||
})
|
||||
|
||||
const iconClasses = CX({
|
||||
cSecondary: !active,
|
||||
cWhite: active,
|
||||
mr10: 1,
|
||||
py2: small,
|
||||
ml10: small,
|
||||
})
|
||||
|
||||
const iconSize = !!small ? '14px' : '16px'
|
||||
|
||||
const button = (
|
||||
<Button
|
||||
noClasses
|
||||
className={btnClasses}
|
||||
title={title}
|
||||
isDisabled={disabled}
|
||||
onClick={onClick}
|
||||
backgroundColor='none'
|
||||
iconClassName={iconClasses}
|
||||
icon={icon}
|
||||
iconSize={iconSize}
|
||||
buttonRef={!children ? buttonRef : undefined}
|
||||
/>
|
||||
)
|
||||
|
||||
if (!children) {
|
||||
return button
|
||||
}
|
||||
const iconSize = !small ? '18px' : '16px'
|
||||
const textColor = !active ? 'primary' : 'white'
|
||||
|
||||
return (
|
||||
<div className={[_s.d, _s.mr2].join(' ')} ref={buttonRef}>
|
||||
{button}
|
||||
{children}
|
||||
<div className={containerClasses} ref={buttonRef}>
|
||||
<Button
|
||||
noClasses
|
||||
className={btnClasses}
|
||||
title={title}
|
||||
isDisabled={disabled}
|
||||
onClick={onClick}
|
||||
backgroundColor='none'
|
||||
iconClassName={iconClasses}
|
||||
icon={icon}
|
||||
iconSize={iconSize}
|
||||
buttonRef={!children ? buttonRef : undefined}
|
||||
>
|
||||
{ children }
|
||||
{
|
||||
!small &&
|
||||
<Text color={textColor} weight='medium' className={[_s.pr5].join(' ')}>
|
||||
{title}
|
||||
</Text>
|
||||
}
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -76,9 +86,9 @@ ComposeExtraButton.propTypes = {
|
||||
disabled: PropTypes.bool,
|
||||
onClick: PropTypes.func,
|
||||
icon: PropTypes.string,
|
||||
small: PropTypes.bool,
|
||||
active: PropTypes.bool,
|
||||
buttonRef: PropTypes.func,
|
||||
small: PropTypes.bool,
|
||||
}
|
||||
|
||||
export default ComposeExtraButton
|
||||
@@ -0,0 +1,88 @@
|
||||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {
|
||||
CX,
|
||||
BREAKPOINT_EXTRA_SMALL,
|
||||
} from '../../../constants'
|
||||
import Responsive from '../../ui/util/responsive_component'
|
||||
import ResponsiveClassesComponent from '../../ui/util/responsive_classes_component'
|
||||
import EmojiPickerButton from './emoji_picker_button'
|
||||
import PollButton from './poll_button'
|
||||
import SchedulePostButton from './schedule_post_button'
|
||||
import SpoilerButton from './spoiler_button'
|
||||
import ExpiresPostButton from './expires_post_button'
|
||||
import RichTextEditorButton from './rich_text_editor_button'
|
||||
import StatusVisibilityButton from './status_visibility_button'
|
||||
import UploadButton from './media_upload_button'
|
||||
import { getWindowDimension } from '../../../utils/is_mobile'
|
||||
|
||||
const initialState = getWindowDimension()
|
||||
|
||||
class ComposeExtraButtonList extends React.PureComponent {
|
||||
|
||||
state = {
|
||||
height: initialState.height,
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
this.handleResize()
|
||||
window.addEventListener('keyup', this.handleKeyUp, false)
|
||||
window.addEventListener('resize', this.handleResize, false)
|
||||
}
|
||||
|
||||
handleResize = () => {
|
||||
const { height } = getWindowDimension()
|
||||
|
||||
this.setState({ height })
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
window.removeEventListener('keyup', this.handleKeyUp)
|
||||
window.removeEventListener('resize', this.handleResize, false)
|
||||
}
|
||||
|
||||
|
||||
render() {
|
||||
const { isMatch, edit, hidePro } = this.props
|
||||
const { height } = this.state
|
||||
|
||||
const small = height <= 660
|
||||
|
||||
const containerClasses = CX({
|
||||
d: 1,
|
||||
w100PC: 1,
|
||||
bgPrimary: 1,
|
||||
px15: 1,
|
||||
py10: 1,
|
||||
mtAuto: 1,
|
||||
boxShadowBlockY: 1,
|
||||
topLeftRadiusSmall: 1,
|
||||
borderColorSecondary: 1,
|
||||
topRightRadiusSmall: 1,
|
||||
flexRow: small,
|
||||
overflowXScroll: small,
|
||||
noScrollbar: small,
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={containerClasses}>
|
||||
<UploadButton small={small} />
|
||||
<EmojiPickerButton isMatch={isMatch} small={small} />
|
||||
{ !edit && <PollButton small={small} /> }
|
||||
<StatusVisibilityButton small={small} />
|
||||
<SpoilerButton small={small} />
|
||||
{ !hidePro && !edit && <SchedulePostButton small={small} /> }
|
||||
{ !hidePro && !edit && <ExpiresPostButton small={small} /> }
|
||||
{ !hidePro && <RichTextEditorButton small={small} /> }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
ComposeExtraButtonList.propTypes = {
|
||||
hidePro: PropTypes.bool,
|
||||
edit: PropTypes.bool,
|
||||
isMatch: PropTypes.bool,
|
||||
}
|
||||
|
||||
export default ComposeExtraButtonList
|
||||
@@ -11,13 +11,14 @@ import {
|
||||
MAX_POST_CHARACTER_COUNT,
|
||||
ALLOWED_AROUND_SHORT_CODE,
|
||||
BREAKPOINT_EXTRA_SMALL,
|
||||
BREAKPOINT_EXTRA_EXTRA_SMALL,
|
||||
BREAKPOINT_MEDIUM,
|
||||
} from '../../../constants'
|
||||
import AutosuggestTextbox from '../../../components/autosuggest_textbox'
|
||||
import Responsive from '../../ui/util/responsive_component'
|
||||
import ResponsiveClassesComponent from '../../ui/util/responsive_classes_component'
|
||||
import Avatar from '../../../components/avatar'
|
||||
import Button from '../../../components/button'
|
||||
import CharacterCounter from '../../../components/character_counter'
|
||||
import EmojiPickerButton from './emoji_picker_button'
|
||||
import PollButton from './poll_button'
|
||||
import PollForm from './poll_form'
|
||||
@@ -30,6 +31,10 @@ import StatusVisibilityButton from './status_visibility_button'
|
||||
import UploadButton from './media_upload_button'
|
||||
import UploadForm from './upload_form'
|
||||
import Input from '../../../components/input'
|
||||
import Text from '../../../components/text'
|
||||
import Icon from '../../../components/icon'
|
||||
import ComposeExtraButtonList from './compose_extra_button_list'
|
||||
import ComposeDestinationHeader from './compose_destination_header'
|
||||
|
||||
const messages = defineMessages({
|
||||
placeholder: { id: 'compose_form.placeholder', defaultMessage: "What's on your mind?" },
|
||||
@@ -193,11 +198,12 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
isSubmitting,
|
||||
isPro,
|
||||
hidePro,
|
||||
isStandalone,
|
||||
} = this.props
|
||||
|
||||
const disabled = isSubmitting
|
||||
const text = [this.props.spoilerText, countableText(this.props.text)].join('');
|
||||
const disabledButton = disabled || isUploading || isChangingUpload || length(text) > MAX_POST_CHARACTER_COUNT || (length(text) !== 0 && length(text.trim()) === 0 && !anyMedia);
|
||||
const disabledButton = isSubmitting || isUploading || isChangingUpload || length(text) > MAX_POST_CHARACTER_COUNT || (length(text.trim()) === 0 && !anyMedia)
|
||||
const shouldAutoFocus = autoFocus && !showSearch && !isMobile(window.innerWidth)
|
||||
|
||||
const parentContainerClasses = CX({
|
||||
@@ -238,220 +244,213 @@ class ComposeForm extends ImmutablePureComponent {
|
||||
displayNone: length(this.props.text) === 0,
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={[_s.d, _s.w100PC].join(' ')}>
|
||||
{
|
||||
shouldCondense &&
|
||||
<div className={parentContainerClasses}>
|
||||
<div className={[_s.d, _s.w100PC].join(' ')}>
|
||||
if (shouldCondense) {
|
||||
return (
|
||||
<div className={[_s.d, _s.w100PC].join(' ')}>
|
||||
<div className={[_s.d, _s.flexRow, _s.w100PC].join(' ')}>
|
||||
<div className={[_s.d, _s.mr10].join(' ')}>
|
||||
<Avatar account={account} size={28} noHover />
|
||||
</div>
|
||||
|
||||
<div className={[_s.d, _s.flexRow, _s.w100PC].join(' ')}>
|
||||
<div className={[_s.d, _s.mr10].join(' ')}>
|
||||
<Avatar account={account} size={28} noHover />
|
||||
</div>
|
||||
<div
|
||||
className={[_s.d, _s.flexWrap, _s.overflowHidden, _s.flex1, _s.minH28PX, _s.py2, _s.aiEnd, _s.flexRow, _s.radiusSmall, _s.bgSubtle, _s.px5].join(' ')}
|
||||
ref={this.setForm}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
|
||||
<div
|
||||
className={childContainerClasses}
|
||||
ref={this.setForm}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
<AutosuggestTextbox
|
||||
ref={(isModalOpen && shouldCondense) ? null : this.setAutosuggestTextarea}
|
||||
placeholder={intl.formatMessage(messages.commentPlaceholder)}
|
||||
disabled={disabled}
|
||||
value={this.props.text}
|
||||
onChange={this.handleChange}
|
||||
suggestions={this.props.suggestions}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
onFocus={this.handleComposeFocus}
|
||||
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
|
||||
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
|
||||
onSuggestionSelected={this.onSuggestionSelected}
|
||||
onPaste={onPaste}
|
||||
autoFocus={shouldAutoFocus}
|
||||
small={shouldCondense}
|
||||
isPro={isPro}
|
||||
isEdit={!!edit}
|
||||
id='comment-composer'
|
||||
/>
|
||||
|
||||
<AutosuggestTextbox
|
||||
ref={(isModalOpen && shouldCondense) ? null : this.setAutosuggestTextarea}
|
||||
placeholder={intl.formatMessage(messages.commentPlaceholder)}
|
||||
disabled={disabled}
|
||||
value={this.props.text}
|
||||
onChange={this.handleChange}
|
||||
suggestions={this.props.suggestions}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
onFocus={this.handleComposeFocus}
|
||||
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
|
||||
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
|
||||
onSuggestionSelected={this.onSuggestionSelected}
|
||||
onPaste={onPaste}
|
||||
autoFocus={shouldAutoFocus}
|
||||
small={shouldCondense}
|
||||
isPro={isPro}
|
||||
isEdit={!!edit}
|
||||
id='comment-composer'
|
||||
/>
|
||||
|
||||
<div className={actionsContainerClasses}>
|
||||
<div className={[_s.d, _s.flexRow, _s.mrAuto].join(' ')}>
|
||||
|
||||
{ /* <EmojiPickerButton small={shouldCondense} isMatch={isMatch} /> */}
|
||||
|
||||
{ /* <UploadButton small={shouldCondense} /> */}
|
||||
|
||||
<div className={commentPublishBtnClasses}>
|
||||
<Button
|
||||
isNarrow
|
||||
onClick={this.handleSubmit}
|
||||
isDisabled={disabledButton}
|
||||
className={_s.px10}
|
||||
>
|
||||
{intl.formatMessage(scheduledAt ? messages.schedulePost : messages.publish)}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div className={[_s.d, _s.flexRow, _s.aiStart, _s.mlAuto].join(' ')}>
|
||||
<div className={[_s.d, _s.flexRow, _s.mrAuto].join(' ')}>
|
||||
<div className={commentPublishBtnClasses}>
|
||||
<Button
|
||||
isNarrow
|
||||
onClick={this.handleSubmit}
|
||||
isDisabled={disabledButton}
|
||||
className={_s.px10}
|
||||
>
|
||||
{intl.formatMessage(scheduledAt ? messages.schedulePost : messages.publish)}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{
|
||||
(isUploading || anyMedia) &&
|
||||
<div className={[_s.d, _s.w100PC, _s.pl35, _s.mt5].join(' ')}>
|
||||
<UploadForm replyToId={replyToId} isModalOpen={isModalOpen} />
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
if (isModalOpen) {
|
||||
//
|
||||
}
|
||||
|
||||
if (isStandalone || isModalOpen) {
|
||||
return (
|
||||
<div className={[_s.d, _s.w100PC, _s.flexGrow1, _s.bgTertiary].join(' ')}>
|
||||
|
||||
<div className={[_s.d, _s.calcMaxH370PX, _s.overflowYScroll, _s.boxShadowBlock, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
|
||||
<ComposeDestinationHeader account={account} />
|
||||
|
||||
<div
|
||||
className={[_s.d, _s.bgPrimary, _s.boxShadowBlock, _s.w100PC, _s.minH200PX, _s.pb10, _s.borderBottom1PX, _s.borderTop1PX, _s.borderColorSecondary].join(' ')}
|
||||
ref={this.setForm}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
|
||||
{
|
||||
!!reduxReplyToId && isModalOpen && isMatch &&
|
||||
<div className={[_s.d, _s.px15, _s.py10, _s.mt5].join(' ')}>
|
||||
<StatusContainer
|
||||
contextType='compose'
|
||||
id={reduxReplyToId}
|
||||
isChild
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
!!spoiler &&
|
||||
<div className={[_s.d, _s.px15, _s.py10, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
|
||||
<Input
|
||||
placeholder={intl.formatMessage(messages.spoiler_placeholder)}
|
||||
value={this.props.spoilerText}
|
||||
onChange={this.handleChangeSpoilerText}
|
||||
disabled={!this.props.spoiler}
|
||||
prependIcon='warning'
|
||||
maxLength={256}
|
||||
id='cw-spoiler-input'
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
<AutosuggestTextbox
|
||||
ref={(isModalOpen && shouldCondense) ? null : this.setAutosuggestTextarea}
|
||||
placeholder={intl.formatMessage((shouldCondense || !!reduxReplyToId) && isMatch ? messages.commentPlaceholder : messages.placeholder)}
|
||||
disabled={disabled}
|
||||
value={this.props.text}
|
||||
valueMarkdown={this.props.markdown}
|
||||
onChange={this.handleChange}
|
||||
suggestions={this.props.suggestions}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
onFocus={this.handleComposeFocus}
|
||||
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
|
||||
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
|
||||
onSuggestionSelected={this.onSuggestionSelected}
|
||||
onPaste={onPaste}
|
||||
autoFocus={shouldAutoFocus}
|
||||
small={shouldCondense}
|
||||
isPro={isPro}
|
||||
isEdit={!!edit}
|
||||
id='main-composer'
|
||||
/>
|
||||
|
||||
{
|
||||
(isUploading || anyMedia) &&
|
||||
<div className={[_s.d, _s.w100PC, _s.pl35, _s.mt5].join(' ')}>
|
||||
<div className={[_s.d, _s.px15, _s.mt5].join(' ')}>
|
||||
<UploadForm
|
||||
replyToId={replyToId}
|
||||
isModalOpen={isModalOpen}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
!shouldCondense &&
|
||||
<div className={parentContainerClasses}>
|
||||
<div className={[_s.d, _s.flexRow, _s.w100PC].join(' ')}>
|
||||
<div
|
||||
className={childContainerClasses}
|
||||
ref={this.setForm}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
|
||||
{
|
||||
!!reduxReplyToId && isModalOpen && isMatch &&
|
||||
<div className={[_s.d, _s.px15, _s.py10, _s.mt5].join(' ')}>
|
||||
<StatusContainer
|
||||
contextType='compose'
|
||||
id={reduxReplyToId}
|
||||
isChild
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
!!spoiler &&
|
||||
<div className={[_s.d, _s.px15, _s.py10, _s.borderBottom1PX, _s.borderColorSecondary].join(' ')}>
|
||||
<Input
|
||||
placeholder={intl.formatMessage(messages.spoiler_placeholder)}
|
||||
value={this.props.spoilerText}
|
||||
onChange={this.handleChangeSpoilerText}
|
||||
disabled={!this.props.spoiler}
|
||||
prependIcon='warning'
|
||||
maxLength={256}
|
||||
id='cw-spoiler-input'
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
<AutosuggestTextbox
|
||||
ref={(isModalOpen && shouldCondense) ? null : this.setAutosuggestTextarea}
|
||||
placeholder={intl.formatMessage((shouldCondense || !!reduxReplyToId) && isMatch ? messages.commentPlaceholder : messages.placeholder)}
|
||||
disabled={disabled}
|
||||
value={this.props.text}
|
||||
valueMarkdown={this.props.markdown}
|
||||
onChange={this.handleChange}
|
||||
suggestions={this.props.suggestions}
|
||||
onKeyDown={this.handleKeyDown}
|
||||
onFocus={this.handleComposeFocus}
|
||||
onSuggestionsFetchRequested={this.onSuggestionsFetchRequested}
|
||||
onSuggestionsClearRequested={this.onSuggestionsClearRequested}
|
||||
onSuggestionSelected={this.onSuggestionSelected}
|
||||
onPaste={onPaste}
|
||||
autoFocus={shouldAutoFocus}
|
||||
small={shouldCondense}
|
||||
isPro={isPro}
|
||||
isEdit={!!edit}
|
||||
id='main-composer'
|
||||
/>
|
||||
|
||||
{
|
||||
(isUploading || anyMedia) &&
|
||||
<div className={[_s.d, _s.px15, _s.mt5].join(' ')}>
|
||||
<UploadForm
|
||||
replyToId={replyToId}
|
||||
isModalOpen={isModalOpen}
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
!edit && hasPoll &&
|
||||
<div className={[_s.d, _s.px15, _s.mt5].join(' ')}>
|
||||
<PollForm replyToId={replyToId} />
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
!!quoteOfId && isModalOpen && isMatch &&
|
||||
<div className={[_s.d, _s.px15, _s.py10, _s.mt5].join(' ')}>
|
||||
<StatusContainer
|
||||
contextType='compose'
|
||||
id={quoteOfId}
|
||||
isChild
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div className={actionsContainerClasses}>
|
||||
<div className={[_s.d, _s.flexRow, _s.mrAuto].join(' ')}>
|
||||
|
||||
<UploadButton small={shouldCondense} />
|
||||
|
||||
<EmojiPickerButton small={shouldCondense} isMatch={isMatch} />
|
||||
|
||||
{ /* <GifSelectorButton small={shouldCondense} /> */}
|
||||
|
||||
{
|
||||
!edit &&
|
||||
<PollButton />
|
||||
}
|
||||
|
||||
<StatusVisibilityButton />
|
||||
<SpoilerButton />
|
||||
{
|
||||
!hidePro && !edit &&
|
||||
<SchedulePostButton />
|
||||
}
|
||||
|
||||
{
|
||||
!hidePro && !edit &&
|
||||
<ExpiresPostButton />
|
||||
}
|
||||
|
||||
{
|
||||
!hidePro &&
|
||||
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
|
||||
<RichTextEditorButton />
|
||||
</Responsive>
|
||||
}
|
||||
</div>
|
||||
|
||||
<Responsive min={BREAKPOINT_EXTRA_SMALL}>
|
||||
<CharacterCounter max={MAX_POST_CHARACTER_COUNT} text={text} />
|
||||
</Responsive>
|
||||
|
||||
<Button
|
||||
isOutline
|
||||
isDisabled={disabledButton}
|
||||
backgroundColor='none'
|
||||
color='brand'
|
||||
className={[_s.fs15PX, _s.px15].join(' ')}
|
||||
onClick={this.handleSubmit}
|
||||
>
|
||||
{intl.formatMessage(scheduledAt ? messages.schedulePost : edit ? messages.publishEdit : messages.publish)}
|
||||
</Button>
|
||||
{
|
||||
!edit && hasPoll &&
|
||||
<div className={[_s.d, _s.px15, _s.mt5].join(' ')}>
|
||||
<PollForm replyToId={replyToId} />
|
||||
</div>
|
||||
}
|
||||
|
||||
{
|
||||
!!quoteOfId && isModalOpen && isMatch &&
|
||||
<div className={[_s.d, _s.px15, _s.py10, _s.mt5].join(' ')}>
|
||||
<StatusContainer
|
||||
contextType='compose'
|
||||
id={quoteOfId}
|
||||
isChild
|
||||
/>
|
||||
</div>
|
||||
}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div className={[_s.d, _s.w100PC, _s.pt10, _s.px10].join(' ')}>
|
||||
<Button
|
||||
isBlock
|
||||
isDisabled={disabledButton}
|
||||
backgroundColor={disabledButton ? 'secondary' : 'brand'}
|
||||
color={disabledButton ? 'tertiary' : 'white'}
|
||||
className={[_s.fs15PX, _s.px15, _s.flexGrow1, _s.mlAuto].join(' ')}
|
||||
onClick={this.handleSubmit}
|
||||
>
|
||||
<Text color='inherit' weight='medium' align='center'>
|
||||
{intl.formatMessage(scheduledAt ? messages.schedulePost : edit ? messages.publishEdit : messages.publish)}
|
||||
</Text>
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<ComposeExtraButtonList isMatch={isMatch} hidePro={hidePro} edit={edit} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={[_s.d, _s.w100PC, _s.pb10, _s.flexWrap, _s.overflowHidden, _s.flex1].join(' ')}
|
||||
ref={this.setForm}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
<Text className={[_s.d, _s.px15, _s.pt15, _s.pb10].join(' ')} size='medium' color='tertiary'>
|
||||
{intl.formatMessage((shouldCondense || !!reduxReplyToId) && isMatch ? messages.commentPlaceholder : messages.placeholder)}
|
||||
</Text>
|
||||
|
||||
<div className={[_s.d, _s.flexRow, _s.aiCenter, _s.mt5, _s.px10, _s.flexWrap].join(' ')}>
|
||||
<UploadButton />
|
||||
<EmojiPickerButton isMatch={isMatch} />
|
||||
<Responsive min={BREAKPOINT_EXTRA_EXTRA_SMALL}>
|
||||
<PollButton />
|
||||
</Responsive>
|
||||
<Button
|
||||
isOutline
|
||||
isDisabled={disabledButton}
|
||||
backgroundColor='none'
|
||||
color='brand'
|
||||
className={[_s.fs15PX, _s.px15, _s.flexGrow1, _s.maxW212PX, _s.mlAuto].join(' ')}
|
||||
onClick={this.handleSubmit}
|
||||
>
|
||||
<Text color='inherit' weight='medium' align='center'>
|
||||
{intl.formatMessage(scheduledAt ? messages.schedulePost : edit ? messages.publishEdit : messages.publish)}
|
||||
</Text>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -497,6 +496,7 @@ ComposeForm.propTypes = {
|
||||
isPro: PropTypes.bool,
|
||||
hidePro: PropTypes.bool,
|
||||
autoJoinGroup: PropTypes.bool,
|
||||
isStandalone: PropTypes.bool,
|
||||
}
|
||||
|
||||
ComposeForm.defaultProps = {
|
||||
|
||||
@@ -29,9 +29,9 @@ class EmojiPickerButton extends React.PureComponent {
|
||||
title={intl.formatMessage(messages.emoji)}
|
||||
onClick={this.handleClick}
|
||||
icon='happy'
|
||||
small={small}
|
||||
active={active && isMatch}
|
||||
buttonRef={this.setButton}
|
||||
small={small}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -47,21 +47,19 @@ const mapStateToProps = (state) => ({
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
onClick(targetRef) {
|
||||
dispatch(openPopover('EMOJI_PICKER', {
|
||||
targetRef,
|
||||
}))
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
EmojiPickerButton.propTypes = {
|
||||
intl: PropTypes.object.isRequired,
|
||||
onClick: PropTypes.func.isRequired,
|
||||
active: PropTypes.bool,
|
||||
small: PropTypes.bool,
|
||||
isMatch: PropTypes.bool,
|
||||
small: PropTypes.bool,
|
||||
}
|
||||
|
||||
export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(EmojiPickerButton))
|
||||
@@ -24,7 +24,14 @@ class UploadButton extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, resetFileKey, unavailable, disabled, acceptContentTypes, small } = this.props
|
||||
const {
|
||||
intl,
|
||||
resetFileKey,
|
||||
unavailable,
|
||||
disabled,
|
||||
acceptContentTypes,
|
||||
small,
|
||||
} = this.props
|
||||
|
||||
if (unavailable) return null
|
||||
|
||||
@@ -33,8 +40,8 @@ class UploadButton extends ImmutablePureComponent {
|
||||
title={intl.formatMessage(messages.title)}
|
||||
disabled={disabled}
|
||||
onClick={this.handleClick}
|
||||
icon='media'
|
||||
small={small}
|
||||
icon='media'
|
||||
>
|
||||
<label>
|
||||
<span className={_s.displayNone}>{intl.formatMessage(messages.upload)}</span>
|
||||
|
||||
@@ -12,13 +12,19 @@ class PollButton extends React.PureComponent {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { intl, active, unavailable, disabled, small } = this.props
|
||||
const {
|
||||
intl,
|
||||
active,
|
||||
unavailable,
|
||||
disabled,
|
||||
small,
|
||||
} = this.props
|
||||
|
||||
if (unavailable) return null
|
||||
|
||||
return (
|
||||
<ComposeExtraButton
|
||||
title={intl.formatMessage(active ? messages.remove_poll : messages.title)}
|
||||
title={intl.formatMessage(active ? messages.remove_poll : messages.add_poll)}
|
||||
disabled={disabled}
|
||||
onClick={this.handleClick}
|
||||
icon='poll'
|
||||
@@ -42,7 +48,6 @@ const mapStateToProps = (state) => ({
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
onClick() {
|
||||
dispatch((_, getState) => {
|
||||
if (getState().getIn(['compose', 'poll'])) {
|
||||
@@ -52,7 +57,6 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
PollButton.propTypes = {
|
||||
|
||||
@@ -46,11 +46,9 @@ const mapStateToProps = (state) => ({
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
onChangeRichTextEditorControlsVisibility() {
|
||||
dispatch(changeRichTextEditorControlsVisibility())
|
||||
},
|
||||
|
||||
onOpenProUpgradeModal() {
|
||||
dispatch(openModal('PRO_UPGRADE'))
|
||||
},
|
||||
|
||||
@@ -39,11 +39,9 @@ const mapStateToProps = (state) => ({
|
||||
})
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
onClick () {
|
||||
dispatch(changeComposeSpoilerness())
|
||||
},
|
||||
|
||||
})
|
||||
|
||||
SpoilerButton.propTypes = {
|
||||
|
||||
Reference in New Issue
Block a user