From 3d0a85cde415a40d19e37a28c272a6e3f86b1179 Mon Sep 17 00:00:00 2001 From: mgabdev <> Date: Wed, 25 Mar 2020 23:11:32 -0400 Subject: [PATCH] Progress --- .../components/account_action_button.js | 54 +++++ .../components/bundle_column_error.js | 4 +- .../components/bundle_modal_error.js | 4 +- app/javascript/gabsocial/components/button.js | 32 ++- app/javascript/gabsocial/components/domain.js | 4 +- .../components/floating_action_button.js | 12 +- .../components/icon_button/icon_button.js | 96 -------- .../gabsocial/components/icon_button/index.js | 1 - app/javascript/gabsocial/components/input.js | 27 ++- .../components/media_gallery/media_gallery.js | 4 +- .../components/modal/actions_modal.js | 4 +- .../modal/hashtag_timeline_settings_modal.js | 86 +++++++ .../gabsocial/components/modal/media_modal.js | 4 +- .../gabsocial/components/modal/modal_root.js | 2 + .../notifications_timeline_settings_modal.js | 59 ----- .../components/modal/status_revision_modal.js | 4 +- .../components/panel/progress_panel.js | 6 +- .../popover/status_options_popover.js | 182 ++++++++++----- .../popover/status_privacy_popover.js} | 38 ++-- .../gabsocial/components/profile_header.js | 122 +++++----- .../gabsocial/components/progress_bar.js | 49 +++- .../gabsocial/components/status_action_bar.js | 8 +- .../status_content/status_content.js | 215 +++++++++++------- .../gabsocial/components/status_header.js | 26 ++- app/javascript/gabsocial/components/switch.js | 2 +- .../gabsocial/components/tab_bar_item.js | 39 +++- app/javascript/gabsocial/components/text.js | 5 +- .../components/action_bar/action_bar.js | 62 ----- .../compose/components/action_bar/index.js | 1 - .../character_counter.js | 0 .../character_counter/character_counter.scss | 16 -- .../components/character_counter/index.js | 1 - .../components/compose_extra_button.js | 55 +---- .../components/compose_form/compose_form.js | 13 +- .../navigation_bar/navigation_bar.js | 5 +- .../compose/components/post_privacy_button.js | 65 ++++++ .../components/quoted_status_preview.js | 2 + .../reply_indicator/reply_indicator.js | 4 +- .../components/sensitive_media_button.js | 51 +++++ .../features/compose/components/upload.js | 178 +++++++++++++++ .../compose/components/upload/index.js | 1 - .../compose/components/upload/upload.js | 126 ---------- .../compose/components/upload/upload.scss | 78 ------- .../components/upload_form/upload_form.js | 46 ++-- .../components/upload_progress/index.js | 1 - .../upload_progress/upload_progress.js | 48 ---- .../upload_progress/upload_progress.scss | 39 ---- .../containers/sensitive_button_container.js | 56 ----- .../compose/containers/upload_container.js | 26 --- .../account_authorize/account_authorize.js | 5 +- .../list_create-old/components/list/list.js | 6 +- .../features/list_create-old/list_adder.js | 4 +- .../features/list_edit/components/account.js | 6 +- .../gabsocial/features/list_edit/list_edit.js | 134 ++++++----- .../gabsocial/features/lists_directory.js | 2 +- .../column_settings/column_settings.js | 89 -------- .../components/column_settings/index.js | 1 - .../notification_filter_bar/index.js | 1 - .../notification_filter_bar.js | 95 -------- .../containers/column_settings_container.js | 1 + .../containers/filter_bar_container.js | 15 -- app/javascript/gabsocial/features/ui/ui.js | 2 +- .../gabsocial/layouts/default_layout.js | 16 +- app/javascript/gabsocial/pages/groups_page.js | 8 - app/javascript/gabsocial/pages/list_page.js | 2 +- .../gabsocial/pages/notifications_page.js | 72 +++++- app/javascript/gabsocial/reducers/settings.js | 27 +-- app/javascript/styles/global.css | 32 +++ 68 files changed, 1206 insertions(+), 1275 deletions(-) create mode 100644 app/javascript/gabsocial/components/account_action_button.js delete mode 100644 app/javascript/gabsocial/components/icon_button/icon_button.js delete mode 100644 app/javascript/gabsocial/components/icon_button/index.js create mode 100644 app/javascript/gabsocial/components/modal/hashtag_timeline_settings_modal.js delete mode 100644 app/javascript/gabsocial/components/modal/notifications_timeline_settings_modal.js rename app/javascript/gabsocial/{features/compose/components/privacy_dropdown.js => components/popover/status_privacy_popover.js} (87%) delete mode 100644 app/javascript/gabsocial/features/compose/components/action_bar/action_bar.js delete mode 100644 app/javascript/gabsocial/features/compose/components/action_bar/index.js rename app/javascript/gabsocial/features/compose/components/{character_counter => }/character_counter.js (100%) delete mode 100644 app/javascript/gabsocial/features/compose/components/character_counter/character_counter.scss delete mode 100644 app/javascript/gabsocial/features/compose/components/character_counter/index.js create mode 100644 app/javascript/gabsocial/features/compose/components/post_privacy_button.js create mode 100644 app/javascript/gabsocial/features/compose/components/sensitive_media_button.js create mode 100644 app/javascript/gabsocial/features/compose/components/upload.js delete mode 100644 app/javascript/gabsocial/features/compose/components/upload/index.js delete mode 100644 app/javascript/gabsocial/features/compose/components/upload/upload.js delete mode 100644 app/javascript/gabsocial/features/compose/components/upload/upload.scss delete mode 100644 app/javascript/gabsocial/features/compose/components/upload_progress/index.js delete mode 100644 app/javascript/gabsocial/features/compose/components/upload_progress/upload_progress.js delete mode 100644 app/javascript/gabsocial/features/compose/components/upload_progress/upload_progress.scss delete mode 100644 app/javascript/gabsocial/features/compose/containers/sensitive_button_container.js delete mode 100644 app/javascript/gabsocial/features/compose/containers/upload_container.js delete mode 100644 app/javascript/gabsocial/features/notifications/components/column_settings/column_settings.js delete mode 100644 app/javascript/gabsocial/features/notifications/components/column_settings/index.js delete mode 100644 app/javascript/gabsocial/features/notifications/components/notification_filter_bar/index.js delete mode 100644 app/javascript/gabsocial/features/notifications/components/notification_filter_bar/notification_filter_bar.js delete mode 100644 app/javascript/gabsocial/features/notifications/containers/filter_bar_container.js diff --git a/app/javascript/gabsocial/components/account_action_button.js b/app/javascript/gabsocial/components/account_action_button.js new file mode 100644 index 00000000..41078261 --- /dev/null +++ b/app/javascript/gabsocial/components/account_action_button.js @@ -0,0 +1,54 @@ +import classNames from 'classnames/bind' + +const cx = classNames.bind(_s) + +// : todo : + +export default class AccountActionButton extends PureComponent { + static propTypes = { + children: PropTypes.any, + size: PropTypes.oneOf(Object.keys(SIZES)), + center: PropTypes.bool, + } + + static defaultProps = { + size: SIZES.h1, + } + + render() { + const { children, size, center } = this.props + + const classes = cx({ + default: 1, + text: 1, + textAlignCenter: center, + + colorPrimary: [SIZES.h1, SIZES.h3].indexOf(size) > -1, + colorSecondary: [SIZES.h2, SIZES.h4, SIZES.h5].indexOf(size) > -1, + + fontSize24PX: size === SIZES.h1, + fontSize19PX: size === SIZES.h2, + fontSize16PX: size === SIZES.h3, + fontSize13PX: size === SIZES.h4, + fontSize12PX: size === SIZES.h5, + + mt5: [SIZES.h2, SIZES.h4].indexOf(size) > -1, + + lineHeight2: size === SIZES.h5, + py2: size === SIZES.h5, + + // fontWeightNormal: weight === WEIGHTS.normal, + fontWeightMedium: [SIZES.h1, SIZES.h5].indexOf(size) > -1, + fontWeightBold: [SIZES.h3, SIZES.h4].indexOf(size) > -1, + }) + + return React.createElement( + size, + { + className: classes, + role: 'heading', + }, + children, + ) + } +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/bundle_column_error.js b/app/javascript/gabsocial/components/bundle_column_error.js index afb39abc..41563562 100644 --- a/app/javascript/gabsocial/components/bundle_column_error.js +++ b/app/javascript/gabsocial/components/bundle_column_error.js @@ -1,5 +1,5 @@ import { defineMessages, injectIntl } from 'react-intl' -import IconButton from './icon_button' +import Button from './button' const messages = defineMessages({ title: { id: 'bundle_column_error.title', defaultMessage: 'Network error' }, @@ -25,7 +25,7 @@ class BundleColumnError extends PureComponent { return (
- +
) diff --git a/app/javascript/gabsocial/components/bundle_modal_error.js b/app/javascript/gabsocial/components/bundle_modal_error.js index a1f0bf60..b4cf5b48 100644 --- a/app/javascript/gabsocial/components/bundle_modal_error.js +++ b/app/javascript/gabsocial/components/bundle_modal_error.js @@ -1,5 +1,5 @@ import { defineMessages, injectIntl } from 'react-intl'; -import IconButton from './icon_button'; +import Button from './button'; const messages = defineMessages({ error: { id: 'bundle_modal_error.message', defaultMessage: 'Something went wrong while loading this component.' }, @@ -29,7 +29,7 @@ class BundleModalError extends PureComponent { return (
- +
diff --git a/app/javascript/gabsocial/components/button.js b/app/javascript/gabsocial/components/button.js index d15d48e9..e2f7b13a 100644 --- a/app/javascript/gabsocial/components/button.js +++ b/app/javascript/gabsocial/components/button.js @@ -10,8 +10,9 @@ const COLORS = { secondary: 'secondary', tertiary: 'tertiary', white: 'white', + black: 'black', brand: 'brand', - error: 'error', + danger: 'danger', none: 'none', } @@ -87,12 +88,11 @@ export default class Button extends PureComponent { ) : undefined - // : todo : const classes = noClasses ? className : cx(className, { default: 1, noUnderline: 1, @@ -101,18 +101,22 @@ export default class Button extends PureComponent { textAlignCenter: 1, outlineNone: 1, flexRow: !!children && !!icon, + cursorNotAllowed: disabled, + opacity05: disabled, backgroundColorPrimary: backgroundColor === COLORS.white, + backgroundColorBlack: backgroundColor === COLORS.black, backgroundColorBrand: backgroundColor === COLORS.brand, backgroundTransparent: backgroundColor === COLORS.none, backgroundSubtle2: backgroundColor === COLORS.tertiary, backgroundSubtle: backgroundColor === COLORS.secondary, - - colorPrimary: color === COLORS.primary, - colorSecondary: color === COLORS.secondary, - colorTertiary: color === COLORS.tertiary, - colorWhite: color === COLORS.white, - colorBrand: color === COLORS.brand, + backgroundColorDanger: backgroundColor === COLORS.danger, + + colorPrimary: !!children && color === COLORS.primary, + colorSecondary: !!children && color === COLORS.secondary, + colorTertiary: !!children && color === COLORS.tertiary, + colorWhite: !!children && color === COLORS.white, + colorBrand: !!children && color === COLORS.brand, borderColorBrand: color === COLORS.brand && outline, border1PX: outline, @@ -128,12 +132,16 @@ export default class Button extends PureComponent { underline_onHover: underlineOnHover, - backgroundSubtle2Dark_onHover: backgroundColor === COLORS.tertiary, - + backgroundSubtle2Dark_onHover: backgroundColor === COLORS.tertiary || backgroundColor === COLORS.secondary, + backgroundColorBlackOpaque_onHover: backgroundColor === COLORS.black, backgroundColorBrandDark_onHover: backgroundColor === COLORS.brand, backgroundColorBrand_onHover: color === COLORS.brand && outline, - colorWhite_onHover: color === COLORS.brand && outline, + colorWhite_onHover: !!children && color === COLORS.brand && outline, + + fillColorWhite: !!icon && color === COLORS.white, + fillColorBrand: !!icon && color === COLORS.brand, + fillColorWhite_onHover: !!icon && color === COLORS.brand && outline, }) const tagName = !!href ? 'a' : !!to ? 'NavLink' : 'button' diff --git a/app/javascript/gabsocial/components/domain.js b/app/javascript/gabsocial/components/domain.js index 21b9947d..79b9b329 100644 --- a/app/javascript/gabsocial/components/domain.js +++ b/app/javascript/gabsocial/components/domain.js @@ -1,5 +1,5 @@ import { defineMessages, injectIntl } from 'react-intl'; -import IconButton from './icon_button'; +import Button from './button'; const messages = defineMessages({ unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' }, @@ -30,7 +30,7 @@ class Domain extends PureComponent {
- path.match(/^\/posts\/|^\/search|^\/getting-started/); + // const floatingActionButton = shouldHideFAB(this.context.router.history.location.pathname) ? null : ; + return ( - ) } diff --git a/app/javascript/gabsocial/components/icon_button/icon_button.js b/app/javascript/gabsocial/components/icon_button/icon_button.js deleted file mode 100644 index 50e83481..00000000 --- a/app/javascript/gabsocial/components/icon_button/icon_button.js +++ /dev/null @@ -1,96 +0,0 @@ -import classNames from 'classnames'; -import spring from 'react-motion/lib/spring'; -import Motion from '../../features/ui/util/optional_motion'; -import Icon from '../icon'; - -export default class IconButton extends PureComponent { - - static propTypes = { - className: PropTypes.string, - title: PropTypes.string.isRequired, - icon: PropTypes.string.isRequired, - onClick: PropTypes.func, - size: PropTypes.number, - active: PropTypes.bool, - pressed: PropTypes.bool, - expanded: PropTypes.bool, - style: PropTypes.object, - disabled: PropTypes.bool, - inverted: PropTypes.bool, - animate: PropTypes.bool, - overlay: PropTypes.bool, - tabIndex: PropTypes.string, - text: PropTypes.string, - width: PropTypes.string, - height: PropTypes.string, - }; - - static defaultProps = { - size: 18, - active: false, - disabled: false, - animate: false, - overlay: false, - tabIndex: '0', - }; - - handleClick = (e) => { - e.preventDefault(); - - if (!this.props.disabled) { - this.props.onClick(e); - } - } - - render () { - const style = { - // fontSize: `${this.props.size}px`, - // width: `${this.props.size * 1.28571429}px`, - // height: `${this.props.size * 1.28571429}px`, - // lineHeight: `${this.props.size}px`, - ...this.props.style, - }; - - const { - active, - animate, - className, - disabled, - expanded, - icon, - inverted, - overlay, - pressed, - tabIndex, - title, - text, - width, - height, - } = this.props; - - const classes = classNames(className, 'icon-button', { - active, - disabled, - inverted, - overlayed: overlay, - }); - - return ( - - ); - } - -} diff --git a/app/javascript/gabsocial/components/icon_button/index.js b/app/javascript/gabsocial/components/icon_button/index.js deleted file mode 100644 index c77d8cd3..00000000 --- a/app/javascript/gabsocial/components/icon_button/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './icon_button' \ No newline at end of file diff --git a/app/javascript/gabsocial/components/input.js b/app/javascript/gabsocial/components/input.js index 7efcde3f..689cc5c4 100644 --- a/app/javascript/gabsocial/components/input.js +++ b/app/javascript/gabsocial/components/input.js @@ -20,6 +20,8 @@ export default class Input extends PureComponent { small: PropTypes.bool, readOnly: PropTypes.string, inputRef: PropTypes.func, + id: PropTypes.string, + hideLabel: PropTypes.bool, } render() { @@ -36,20 +38,25 @@ export default class Input extends PureComponent { title, small, readOnly, - inputRef + inputRef, + id, + hideLabel } = this.props const inputClasses = cx({ default: 1, text: 1, outlineNone: 1, - lineHeight125: 1, + lineHeight125: !small, + lineHeight1: small, displayBlock: 1, - py10: 1, + py10: !small, + py5: small, backgroundTransparent: !readOnly, backgroundSubtle2: readOnly, colorSecondary: readOnly, - fontSize15PX: 1, + fontSize15PX: !small, + fontSize13PX: small, flexGrow1: 1, circle: 1, px5: !!prependIcon, @@ -57,12 +64,19 @@ export default class Input extends PureComponent { pr15: !hasClear, }) + const titleClasses = cx({ + default: 1, + mb10: 1, + pl15: 1, + displayNone: hideLabel, + }) + return ( { !!title && -
- +
+ {title}
@@ -74,6 +88,7 @@ export default class Input extends PureComponent { } ; + spoilerButton = + + + ) + } +} diff --git a/app/javascript/gabsocial/components/modal/media_modal.js b/app/javascript/gabsocial/components/modal/media_modal.js index ffbe3907..ba549dd7 100644 --- a/app/javascript/gabsocial/components/modal/media_modal.js +++ b/app/javascript/gabsocial/components/modal/media_modal.js @@ -5,7 +5,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import Video from '../../features/video'; import ExtendedVideoPlayer from '../extended_video_player'; -import IconButton from '../icon_button'; +import Button from '../button'; import ImageLoader from '../image_loader'; import Icon from '../icon'; @@ -221,7 +221,7 @@ class MediaModal extends ImmutablePureComponent {
- + - -
- ) - } -} diff --git a/app/javascript/gabsocial/components/modal/status_revision_modal.js b/app/javascript/gabsocial/components/modal/status_revision_modal.js index e5caa03b..f8ae4e28 100644 --- a/app/javascript/gabsocial/components/modal/status_revision_modal.js +++ b/app/javascript/gabsocial/components/modal/status_revision_modal.js @@ -2,7 +2,7 @@ import { defineMessages, injectIntl, FormattedMessage } from 'react-intl' import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePureComponent from 'react-immutable-pure-component' import StatusRevisionListContainer from '../../containers/status_revision_list_container' -import IconButton from '../icon_button' +import Button from '../button' const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, @@ -28,7 +28,7 @@ class StatusRevisionModal extends ImmutablePureComponent {

- +
diff --git a/app/javascript/gabsocial/components/panel/progress_panel.js b/app/javascript/gabsocial/components/panel/progress_panel.js index b41d48ed..95c83855 100644 --- a/app/javascript/gabsocial/components/panel/progress_panel.js +++ b/app/javascript/gabsocial/components/panel/progress_panel.js @@ -12,7 +12,11 @@ export default class ProgressPanel extends PureComponent { subtitle="We are 100% funded by you" hasBackground > - + ) } diff --git a/app/javascript/gabsocial/components/popover/status_options_popover.js b/app/javascript/gabsocial/components/popover/status_options_popover.js index e407f169..cc2a8df2 100644 --- a/app/javascript/gabsocial/components/popover/status_options_popover.js +++ b/app/javascript/gabsocial/components/popover/status_options_popover.js @@ -1,81 +1,149 @@ +import ImmutablePropTypes from 'react-immutable-proptypes' +import ImmutablePureComponent from 'react-immutable-pure-component' +import { defineMessages, injectIntl } from 'react-intl' import PopoverLayout from './popover_layout' import List from '../list' -export default class StatusOptionsPopover extends PureComponent { - _makeMenu = (publicStatus) => { - // const { status, intl: { formatMessage }, withDismiss, withGroupAdmin } = this.props - // const mutingConversation = status.get('muted') +const messages = defineMessages({ + delete: { id: 'status.delete', defaultMessage: 'Delete' }, + edit: { id: 'status.edit', defaultMessage: 'Edit' }, + mention: { id: 'status.mention', defaultMessage: 'Mention @{name}' }, + mute: { id: 'account.mute', defaultMessage: 'Mute @{name}' }, + block: { id: 'account.block', defaultMessage: 'Block @{name}' }, + reply: { id: 'status.reply', defaultMessage: 'Reply' }, + comment: { id: 'status.comment', defaultMessage: 'Comment' }, + more: { id: 'status.more', defaultMessage: 'More' }, + share: { id: 'status.share', defaultMessage: 'Share' }, + replyAll: { id: 'status.replyAll', defaultMessage: 'Reply to thread' }, + repost: { id: 'repost', defaultMessage: 'Repost' }, + quote: { id: 'status.quote', defaultMessage: 'Quote' }, + repost_private: { id: 'status.repost_private', defaultMessage: 'Repost to original audience' }, + cancel_repost_private: { id: 'status.cancel_repost_private', defaultMessage: 'Un-repost' }, + cannot_repost: { id: 'status.cannot_repost', defaultMessage: 'This post cannot be reposted' }, + cannot_quote: { id: 'status.cannot_quote', defaultMessage: 'This post cannot be quoted' }, + like: { id: 'status.like', defaultMessage: 'Like' }, + open: { id: 'status.open', defaultMessage: 'Expand this status' }, + report: { id: 'status.report', defaultMessage: 'Report @{name}' }, + muteConversation: { id: 'status.mute_conversation', defaultMessage: 'Mute conversation' }, + unmuteConversation: { id: 'status.unmute_conversation', defaultMessage: 'Unmute conversation' }, + pin: { id: 'status.pin', defaultMessage: 'Pin on profile' }, + unpin: { id: 'status.unpin', defaultMessage: 'Unpin from profile' }, + embed: { id: 'status.embed', defaultMessage: 'Embed' }, + admin_account: { id: 'status.admin_account', defaultMessage: 'Open moderation interface for @{name}' }, + admin_status: { id: 'status.admin_status', defaultMessage: 'Open this status in the moderation interface' }, + group_remove_account: { id: 'status.remove_account_from_group', defaultMessage: 'Remove account from group' }, + group_remove_post: { id: 'status.remove_post_from_group', defaultMessage: 'Remove status from group' }, +}) + +export default +@injectIntl +class StatusOptionsPopover extends ImmutablePureComponent { + static propTypes = { + status: ImmutablePropTypes.map.isRequired, + onOpenUnauthorizedModal: PropTypes.func.isRequired, + onOpenStatusSharePopover: PropTypes.func.isRequired, + onReply: PropTypes.func, + onQuote: PropTypes.func, + onFavorite: PropTypes.func, + onRepost: PropTypes.func, + onDelete: PropTypes.func, + onMention: PropTypes.func, + onMute: PropTypes.func, + onBlock: PropTypes.func, + onReport: PropTypes.func, + onEmbed: PropTypes.func, + onMuteConversation: PropTypes.func, + onPin: PropTypes.func, + withDismiss: PropTypes.bool, + withGroupAdmin: PropTypes.bool, + intl: PropTypes.object.isRequired, + } + + getItems = () => { + const { status, intl, withDismiss, withGroupAdmin } = this.props + const mutingConversation = status.get('muted') let menu = []; - // menu.push({ text: formatMessage(messages.open), action: this.handleOpen }); + menu.push({ + icon: 'circle', + hideArrow: true, + title: formatMessage(messages.open), + onClick: this.handleOpen + }); - // if (publicStatus) { - // menu.push({ text: formatMessage(messages.copy), action: this.handleCopy }); - // menu.push({ text: formatMessage(messages.embed), action: this.handleEmbed }); - // } + if (publicStatus) { + menu.push({ + icon: 'circle', + hideArrow: true, + title: formatMessage(messages.copy), + onClick: this.handleCopy, + }) + menu.push({ + icon: 'circle', + hideArrow: true, + title: formatMessage(messages.embed), + onClick: this.handleEmbed, + }) + } - // if (!me) return menu + if (!me) return menu - // menu.push(null); + if (status.getIn(['account', 'id']) === me || withDismiss) { + menu.push({ + icon: 'circle', + hideArrow: true, + title: formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), + onClick: this.handleConversationMuteClick, + }) + } - // if (status.getIn(['account', 'id']) === me || withDismiss) { - // menu.push({ text: formatMessage(mutingConversation ? messages.unmuteConversation : messages.muteConversation), action: this.handleConversationMuteClick }); - // menu.push(null); - // } + if (status.getIn(['account', 'id']) === me) { + if (publicStatus) { + menu.push({ + icon: 'circle', + hideArrow: true, + title: formatMessage(status.get('pinned') ? messages.unpin : messages.pin), + onClick: this.handlePinClick, + }) + } else { + if (status.get('visibility') === 'private') { + menu.push({ + title: formatMessage(status.get('reblogged') ? messages.cancel_repost_private : messages.repost_private), + onClick: this.handleRepostClick + }) + } + } + menu.push({ text: formatMessage(messages.delete), action: this.handleDeleteClick }); + menu.push({ text: formatMessage(messages.edit), action: this.handleEditClick }); + } else { + menu.push({ text: formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick }); + menu.push({ text: formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick }); + menu.push({ text: formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick }); + menu.push({ text: formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport }); - // if (status.getIn(['account', 'id']) === me) { - // if (publicStatus) { - // menu.push({ text: formatMessage(status.get('pinned') ? messages.unpin : messages.pin), action: this.handlePinClick }); - // } else { - // if (status.get('visibility') === 'private') { - // menu.push({ text: formatMessage(status.get('reblogged') ? messages.cancel_repost_private : messages.repost_private), action: this.handleRepostClick }); - // } - // } - // menu.push({ text: formatMessage(messages.delete), action: this.handleDeleteClick }); - // menu.push({ text: formatMessage(messages.edit), action: this.handleEditClick }); - // } else { - // menu.push({ text: formatMessage(messages.mention, { name: status.getIn(['account', 'username']) }), action: this.handleMentionClick }); - // menu.push(null); - // menu.push({ text: formatMessage(messages.mute, { name: status.getIn(['account', 'username']) }), action: this.handleMuteClick }); - // menu.push({ text: formatMessage(messages.block, { name: status.getIn(['account', 'username']) }), action: this.handleBlockClick }); - // menu.push({ text: formatMessage(messages.report, { name: status.getIn(['account', 'username']) }), action: this.handleReport }); + if (isStaff) { + menu.push({ text: formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` }); + menu.push({ text: formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` }); + } - // if (isStaff) { - // menu.push(null); - // menu.push({ text: formatMessage(messages.admin_account, { name: status.getIn(['account', 'username']) }), href: `/admin/accounts/${status.getIn(['account', 'id'])}` }); - // menu.push({ text: formatMessage(messages.admin_status), href: `/admin/accounts/${status.getIn(['account', 'id'])}/statuses/${status.get('id')}` }); - // } - - // if (withGroupAdmin) { - // menu.push(null); - // menu.push({ text: formatMessage(messages.group_remove_account), action: this.handleGroupRemoveAccount }); - // menu.push({ text: formatMessage(messages.group_remove_post), action: this.handleGroupRemovePost }); - // } - // } + if (withGroupAdmin) { + menu.push({ text: formatMessage(messages.group_remove_account), action: this.handleGroupRemoveAccount }); + menu.push({ text: formatMessage(messages.group_remove_post), action: this.handleGroupRemovePost }); + } + } return menu; } render() { + const items = this.getItems() + return ( diff --git a/app/javascript/gabsocial/features/compose/components/privacy_dropdown.js b/app/javascript/gabsocial/components/popover/status_privacy_popover.js similarity index 87% rename from app/javascript/gabsocial/features/compose/components/privacy_dropdown.js rename to app/javascript/gabsocial/components/popover/status_privacy_popover.js index 4efb554c..ef78c638 100644 --- a/app/javascript/gabsocial/features/compose/components/privacy_dropdown.js +++ b/app/javascript/gabsocial/components/popover/status_privacy_popover.js @@ -3,12 +3,12 @@ import spring from 'react-motion/lib/spring' import detectPassiveEvents from 'detect-passive-events' import classNames from 'classnames' import Overlay from 'react-overlays/lib/Overlay' -import { changeComposeVisibility } from '../../../actions/compose' -import { openModal, closeModal } from '../../../actions/modal' -import { isUserTouching } from '../../../utils/is_mobile' -import Motion from '../../ui/util/optional_motion' -import Icon from '../../../components/icon' -import ComposeExtraButton from './compose_extra_button' +import { changeComposeVisibility } from '../../actions/compose' +import { openModal, closeModal } from '../../actions/modal' +import { isUserTouching } from '../../utils/is_mobile' +import Motion from '../../features/ui/util/optional_motion' +import Icon from '../icon' +import ComposeExtraButton from '../../features/compose/components/compose_extra_button' const messages = defineMessages({ public_short: { id: 'privacy.public.short', defaultMessage: 'Public' }, @@ -246,25 +246,13 @@ class PrivacyDropdown extends PureComponent { const valueOption = this.options.find(item => item.value === value) return ( -
-
- -
- - - - -
+ ) } diff --git a/app/javascript/gabsocial/components/profile_header.js b/app/javascript/gabsocial/components/profile_header.js index 5a6e9c22..21da7138 100644 --- a/app/javascript/gabsocial/components/profile_header.js +++ b/app/javascript/gabsocial/components/profile_header.js @@ -105,14 +105,11 @@ class ProfileHeader extends ImmutablePureComponent { this.props.onFollow(this.props.account) } - handleUnrequest = () => { - // - } - handleBlock = () => { - // this.props.onBlock(this.props.account) + this.props.onBlock(this.props.account) } + // : todo : makeInfo() { const { account, intl } = this.props; @@ -135,28 +132,6 @@ class ProfileHeader extends ImmutablePureComponent { return info; }; - getActionBtn() { - const { account, intl } = this.props; - - let actionBtn = null; - - if (!account || !me) return actionBtn; - - if (me !== account.get('id')) { - if (!account.get('relationship')) { // Wait until the relationship is loaded - // - } else if (account.getIn(['relationship', 'requested'])) { - actionBtn = ) } } \ No newline at end of file diff --git a/app/javascript/gabsocial/components/status_action_bar.js b/app/javascript/gabsocial/components/status_action_bar.js index cedec947..bc0e8418 100644 --- a/app/javascript/gabsocial/components/status_action_bar.js +++ b/app/javascript/gabsocial/components/status_action_bar.js @@ -149,7 +149,7 @@ class StatusActionBar extends ImmutablePureComponent { const favoriteCount = status.get('favourites_count') // : todo : const shareButton = ('share' in navigator) && status.get('visibility') === 'public' && ( - + - )).reduce((aggregate, item) => [...aggregate, item, ' '], []); - - const toggleText = intl.formatMessage(hidden ? messages.showMore : messages.showLess); + )).reduce((aggregate, item) => [...aggregate, item, ' '], []) if (hidden) { - mentionsPlaceholder =
{mentionLinks}
; + mentionsPlaceholder = ( +
+ {mentionLinks} +
+ ) } + const toggleText = intl.formatMessage(hidden ? messages.showMore : messages.showLess) + + const spoilerContainerClasses = cx({ + default: 1, + py10: 1, + borderBottom1PX: !hidden, + borderColorSecondary: !hidden, + mb10: !hidden, + }) + + const statusContentClasses = cx({ + statusContent: 1, + displayNone: hidden, + }) + return ( -
- +
+ +
+
+ +
+
+ +
+ +
+
{mentionsPlaceholder} -
+
- ); + ) } else if (this.props.onClick) { const hasMarginBottom = !!status.get('card') || !!status.get('poll') || status.get('media_attachments').size > 0 @@ -256,7 +305,7 @@ class StatusContent extends ImmutablePureComponent { dangerouslySetInnerHTML={content} lang={status.get('language')} /> - ); + ) } } diff --git a/app/javascript/gabsocial/components/status_header.js b/app/javascript/gabsocial/components/status_header.js index 1672d37b..a1f9a939 100644 --- a/app/javascript/gabsocial/components/status_header.js +++ b/app/javascript/gabsocial/components/status_header.js @@ -12,24 +12,30 @@ import Icon from './icon' import Button from './button' import Avatar from './avatar' +const mapDispatchToProps = (dispatch) => ({ + onOpenStatusOptionsPopover(targetRef, status) { + dispatch(openPopover('STATUS_OPTIONS', { + targetRef, + status, + position: 'top', + })) + }, +}) + export default -@connect(null, null) +@connect(null, mapDispatchToProps) class StatusHeader extends ImmutablePureComponent { static propTypes = { status: ImmutablePropTypes.map, + onOpenStatusOptionsPopover: PropTypes.func.isRequired, } - handleStatusOptionsClick() { - console.log("handleStatusOptionsClick:", this.props) - this.props.dispatch(openPopover('STATUS_OPTIONS', { - targetRef: this.statusOptionsButton, - position: 'top', - status: this.props.status, - })) + handleOpenStatusOptionsPopover = () => { + this.props.onOpenStatusOptionsPopover(this.statusOptionsButton, this.props.status) } - handleOpenStatusEdits() { + handleOpenStatusEdits = () => { // : todo : this.props.dispatch(openPopover('REPOST', { targetRef: this.statusOptionsButton, @@ -150,7 +156,7 @@ class StatusHeader extends ImmutablePureComponent { iconHeight='20px' iconClassName={_s.fillColorSecondary} className={_s.marginLeftAuto} - onClick={this.handleStatusOptionsClick} + onClick={this.handleOpenStatusOptionsPopover} buttonRef={this.setStatusOptionsButton} />
diff --git a/app/javascript/gabsocial/components/switch.js b/app/javascript/gabsocial/components/switch.js index dc9b412a..dbe299f8 100644 --- a/app/javascript/gabsocial/components/switch.js +++ b/app/javascript/gabsocial/components/switch.js @@ -54,7 +54,7 @@ export default class Switch extends PureComponent { return (
- + {label} diff --git a/app/javascript/gabsocial/components/tab_bar_item.js b/app/javascript/gabsocial/components/tab_bar_item.js index 3b3a6460..2f691fc2 100644 --- a/app/javascript/gabsocial/components/tab_bar_item.js +++ b/app/javascript/gabsocial/components/tab_bar_item.js @@ -1,5 +1,7 @@ -import { NavLink, withRouter } from 'react-router-dom' +import { withRouter } from 'react-router-dom' import classNames from 'classnames/bind' +import Button from './button' +import Icon from './icon' import Text from './text' const cx = classNames.bind(_s) @@ -10,8 +12,11 @@ class TabBarItem extends PureComponent { static propTypes = { location: PropTypes.object.isRequired, title: PropTypes.string, + onClick: PropTypes.func, + icon: PropTypes.string, to: PropTypes.string, large: PropTypes.bool, + active: PropTypes.bool, } state = { @@ -31,7 +36,15 @@ class TabBarItem extends PureComponent { } render() { - const { title, to, location, large } = this.props + const { + title, + to, + onClick, + location, + large, + icon, + // active + } = this.props const { active } = this.state const isCurrent = active === -1 ? to === location.pathname : active @@ -46,6 +59,7 @@ class TabBarItem extends PureComponent { justifyContentCenter: 1, borderBottom2PX: 1, py5: 1, + backgroundTransparent: 1, borderColorTransparent: !isCurrent, borderColorBrand: isCurrent, mr5: large, @@ -68,14 +82,31 @@ class TabBarItem extends PureComponent { weight: isCurrent ? 'bold' : large ? 'medium' : 'normal', } + const iconOptions = { + id: icon, + width: !!large ? 20 : 14, + height: !!large ? 20 : 14, + } + return ( - + ) } } \ No newline at end of file diff --git a/app/javascript/gabsocial/components/text.js b/app/javascript/gabsocial/components/text.js index 1b61aa5f..af8be6df 100644 --- a/app/javascript/gabsocial/components/text.js +++ b/app/javascript/gabsocial/components/text.js @@ -42,6 +42,7 @@ export default class Text extends PureComponent { weight: PropTypes.oneOf(Object.keys(WEIGHTS)), align: PropTypes.oneOf(Object.keys(ALIGNMENTS)), underline: PropTypes.bool, + htmlFor: PropTypes.string, } static defaultProps = { @@ -60,7 +61,8 @@ export default class Text extends PureComponent { size, weight, underline, - align + align, + htmlFor } = this.props const classes = cx(className, { @@ -93,6 +95,7 @@ export default class Text extends PureComponent { return React.createElement( tagName, { + htmlFor, className: classes, }, children, diff --git a/app/javascript/gabsocial/features/compose/components/action_bar/action_bar.js b/app/javascript/gabsocial/features/compose/components/action_bar/action_bar.js deleted file mode 100644 index 82fff08d..00000000 --- a/app/javascript/gabsocial/features/compose/components/action_bar/action_bar.js +++ /dev/null @@ -1,62 +0,0 @@ -import { defineMessages, injectIntl } from 'react-intl'; -import { openModal } from '../../../../actions/modal'; -import { meUsername } from '../../../../initial_state'; - -const messages = defineMessages({ - profile: { id: 'account.profile', defaultMessage: 'Profile' }, - preferences: { id: 'navigation_bar.preferences', defaultMessage: 'Preferences' }, - follow_requests: { id: 'navigation_bar.follow_requests', defaultMessage: 'Follow requests' }, - blocks: { id: 'navigation_bar.blocks', defaultMessage: 'Blocked users' }, - domain_blocks: { id: 'navigation_bar.domain_blocks', defaultMessage: 'Hidden domains' }, - mutes: { id: 'navigation_bar.mutes', defaultMessage: 'Muted users' }, - filters: { id: 'navigation_bar.filters', defaultMessage: 'Muted words' }, - logout: { id: 'navigation_bar.logout', defaultMessage: 'Logout' }, - keyboard_shortcuts: { id: 'navigation_bar.keyboard_shortcuts', defaultMessage: 'Hotkeys' }, -}); - -const mapDispatchToProps = (dispatch) => ({ - onOpenHotkeys() { - dispatch(openModal('HOTKEYS')); - }, -}); - -class ActionBar extends PureComponent { - - static propTypes = { - intl: PropTypes.object.isRequired, - size: PropTypes.number, - }; - - handleHotkeyClick = () => { - this.props.onOpenHotkeys(); - } - - render () { - const { intl } = this.props; - const size = this.props.size || 16; - - let menu = []; - - menu.push({ text: intl.formatMessage(messages.profile), to: `/${meUsername}` }); - menu.push(null); - menu.push({ text: intl.formatMessage(messages.follow_requests), to: '/follow_requests' }); - menu.push({ text: intl.formatMessage(messages.mutes), to: '/mutes' }); - menu.push({ text: intl.formatMessage(messages.blocks), to: '/blocks' }); - menu.push({ text: intl.formatMessage(messages.domain_blocks), to: '/domain_blocks' }); - menu.push({ text: intl.formatMessage(messages.filters), href: '/filters' }); - menu.push(null); - menu.push({ text: intl.formatMessage(messages.keyboard_shortcuts), action: this.handleHotkeyClick }); - menu.push({ text: intl.formatMessage(messages.preferences), href: '/settings/preferences' }); - menu.push({ text: intl.formatMessage(messages.logout), href: '/auth/sign_out', isLogout: true }); - - return ( -
-
- { /* */ } -
-
- ); - } -} - -export default injectIntl(connect(null, mapDispatchToProps)(ActionBar)); diff --git a/app/javascript/gabsocial/features/compose/components/action_bar/index.js b/app/javascript/gabsocial/features/compose/components/action_bar/index.js deleted file mode 100644 index a923c5de..00000000 --- a/app/javascript/gabsocial/features/compose/components/action_bar/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './action_bar' \ No newline at end of file diff --git a/app/javascript/gabsocial/features/compose/components/character_counter/character_counter.js b/app/javascript/gabsocial/features/compose/components/character_counter.js similarity index 100% rename from app/javascript/gabsocial/features/compose/components/character_counter/character_counter.js rename to app/javascript/gabsocial/features/compose/components/character_counter.js diff --git a/app/javascript/gabsocial/features/compose/components/character_counter/character_counter.scss b/app/javascript/gabsocial/features/compose/components/character_counter/character_counter.scss deleted file mode 100644 index be284343..00000000 --- a/app/javascript/gabsocial/features/compose/components/character_counter/character_counter.scss +++ /dev/null @@ -1,16 +0,0 @@ -.character-counter { - cursor: default; - font-family: $font-sans-serif, sans-serif; - color: $gab-secondary-text; - - @include text-sizing(14px, 600); - - &--over { - color: $warning-red; - } - - &__wrapper { - align-self: center; - margin-right: 4px; - } -} \ No newline at end of file diff --git a/app/javascript/gabsocial/features/compose/components/character_counter/index.js b/app/javascript/gabsocial/features/compose/components/character_counter/index.js deleted file mode 100644 index 7e3488b1..00000000 --- a/app/javascript/gabsocial/features/compose/components/character_counter/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './character_counter' \ 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 25ad49b2..183bc0f1 100644 --- a/app/javascript/gabsocial/features/compose/components/compose_extra_button.js +++ b/app/javascript/gabsocial/features/compose/components/compose_extra_button.js @@ -1,5 +1,5 @@ import classNames from 'classnames/bind' -import Icon from '../../../components/icon' +import Button from '../../../components/button' const cx = classNames.bind(_s) @@ -13,18 +13,6 @@ export default class ComposeExtraButton extends PureComponent { active: PropTypes.bool, } - state = { - hovering: false, - } - - handleOnMouseEnter = () => { - this.setState({ hovering: true }) - } - - handleOnMouseLeave = () => { - this.setState({ hovering: false }) - } - render() { const { title, @@ -35,7 +23,6 @@ export default class ComposeExtraButton extends PureComponent { small, active } = this.props - const { hovering } = this.state const containerClasses = cx({ default: 1, @@ -44,13 +31,6 @@ export default class ComposeExtraButton extends PureComponent { }) const btnClasses = cx({ - default: 1, - circle: 1, - flexRow: 1, - cursorPointer: 1, - outlineNone: 1, - backgroundSubtle: !hovering && !active, - backgroundSubtle2: hovering && !active, backgroundColorBrandLight: active, py10: !small, px10: !small, @@ -58,18 +38,6 @@ export default class ComposeExtraButton extends PureComponent { px5: small, }) - const titleClasses = cx({ - default: 1, - ml5: 1, - text: 1, - lineHeight15: 1, - fontSize12PX: 1, - fontWeightMedium: 1, - colorSecondary: !active, - colorWhite: active, - displayNone: !hovering, - }) - const iconClasses = cx({ fillColorSecondary: !active, fillColorWhite: active, @@ -78,23 +46,18 @@ export default class ComposeExtraButton extends PureComponent { const iconSize = !!small ? '12px' : '18px' return ( -
- + backgroundColor='secondary' + iconClassName={iconClasses} + icon={icon} + iconWidth={iconSize} + iconHeight={iconSize} + /> {children}
) diff --git a/app/javascript/gabsocial/features/compose/components/compose_form/compose_form.js b/app/javascript/gabsocial/features/compose/components/compose_form/compose_form.js index 4a9c2d28..efe47284 100644 --- a/app/javascript/gabsocial/features/compose/components/compose_form/compose_form.js +++ b/app/javascript/gabsocial/features/compose/components/compose_form/compose_form.js @@ -10,7 +10,7 @@ import AutosuggestTextbox from '../../../../components/autosuggest_textbox'; import PollButton from '../../components/poll_button'; import UploadButton from '../../components/upload_button'; import SpoilerButton from '../../components/spoiler_button'; -import PrivacyDropdown from '../../components/privacy_dropdown'; +import PostPrivacyButton from '../../../../components/post_privacy_button'; import EmojiPickerButton from '../../components/emoji_picker_button' import EmojiPickerDropdown from '../../containers/emoji_picker_dropdown_container'; import PollFormContainer from '../../containers/poll_form_container'; @@ -230,7 +230,8 @@ class ComposeForm extends ImmutablePureComponent { quoteOfId, edit, scheduledAt, - spoiler + spoiler, + replyToId } = this.props const disabled = this.props.isSubmitting; const text = [this.props.spoilerText, countableText(this.props.text)].join(''); @@ -239,7 +240,7 @@ class ComposeForm extends ImmutablePureComponent { const containerClasses = cx({ default: 1, - flexGrow1: 1, + flexNormal: 1, flexRow: shouldCondense, radiusSmall: shouldCondense, backgroundSubtle: shouldCondense, @@ -326,10 +327,10 @@ class ComposeForm extends ImmutablePureComponent { >
- + { !edit && - + }
@@ -345,7 +346,7 @@ class ComposeForm extends ImmutablePureComponent { } { !shouldCondense && - + } diff --git a/app/javascript/gabsocial/features/compose/components/navigation_bar/navigation_bar.js b/app/javascript/gabsocial/features/compose/components/navigation_bar/navigation_bar.js index f3af21bd..a71c19dc 100644 --- a/app/javascript/gabsocial/features/compose/components/navigation_bar/navigation_bar.js +++ b/app/javascript/gabsocial/features/compose/components/navigation_bar/navigation_bar.js @@ -1,10 +1,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage } from 'react-intl'; -import ActionBar from '../action_bar'; import Avatar from '../../../../components/avatar'; import Button from '../../../../components/button' -import IconButton from '../../../../components/icon_button'; import { me } from '../../../../initial_state'; const mapStateToProps = state => { @@ -43,8 +41,7 @@ class NavigationBar extends ImmutablePureComponent {
- - +
); diff --git a/app/javascript/gabsocial/features/compose/components/post_privacy_button.js b/app/javascript/gabsocial/features/compose/components/post_privacy_button.js new file mode 100644 index 00000000..4f9f78fd --- /dev/null +++ b/app/javascript/gabsocial/features/compose/components/post_privacy_button.js @@ -0,0 +1,65 @@ +import { defineMessages, injectIntl } from 'react-intl' +import { addPoll, removePoll } from '../../../actions/compose' +import ComposeExtraButton from './compose_extra_button' + +const messages = defineMessages({ + add_poll: { id: 'poll_button.add_poll', defaultMessage: 'Add poll' }, + title: { id: 'poll_button.title', defaultMessage: 'Poll' }, + remove_poll: { id: 'poll_button.remove_poll', defaultMessage: 'Remove poll' }, +}) + +const mapStateToProps = state => ({ + unavailable: state.getIn(['compose', 'is_uploading']) || (state.getIn(['compose', 'media_attachments']).size > 0), + active: state.getIn(['compose', 'poll']) !== null, +}) + +const mapDispatchToProps = dispatch => ({ + + onClick() { + dispatch((_, getState) => { + if (getState().getIn(['compose', 'poll'])) { + dispatch(removePoll()) + } else { + dispatch(addPoll()) + } + }) + }, + +}) + +export default +@connect(mapStateToProps, mapDispatchToProps) +@injectIntl +class PollButton extends PureComponent { + + static propTypes = { + disabled: PropTypes.bool, + unavailable: PropTypes.bool, + active: PropTypes.bool, + onClick: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + small: PropTypes.bool, + } + + handleClick = () => { + this.props.onClick() + } + + render() { + const { intl, active, unavailable, disabled, small } = this.props + + if (unavailable) return null + + return ( + + ) + } + +} diff --git a/app/javascript/gabsocial/features/compose/components/quoted_status_preview.js b/app/javascript/gabsocial/features/compose/components/quoted_status_preview.js index c2443ef6..0047f3ac 100644 --- a/app/javascript/gabsocial/features/compose/components/quoted_status_preview.js +++ b/app/javascript/gabsocial/features/compose/components/quoted_status_preview.js @@ -2,6 +2,8 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import DisplayName from '../../../components/display_name'; import StatusContent from '../../../components/status_content'; +// : todo : do we need this? make work inside of status/status content + export default class QuotedStatusPreview extends PureComponent { static propTypes = { status: ImmutablePropTypes.map, diff --git a/app/javascript/gabsocial/features/compose/components/reply_indicator/reply_indicator.js b/app/javascript/gabsocial/features/compose/components/reply_indicator/reply_indicator.js index cf53401f..b8f5c626 100644 --- a/app/javascript/gabsocial/features/compose/components/reply_indicator/reply_indicator.js +++ b/app/javascript/gabsocial/features/compose/components/reply_indicator/reply_indicator.js @@ -3,7 +3,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl } from 'react-intl'; import { NavLink } from 'react-router-dom'; import Avatar from '../../../../components/avatar'; -import IconButton from '../../../../components/icon_button'; +import Button from '../../../../components/button'; import DisplayName from '../../../../components/display_name'; import { isRtl } from '../../../../utils/rtl'; @@ -45,7 +45,7 @@ class ReplyIndicator extends ImmutablePureComponent {
- +
diff --git a/app/javascript/gabsocial/features/compose/components/sensitive_media_button.js b/app/javascript/gabsocial/features/compose/components/sensitive_media_button.js new file mode 100644 index 00000000..ddc33795 --- /dev/null +++ b/app/javascript/gabsocial/features/compose/components/sensitive_media_button.js @@ -0,0 +1,51 @@ +import { injectIntl, defineMessages } from 'react-intl' +import { changeComposeSensitivity } from '../../../actions/compose' +import Switch from '../../../components/switch' + +const messages = defineMessages({ + markAsSensitive: { id: 'compose_form.sensitive.hide', defaultMessage: 'Mark media as sensitive' }, +}) + +const mapStateToProps = state => ({ + active: state.getIn(['compose', 'sensitive']), + disabled: state.getIn(['compose', 'spoiler']), +}) + +const mapDispatchToProps = dispatch => ({ + + onClick () { + dispatch(changeComposeSensitivity()) + }, + +}) + +export default +@injectIntl +@connect(mapStateToProps, mapDispatchToProps) +class SensitiveMediaButton extends PureComponent { + + static propTypes = { + active: PropTypes.bool, + disabled: PropTypes.bool, + onClick: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + } + + render () { + const { active, disabled, onClick, intl } = this.props + + return ( +
+ +
+ ) + } + +} diff --git a/app/javascript/gabsocial/features/compose/components/upload.js b/app/javascript/gabsocial/features/compose/components/upload.js new file mode 100644 index 00000000..1db6e958 --- /dev/null +++ b/app/javascript/gabsocial/features/compose/components/upload.js @@ -0,0 +1,178 @@ +import ImmutablePropTypes from 'react-immutable-proptypes' +import ImmutablePureComponent from 'react-immutable-pure-component' +import { defineMessages, injectIntl } from 'react-intl' +import classNames from 'classnames/bind' +import { undoUploadCompose, changeUploadCompose } from '../../../actions/compose' +import { submitCompose } from '../../../actions/compose'; +import Button from '../../../components/button' +import Image from '../../../components/image' +import Input from '../../../components/input' + +const cx = classNames.bind(_s) + +const messages = defineMessages({ + description: { id: 'upload_form.description', defaultMessage: 'Describe for the visually impaired' }, + delete: { id: 'upload_form.undo', defaultMessage: 'Delete' }, +}) + +const mapStateToProps = (state, { id, otherProps }) => { + console.log("otherProps:", otherProps) + return { + media: state.getIn(['compose', 'media_attachments']).find(item => item.get('id') === id), + } +} + +const mapDispatchToProps = dispatch => ({ + + onUndo: id => { + dispatch(undoUploadCompose(id)); + }, + + onDescriptionChange: (id, description) => { + dispatch(changeUploadCompose(id, { description })); + }, + + onSubmit (router) { + dispatch(submitCompose(router)); + }, + +}); + +export default +@injectIntl +@connect(mapStateToProps, mapDispatchToProps) +class Upload extends ImmutablePureComponent { + + static contextTypes = { + router: PropTypes.object, + } + + static propTypes = { + media: ImmutablePropTypes.map.isRequired, + intl: PropTypes.object.isRequired, + onUndo: PropTypes.func.isRequired, + onDescriptionChange: PropTypes.func.isRequired, + onSubmit: PropTypes.func.isRequired, + } + + state = { + hovered: false, + focused: false, + dirtyDescription: null, + } + + handleKeyDown = (e) => { + if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) { + this.handleSubmit() + } + } + + handleSubmit = () => { + this.handleInputBlur() + this.props.onSubmit(this.context.router.history) + } + + handleUndoClick = e => { + e.stopPropagation() + this.props.onUndo(this.props.media.get('id')) + } + + handleInputChange = e => { + this.setState({ dirtyDescription: e.target.value }) + } + + handleMouseEnter = () => { + this.setState({ hovered: true }) + } + + handleMouseLeave = () => { + this.setState({ hovered: false }) + } + + handleInputFocus = () => { + this.setState({ focused: true }) + } + + handleClick = () => { + this.setState({ focused: true }) + } + + handleInputBlur = () => { + const { dirtyDescription } = this.state + + this.setState({ + focused: false, + dirtyDescription: null, + }) + + if (dirtyDescription !== null) { + this.props.onDescriptionChange(this.props.media.get('id'), dirtyDescription) + } + } + + render() { + const { intl, media } = this.props + const active = this.state.hovered || this.state.focused + const description = this.state.dirtyDescription || (this.state.dirtyDescription !== '' && media.get('description')) || '' + + const descriptionContainerClasses = cx({ + default: 1, + positionAbsolute: 1, + right0: 1, + bottom0: 1, + left0: 1, + my5: 1, + ml5: 1, + mr5: 1, + displayNone: !active, + }) + + console.log("media:", media) + + return ( +
+
+ +
+
+ ) + } + +} diff --git a/app/javascript/gabsocial/features/compose/components/upload/index.js b/app/javascript/gabsocial/features/compose/components/upload/index.js deleted file mode 100644 index e482ed01..00000000 --- a/app/javascript/gabsocial/features/compose/components/upload/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './upload' \ No newline at end of file diff --git a/app/javascript/gabsocial/features/compose/components/upload/upload.js b/app/javascript/gabsocial/features/compose/components/upload/upload.js deleted file mode 100644 index 414c6860..00000000 --- a/app/javascript/gabsocial/features/compose/components/upload/upload.js +++ /dev/null @@ -1,126 +0,0 @@ -import ImmutablePropTypes from 'react-immutable-proptypes' -import ImmutablePureComponent from 'react-immutable-pure-component' -import { defineMessages, injectIntl } from 'react-intl' -import classNames from 'classnames' -import Button from '../../../../components/button' -import Image from '../../../../components/image' - -const messages = defineMessages({ - description: { id: 'upload_form.description', defaultMessage: 'Describe for the visually impaired' }, - delete: { id: 'upload_form.undo', defaultMessage: 'Delete' }, -}) - -export default -@injectIntl -class Upload extends ImmutablePureComponent { - - static contextTypes = { - router: PropTypes.object, - } - - static propTypes = { - media: ImmutablePropTypes.map.isRequired, - intl: PropTypes.object.isRequired, - onUndo: PropTypes.func.isRequired, - onDescriptionChange: PropTypes.func.isRequired, - onSubmit: PropTypes.func.isRequired, - } - - state = { - hovered: false, - focused: false, - dirtyDescription: null, - } - - handleKeyDown = (e) => { - if (e.keyCode === 13 && (e.ctrlKey || e.metaKey)) { - this.handleSubmit() - } - } - - handleSubmit = () => { - this.handleInputBlur() - this.props.onSubmit(this.context.router.history) - } - - handleUndoClick = e => { - e.stopPropagation() - this.props.onUndo(this.props.media.get('id')) - } - - handleInputChange = e => { - this.setState({ dirtyDescription: e.target.value }) - } - - handleMouseEnter = () => { - this.setState({ hovered: true }) - } - - handleMouseLeave = () => { - this.setState({ hovered: false }) - } - - handleInputFocus = () => { - this.setState({ focused: true }) - } - - handleClick = () => { - this.setState({ focused: true }) - } - - handleInputBlur = () => { - const { dirtyDescription } = this.state - - this.setState({ - focused: false, - dirtyDescription: null, - }) - - if (dirtyDescription !== null) { - this.props.onDescriptionChange(this.props.media.get('id'), dirtyDescription) - } - } - - render() { - const { intl, media } = this.props - const active = this.state.hovered || this.state.focused - const description = this.state.dirtyDescription || (this.state.dirtyDescription !== '' && media.get('description')) || '' - const focusX = media.getIn(['meta', 'focus', 'x']) - const focusY = media.getIn(['meta', 'focus', 'y']) - const x = ((focusX / 2) + .5) * 100 - const y = ((focusY / -2) + .5) * 100 - - return ( -
-
-
-
- -
-