-
+
{children}
@@ -30,6 +31,7 @@ DeckColumn.propTypes = {
title: PropTypes.string,
subtitle: PropTypes.string,
icon: PropTypes.string,
+ index: PropTypes.number,
}
export default DeckColumn
\ No newline at end of file
diff --git a/app/javascript/gabsocial/components/deck_column_header.js b/app/javascript/gabsocial/components/deck_column_header.js
index ad1012b3..0abd5440 100644
--- a/app/javascript/gabsocial/components/deck_column_header.js
+++ b/app/javascript/gabsocial/components/deck_column_header.js
@@ -1,11 +1,21 @@
import React from 'react'
import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
+import { deleteDeckColumnAtIndex } from '../actions/deck'
import Icon from './icon'
import Text from './text'
import Button from './button'
class DeckColumnHeader extends React.PureComponent {
+ handleClickDelete = () => {
+ this.props.dispatch(deleteDeckColumnAtIndex(this.props.index))
+ }
+
+ handleClickRefresh = () => {
+
+ }
+
render() {
const {
title,
@@ -15,22 +25,41 @@ class DeckColumnHeader extends React.PureComponent {
} = this.props
return (
-
- { !!icon &&
}
+
+ {
+ !!icon &&
+
+
+
+
+
+ }
+ { !!icon &&
}
- { !!title && {title} }
- { !!subtitle && {subtitle} }
+ { !!title && {title} }
+ { !!subtitle && {subtitle} }
-
- {
- !!title &&
+ {
+ !!title &&
+
- }
-
+
+
+ }
)
}
@@ -41,6 +70,7 @@ DeckColumnHeader.propTypes = {
title: PropTypes.string,
subtitle: PropTypes.string,
icon: PropTypes.string,
+ index: PropTypes.number,
}
-export default DeckColumnHeader
\ No newline at end of file
+export default connect()(DeckColumnHeader)
\ No newline at end of file
diff --git a/app/javascript/gabsocial/components/modal/compose_post_destination_modal.js b/app/javascript/gabsocial/components/modal/compose_post_destination_modal.js
new file mode 100644
index 00000000..e69de29b
diff --git a/app/javascript/gabsocial/components/modal/deck_column_add_modal.js b/app/javascript/gabsocial/components/modal/deck_column_add_modal.js
index 5e860a77..c493d9bb 100644
--- a/app/javascript/gabsocial/components/modal/deck_column_add_modal.js
+++ b/app/javascript/gabsocial/components/modal/deck_column_add_modal.js
@@ -2,7 +2,6 @@ import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'react-redux'
import { setDeckColumnAtIndex } from '../../actions/deck'
-import { saveSettings } from '../../actions/settings'
import { openModal } from '../../actions/modal'
import ModalLayout from './modal_layout'
import Button from '../button'
@@ -11,6 +10,7 @@ import Text from '../text'
class DeckColumnAddModal extends React.PureComponent {
onAdd = (column) => {
+ console.log("onAdd column: ", column)
switch (column) {
case 'user':
//
@@ -18,15 +18,12 @@ class DeckColumnAddModal extends React.PureComponent {
case 'list':
//
break
- case 'groups':
- //
- break
case 'group':
//
break
default:
this.props.dispatch(setDeckColumnAtIndex(column))
- this.props.dispatch(saveSettings())
+ this.props.onClose()
break
}
}
@@ -47,7 +44,7 @@ class DeckColumnAddModal extends React.PureComponent {
this.onAdd('home')} />
this.onAdd('user')} />
- this.onAdd('home')} />
+ this.onAdd('notifications')} />
this.onAdd('list')} />
@@ -56,7 +53,7 @@ class DeckColumnAddModal extends React.PureComponent {
this.onAdd('pro')} />
- this.onAdd('groups')} />
+ this.onAdd('compose')} />
this.onAdd('group')} />
@@ -85,7 +82,7 @@ const DeckColumnAddModalButton = ({ icon, type, onClick }) => (
DeckColumnAddModalButton.propTypes = {
- onSetDeckColumnAtIndex: PropTypes.func.isRequired,
+ onClose: PropTypes.func.isRequired,
}
export default connect()(DeckColumnAddModal)
\ No newline at end of file
diff --git a/app/javascript/gabsocial/components/navigation_bar/compose_navigation_bar_xs.js b/app/javascript/gabsocial/components/navigation_bar/compose_navigation_bar_xs.js
new file mode 100644
index 00000000..75f13c02
--- /dev/null
+++ b/app/javascript/gabsocial/components/navigation_bar/compose_navigation_bar_xs.js
@@ -0,0 +1,96 @@
+import React from 'react'
+import PropTypes from 'prop-types'
+import { connect } from 'react-redux'
+import { length } from 'stringz'
+import { openPopover } from '../../actions/popover'
+import { MAX_POST_CHARACTER_COUNT } from '../../constants'
+import Heading from '../heading'
+import Button from '../button'
+import BackButton from '../back_button'
+import Text from '../text'
+import CharacterCounter from '../character_counter'
+
+class ComposeNavigationBar extends React.PureComponent {
+
+ handleOnPost = () => {
+ //
+ }
+
+ render() {
+ const {
+ isUploading,
+ isChangingUpload,
+ isSubmitting,
+ anyMedia,
+ text,
+ } = this.props
+
+ const disabledButton = isSubmitting || isUploading || isChangingUpload || length(text) > MAX_POST_CHARACTER_COUNT || (length(text.trim()) === 0 && !anyMedia)
+ const buttonOptions = {
+ backgroundColor: disabledButton ? 'tertiary' : 'brand',
+ color: disabledButton ? 'tertiary' : 'white',
+ isDisabled: disabledButton,
+ onClick: this.handleOnPost,
+ }
+
+ return (
+
+
+
+
+
+
+
+
+
+ Compose
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+ }
+
+}
+
+const mapStateToProps = (state, props) => ({
+ isUploading: state.getIn(['compose', 'is_uploading']),
+ isChangingUpload: state.getIn(['compose', 'is_changing_upload']),
+ isSubmitting: state.getIn(['compose', 'is_submitting']),
+ anyMedia: state.getIn(['compose', 'media_attachments']).size > 0,
+ text: state.getIn(['compose', 'text']),
+})
+
+const mapDispatchToProps = (dispatch) => ({
+ onSubmitCompose() {
+ //
+ },
+})
+
+ComposeNavigationBar.propTypes = {
+ isUploading: PropTypes.bool,
+ isChangingUpload: PropTypes.bool,
+ isSubmitting: PropTypes.bool,
+ anyMedia: PropTypes.bool,
+ text: PropTypes.string,
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(ComposeNavigationBar)
\ No newline at end of file
diff --git a/app/javascript/gabsocial/components/sidebar/deck_sidebar.js b/app/javascript/gabsocial/components/sidebar/deck_sidebar.js
index fe8d31ee..5644844e 100644
--- a/app/javascript/gabsocial/components/sidebar/deck_sidebar.js
+++ b/app/javascript/gabsocial/components/sidebar/deck_sidebar.js
@@ -11,6 +11,7 @@ import { makeGetAccount } from '../../selectors'
import {
THEMES,
DEFAULT_THEME,
+ MODAL_COMPOSE,
POPOVER_NAV_SETTINGS,
MODAL_DECK_COLUMN_ADD,
} from '../../constants'
@@ -38,6 +39,10 @@ class DeckSidebar extends ImmutablePureComponent {
this.props.onOpenNewColumnModal()
}
+ handleOnOpenComposeModal = () => {
+ this.props.onOpenComposeModal()
+ }
+
setAvatarNode = (c) => {
this.avatarNode = c
}
@@ -70,9 +75,9 @@ class DeckSidebar extends ImmutablePureComponent {
-
+
-
+
@@ -117,12 +122,15 @@ const mapDispatchToProps = (dispatch) => ({
onOpenNavSettingsPopover(targetRef) {
dispatch(openPopover(POPOVER_NAV_SETTINGS, {
targetRef,
- position: 'right-start',
+ position: 'top-start',
}))
},
onOpenNewColumnModal() {
dispatch(openModal(MODAL_DECK_COLUMN_ADD))
},
+ onOpenComposeModal() {
+ dispatch(openModal(MODAL_COMPOSE))
+ },
onChange(key, value) {
dispatch(changeSetting(['displayOptions', key], value))
dispatch(saveSettings())
@@ -133,6 +141,7 @@ DeckSidebar.propTypes = {
account: ImmutablePropTypes.map,
onOpenNavSettingsPopover: PropTypes.func.isRequired,
onOpenNewColumnModal: PropTypes.func.isRequired,
+ onOpenComposeModal: PropTypes.func.isRequired,
theme: PropTypes.string,
logoDisabled: PropTypes.bool,
}
diff --git a/app/javascript/gabsocial/constants.js b/app/javascript/gabsocial/constants.js
index e1185528..747879d2 100644
--- a/app/javascript/gabsocial/constants.js
+++ b/app/javascript/gabsocial/constants.js
@@ -10,6 +10,7 @@ export const BREAKPOINT_LARGE = 1280
export const BREAKPOINT_MEDIUM = 1160
export const BREAKPOINT_SMALL = 1080
export const BREAKPOINT_EXTRA_SMALL = 992
+export const BREAKPOINT_EXTRA_EXTRA_SMALL = 767
export const MOUSE_IDLE_DELAY = 300
@@ -165,6 +166,8 @@ export const TIMELINE_INJECTION_WEIGHT_MULTIPLIER = 100
export const TIMELINE_INJECTION_WEIGHT_SUBTRACTOR = 0.005
export const TIMELINE_INJECTION_WEIGHT_MIN = 0.01
+export const GAB_DECK_OPTIONS = ['home', 'user.id', 'notifications', 'list.id', 'likes', 'bookmarks', 'pro', 'compose', 'group.id']
+
export const TRENDS_RSS_SOURCES = [
{'id':'5daf64b18e955e2433b0f5ce','title':'Breitbart'},
{'id':'5daf66772fea4d3ba000883b','title':'Gateway Pundit'},
diff --git a/app/javascript/gabsocial/features/compose/components/compose_destination_header.js b/app/javascript/gabsocial/features/compose/components/compose_destination_header.js
new file mode 100644
index 00000000..b57c2ebf
--- /dev/null
+++ b/app/javascript/gabsocial/features/compose/components/compose_destination_header.js
@@ -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 (
+
+
+
+
+
+
+ )
+ }
+}
+
+ComposeDestinationHeader.propTypes = {
+ account: ImmutablePropTypes.map,
+}
+
+export default ComposeDestinationHeader
\ No newline at end of file
diff --git a/app/javascript/gabsocial/features/compose/components/compose_extra_button.js b/app/javascript/gabsocial/features/compose/components/compose_extra_button.js
index 9a09acdb..2d8f98c4 100644
--- a/app/javascript/gabsocial/features/compose/components/compose_extra_button.js
+++ b/app/javascript/gabsocial/features/compose/components/compose_extra_button.js
@@ -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 = (
-
- )
-
- if (!children) {
- return button
- }
+ const iconSize = !small ? '18px' : '16px'
+ const textColor = !active ? 'primary' : 'white'
return (
-
- {button}
- {children}
+
+
)
}
@@ -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
\ No newline at end of file
diff --git a/app/javascript/gabsocial/features/compose/components/compose_extra_button_list.js b/app/javascript/gabsocial/features/compose/components/compose_extra_button_list.js
new file mode 100644
index 00000000..04779fcf
--- /dev/null
+++ b/app/javascript/gabsocial/features/compose/components/compose_extra_button_list.js
@@ -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 (
+
+
+
+ { !edit &&
}
+
+
+ { !hidePro && !edit &&
}
+ { !hidePro && !edit &&
}
+ { !hidePro &&
}
+
+ )
+ }
+}
+
+ComposeExtraButtonList.propTypes = {
+ hidePro: PropTypes.bool,
+ edit: PropTypes.bool,
+ isMatch: PropTypes.bool,
+}
+
+export default ComposeExtraButtonList
diff --git a/app/javascript/gabsocial/features/compose/components/compose_form.js b/app/javascript/gabsocial/features/compose/components/compose_form.js
index 451d33a5..39e23315 100644
--- a/app/javascript/gabsocial/features/compose/components/compose_form.js
+++ b/app/javascript/gabsocial/features/compose/components/compose_form.js
@@ -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 (
-
- {
- shouldCondense &&
-
-
+ if (shouldCondense) {
+ return (
+
+
+
-
-
+
-
+
-
-
-
-
-
- { /*
*/}
-
- { /*
*/}
-
-
-
-
-
-
+
+
+
+
+
+
+
+ {
+ (isUploading || anyMedia) &&
+
+
+
+ }
+
+ )
+ }
+
+ if (isModalOpen) {
+ //
+ }
+
+ if (isStandalone || isModalOpen) {
+ return (
+
+
+
+
+
+
+
+ {
+ !!reduxReplyToId && isModalOpen && isMatch &&
+
+
+
+ }
+
+ {
+ !!spoiler &&
+
+
+
+ }
+
+
+
{
(isUploading || anyMedia) &&
-
-
- }
- {
- !shouldCondense &&
-
-
-
-
- {
- !!reduxReplyToId && isModalOpen && isMatch &&
-
-
-
- }
-
- {
- !!spoiler &&
-
-
-
- }
-
-
-
- {
- (isUploading || anyMedia) &&
-
-
-
- }
-
- {
- !edit && hasPoll &&
-
- }
-
- {
- !!quoteOfId && isModalOpen && isMatch &&
-
-
-
- }
-
-
-
-
-
-
-
-
- { /*
*/}
-
- {
- !edit &&
-
- }
-
-
-
- {
- !hidePro && !edit &&
-
- }
-
- {
- !hidePro && !edit &&
-
- }
-
- {
- !hidePro &&
-
-
-
- }
-
-
-
-
-
-
-
+ {
+ !edit && hasPoll &&
+
+ }
+
+ {
+ !!quoteOfId && isModalOpen && isMatch &&
+
+
+
+ }
-
- }
+
+
+
+
+
+
+
+ )
+ }
+
+ return (
+
+
+ {intl.formatMessage((shouldCondense || !!reduxReplyToId) && isMatch ? messages.commentPlaceholder : messages.placeholder)}
+
+
+
+
+
+
+
+
+
+
)
}
@@ -497,6 +496,7 @@ ComposeForm.propTypes = {
isPro: PropTypes.bool,
hidePro: PropTypes.bool,
autoJoinGroup: PropTypes.bool,
+ isStandalone: PropTypes.bool,
}
ComposeForm.defaultProps = {
diff --git a/app/javascript/gabsocial/features/compose/components/emoji_picker_button.js b/app/javascript/gabsocial/features/compose/components/emoji_picker_button.js
index 19008171..1b861de4 100644
--- a/app/javascript/gabsocial/features/compose/components/emoji_picker_button.js
+++ b/app/javascript/gabsocial/features/compose/components/emoji_picker_button.js
@@ -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))
\ No newline at end of file
diff --git a/app/javascript/gabsocial/features/compose/components/media_upload_button.js b/app/javascript/gabsocial/features/compose/components/media_upload_button.js
index 26f6fc19..3b1e1087 100644
--- a/app/javascript/gabsocial/features/compose/components/media_upload_button.js
+++ b/app/javascript/gabsocial/features/compose/components/media_upload_button.js
@@ -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'
>