diff --git a/app/javascript/gabsocial/components/account/account.js b/app/javascript/gabsocial/components/account/account.js index 4a8d7303..430ed993 100644 --- a/app/javascript/gabsocial/components/account/account.js +++ b/app/javascript/gabsocial/components/account/account.js @@ -21,7 +21,8 @@ const messages = defineMessages({ unmute_notifications: { id: 'account.unmute_notifications', defaultMessage: 'Unmute notifications from @{name}' }, }) -export default @injectIntl +export default +@injectIntl class Account extends ImmutablePureComponent { static propTypes = { diff --git a/app/javascript/gabsocial/components/autosuggest_account/autosuggest_account.js b/app/javascript/gabsocial/components/autosuggest_account/autosuggest_account.js index 6ff06fcb..28510322 100644 --- a/app/javascript/gabsocial/components/autosuggest_account/autosuggest_account.js +++ b/app/javascript/gabsocial/components/autosuggest_account/autosuggest_account.js @@ -14,7 +14,8 @@ const makeMapStateToProps = () => { return mapStateToProps; }; -export default @connect(makeMapStateToProps) +export default +@connect(makeMapStateToProps) class AutosuggestAccount extends ImmutablePureComponent { static propTypes = { diff --git a/app/javascript/gabsocial/components/bundle_column_error/bundle_column_error.js b/app/javascript/gabsocial/components/bundle_column_error/bundle_column_error.js index 3358197b..6e51f404 100644 --- a/app/javascript/gabsocial/components/bundle_column_error/bundle_column_error.js +++ b/app/javascript/gabsocial/components/bundle_column_error/bundle_column_error.js @@ -8,7 +8,8 @@ const messages = defineMessages({ retry: { id: 'bundle_column_error.retry', defaultMessage: 'Try again' }, }); -export default @injectIntl +export default +@injectIntl class BundleColumnError extends PureComponent { static propTypes = { diff --git a/app/javascript/gabsocial/components/bundle_modal_error/bundle_modal_error.js b/app/javascript/gabsocial/components/bundle_modal_error.js similarity index 95% rename from app/javascript/gabsocial/components/bundle_modal_error/bundle_modal_error.js rename to app/javascript/gabsocial/components/bundle_modal_error.js index 799b62b5..a1f0bf60 100644 --- a/app/javascript/gabsocial/components/bundle_modal_error/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 IconButton from './icon_button'; const messages = defineMessages({ error: { id: 'bundle_modal_error.message', defaultMessage: 'Something went wrong while loading this component.' }, @@ -7,7 +7,8 @@ const messages = defineMessages({ close: { id: 'bundle_modal_error.close', defaultMessage: 'Close' }, }); -export default @injectIntl +export default +@injectIntl class BundleModalError extends PureComponent { static propTypes = { diff --git a/app/javascript/gabsocial/components/bundle_modal_error/bundle_modal_error.scss b/app/javascript/gabsocial/components/bundle_modal_error/bundle_modal_error.scss deleted file mode 100644 index e69de29b..00000000 diff --git a/app/javascript/gabsocial/components/bundle_modal_error/index.js b/app/javascript/gabsocial/components/bundle_modal_error/index.js deleted file mode 100644 index 8cfc4461..00000000 --- a/app/javascript/gabsocial/components/bundle_modal_error/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './bundle_modal_error'; \ No newline at end of file diff --git a/app/javascript/gabsocial/components/column_header.js b/app/javascript/gabsocial/components/column_header.js index 14c428d0..a6cc9178 100644 --- a/app/javascript/gabsocial/components/column_header.js +++ b/app/javascript/gabsocial/components/column_header.js @@ -9,7 +9,8 @@ const messages = defineMessages({ hide: { id: 'column_header.hide_settings', defaultMessage: 'Hide settings' }, }) -export default @injectIntl +export default +@injectIntl class ColumnHeader extends PureComponent { static contextTypes = { diff --git a/app/javascript/gabsocial/components/column_indicator.js b/app/javascript/gabsocial/components/column_indicator.js index 928edff4..9d79cf91 100644 --- a/app/javascript/gabsocial/components/column_indicator.js +++ b/app/javascript/gabsocial/components/column_indicator.js @@ -6,7 +6,8 @@ const messages = defineMessages({ missing: { id: 'missing_indicator.sublabel', defaultMessage: 'This resource could not be found.' }, }) -export default @injectIntl +export default +@injectIntl class ColumnIndicator extends PureComponent { static propTypes = { diff --git a/app/javascript/gabsocial/components/domain/domain.js b/app/javascript/gabsocial/components/domain/domain.js index 425075ae..ccc5476b 100644 --- a/app/javascript/gabsocial/components/domain/domain.js +++ b/app/javascript/gabsocial/components/domain/domain.js @@ -5,7 +5,8 @@ const messages = defineMessages({ unblockDomain: { id: 'account.unblock_domain', defaultMessage: 'Unhide {domain}' }, }); -export default @injectIntl +export default +@injectIntl class Domain extends PureComponent { static propTypes = { diff --git a/app/javascript/gabsocial/components/dropdown_menu/dropdown_menu.js b/app/javascript/gabsocial/components/dropdown_menu/dropdown_menu.js index 1aee3168..305cf022 100644 --- a/app/javascript/gabsocial/components/dropdown_menu/dropdown_menu.js +++ b/app/javascript/gabsocial/components/dropdown_menu/dropdown_menu.js @@ -3,12 +3,36 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import detectPassiveEvents from 'detect-passive-events'; import Overlay from 'react-overlays/lib/Overlay'; import spring from 'react-motion/lib/spring'; -import Motion from '../../features/ui/util/optional_motion'; +import { openDropdownMenu, closeDropdownMenu } from '../../actions/dropdown_menu'; +import { openModal, closeModal } from '../../actions/modal'; +import { isUserTouching } from '../../utils/is_mobile'; +import Motion from '../../features/ui/util/optional_motion' import IconButton from '../icon_button'; const listenerOptions = detectPassiveEvents.hasSupport ? { passive: true } : false; let id = 0; +const mapStateToProps = state => ({ + isModalOpen: state.get('modal').modalType === 'ACTIONS', + dropdownPlacement: state.getIn(['dropdown_menu', 'placement']), + openDropdownId: state.getIn(['dropdown_menu', 'openId']), + openedViaKeyboard: state.getIn(['dropdown_menu', 'keyboard']), +}); + +const mapDispatchToProps = (dispatch, { status, items }) => ({ + onOpen(id, onItemClick, dropdownPlacement, keyboard) { + dispatch(isUserTouching() ? openModal('ACTIONS', { + status, + actions: items, + onClick: onItemClick, + }) : openDropdownMenu(id, dropdownPlacement, keyboard)); + }, + onClose(id) { + dispatch(closeModal()); + dispatch(closeDropdownMenu(id)); + }, +}); + class DropdownMenu extends PureComponent { static contextTypes = { @@ -158,7 +182,9 @@ class DropdownMenu extends PureComponent { } -export default class Dropdown extends ImmutablePureComponent { +export default +@connect(mapStateToProps, mapDispatchToProps) +class Dropdown extends ImmutablePureComponent { static contextTypes = { router: PropTypes.object, diff --git a/app/javascript/gabsocial/components/floating_action_button/floating_action_button.js b/app/javascript/gabsocial/components/floating_action_button.js similarity index 69% rename from app/javascript/gabsocial/components/floating_action_button/floating_action_button.js rename to app/javascript/gabsocial/components/floating_action_button.js index ce84b6f8..ebf02876 100644 --- a/app/javascript/gabsocial/components/floating_action_button/floating_action_button.js +++ b/app/javascript/gabsocial/components/floating_action_button.js @@ -1,4 +1,5 @@ -import ComposeIcon from './assets/compose_icon'; +import Icon from './icon' +import Button from './button' export default class FloatingActionButton extends Component { static propTypes = { @@ -14,9 +15,9 @@ export default class FloatingActionButton extends Component { const { onClick, message } = this.props; return ( - + ) } } \ No newline at end of file diff --git a/app/javascript/gabsocial/components/floating_action_button/assets/compose_icon.js b/app/javascript/gabsocial/components/floating_action_button/assets/compose_icon.js deleted file mode 100644 index c9cb3098..00000000 --- a/app/javascript/gabsocial/components/floating_action_button/assets/compose_icon.js +++ /dev/null @@ -1,25 +0,0 @@ -const ComposeIcon = ({ - className = 'compose-icon', - width = '26px', - height = '26px', - viewBox = '0 0 50 50' -}) => ( - - - - - - - - - -) - -export default ComposeIcon \ No newline at end of file diff --git a/app/javascript/gabsocial/components/floating_action_button/floating_action_button.scss b/app/javascript/gabsocial/components/floating_action_button/floating_action_button.scss deleted file mode 100644 index 94e114c8..00000000 --- a/app/javascript/gabsocial/components/floating_action_button/floating_action_button.scss +++ /dev/null @@ -1,28 +0,0 @@ -.floating-action-button { - display: none; - position: fixed; - z-index: 1000; - border: none; - background-color: $gab-brand-default; - padding-top: 6px; - padding-left: 10px; - - @include circle(56px); - @include abs-position(auto, 14px, 14px, auto, false); - - @media screen and (max-width: $nav-breakpoint-3) { - display: block !important; - } - - &:hover, - &:focus, - &:active { - background-color: lighten($gab-brand-default, 5%); - } - - .compose-icon { - &__path { - fill: #fff; - } - } -} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/floating_action_button/index.js b/app/javascript/gabsocial/components/floating_action_button/index.js deleted file mode 100644 index 6e9ddb44..00000000 --- a/app/javascript/gabsocial/components/floating_action_button/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './floating_action_button'; \ No newline at end of file diff --git a/app/javascript/gabsocial/components/group_list_item/group_list_item.js b/app/javascript/gabsocial/components/group_list_item/group_list_item.js deleted file mode 100644 index 45b747d6..00000000 --- a/app/javascript/gabsocial/components/group_list_item/group_list_item.js +++ /dev/null @@ -1,39 +0,0 @@ -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import { defineMessages, injectIntl } from 'react-intl'; -import { Link } from 'react-router-dom'; -import { shortNumberFormat } from '../../utils/numbers'; - -const messages = defineMessages({ - members: { id: 'groups.card.members', defaultMessage: 'Members' }, -}); - -export default -@injectIntl -class GroupListItem extends ImmutablePureComponent { - static propTypes = { - group: ImmutablePropTypes.map.isRequired, - } - - render() { - const { intl, group } = this.props; - - if (!group) return null; - - return ( -
-
- - {group.get('title')} -
- - {shortNumberFormat(group.get('member_count'))} -   - {intl.formatMessage(messages.members)} - - -
-
- ); - } -} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/group_list_item/index.js b/app/javascript/gabsocial/components/group_list_item/index.js deleted file mode 100644 index e69de29b..00000000 diff --git a/app/javascript/gabsocial/components/layouts/profile_layout.js b/app/javascript/gabsocial/components/layouts/profile_layout.js deleted file mode 100644 index aceffd2d..00000000 --- a/app/javascript/gabsocial/components/layouts/profile_layout.js +++ /dev/null @@ -1,39 +0,0 @@ -import Sidebar from '../sidebar' - -export default class ProfileLayout extends PureComponent { - static propTypes = { - layout: PropTypes.object, - title: PropTypes.string, - showBackBtn: PropTypes.bool, - } - - render() { - const { children } = this.props - - return ( -
- - - -
- -
- -
- -
-
- {children} -
-
- -
- -
- ) - } - -} diff --git a/app/javascript/gabsocial/components/link_footer.js b/app/javascript/gabsocial/components/link_footer.js index 12d9c120..6b99852a 100644 --- a/app/javascript/gabsocial/components/link_footer.js +++ b/app/javascript/gabsocial/components/link_footer.js @@ -33,7 +33,8 @@ const mapDispatchToProps = (dispatch) => ({ }, }) -export default @connect(null, mapDispatchToProps) +export default +@connect(null, mapDispatchToProps) @injectIntl class LinkFooter extends PureComponent { diff --git a/app/javascript/gabsocial/components/load_more.js b/app/javascript/gabsocial/components/load_more.js index 61573967..01e96b05 100644 --- a/app/javascript/gabsocial/components/load_more.js +++ b/app/javascript/gabsocial/components/load_more.js @@ -5,7 +5,8 @@ const messages = defineMessages({ load_more: { id: 'status.load_more', defaultMessage: 'Load more' }, }) -export default @injectIntl +export default +@injectIntl class LoadMore extends PureComponent { static propTypes = { diff --git a/app/javascript/gabsocial/components/modal/hotkeys_modal.js b/app/javascript/gabsocial/components/modal/hotkeys_modal.js new file mode 100644 index 00000000..21e1626c --- /dev/null +++ b/app/javascript/gabsocial/components/modal/hotkeys_modal.js @@ -0,0 +1,153 @@ +import { defineMessages, injectIntl } from 'react-intl' +import ImmutablePureComponent from 'react-immutable-pure-component' +import ModalLayout from './modal_layout' +import Text from '../text' +import Heading from '../heading' + +const messages = defineMessages({ + heading: { id: 'keyboard_shortcuts.heading', defaultMessage: 'Keyboard Shortcuts' }, + close: { id: 'lightbox.close', defaultMessage: 'Close' }, + hotkey: { id: 'keyboard_shortcuts.hotkey', defaultMessage: 'Hotkey' }, + reply: { id: 'keyboard_shortcuts.reply', defaultMessage: 'reply' }, + mention: { id: 'keyboard_shortcuts.mention', defaultMessage: 'mention author' }, + profile: { id: 'keyboard_shortcuts.profile', defaultMessage: 'open author\'s profile' }, + favourite: { id: 'keyboard_shortcuts.favourite', defaultMessage: 'favorite' }, + boost: { id: 'keyboard_shortcuts.boost', defaultMessage: 'repost' }, + enter: { id: 'keyboard_shortcuts.enter', defaultMessage: 'open status' }, + toggle_hidden: { id: 'keyboard_shortcuts.toggle_hidden', defaultMessage: 'show/hide text behind CW' }, + toggle_sensitivity: { id: 'keyboard_shortcuts.toggle_sensitivity', defaultMessage: 'show/hide media' }, + up: { id: 'keyboard_shortcuts.up', defaultMessage: 'move up in the list' }, + down: { id: 'keyboard_shortcuts.down', defaultMessage: 'move down in the list' }, + column: { id: 'keyboard_shortcuts.column', defaultMessage: 'focus a status in one of the columns' }, + compose: { id: 'keyboard_shortcuts.compose', defaultMessage: 'focus the compose textarea' }, + gab: { id: 'keyboard_shortcuts.toot', defaultMessage: 'start a brand new gab' }, + back: { id: 'keyboard_shortcuts.back', defaultMessage: 'navigate back' }, + search: { id: 'keyboard_shortcuts.search', defaultMessage: 'focus search' }, + unfocus: { id: 'keyboard_shortcuts.unfocus', defaultMessage: 'un-focus compose textarea/search' }, + home: { id: 'keyboard_shortcuts.home', defaultMessage: 'open home timeline' }, + notifications: { id: 'keyboard_shortcuts.notifications', defaultMessage: 'open notifications column' }, + direct: { id: 'keyboard_shortcuts.direct', defaultMessage: 'open direct messages column' }, + start: { id: 'keyboard_shortcuts.start', defaultMessage: 'open "get started" column' }, + favourites: { id: 'keyboard_shortcuts.favourites', defaultMessage: 'open favorites list' }, + pinned: { id: 'keyboard_shortcuts.pinned', defaultMessage: 'open pinned gabs list' }, + my_profile: { id: 'keyboard_shortcuts.my_profile', defaultMessage: 'open your profile' }, + blocked: { id: 'keyboard_shortcuts.blocked', defaultMessage: 'open blocked users list' }, + muted: { id: 'keyboard_shortcuts.muted', defaultMessage: 'open muted users list' }, + requests: { id: 'keyboard_shortcuts.requests', defaultMessage: 'open follow requests list' }, + legend: { id: 'keyboard_shortcuts.legend', defaultMessage: 'display this legend' }, +}) + +export default +@injectIntl +class HotkeysModal extends ImmutablePureComponent { + + static propTypes = { + intl: PropTypes.object.isRequired, + } + + render() { + const { intl } = this.props + + return ( + +
+ + + + + + + + + + + + + + + + + +
+ + {intl.formatMessage(messages.hotkey)} + +
+ + + + + + + + + + + + + + + + + + +
+ + {intl.formatMessage(messages.hotkey)} + +
+ + + + + + + + + + + + + + + + +
+ + {intl.formatMessage(messages.hotkey)} + +
+
+
+ ) + } + +} + +class HotKeysModalRow extends PureComponent { + static propTypes = { + hotkey: PropTypes.string.isRequired, + action: PropTypes.string.isRequired, + } + + render() { + const { hotkey, action } = this.props + + return ( + + + + + {hotkey} + + + + + + {action} + + + + ) + } +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/modal/hotkeys_modal/hotkeys_modal.js b/app/javascript/gabsocial/components/modal/hotkeys_modal/hotkeys_modal.js deleted file mode 100644 index 8fd17864..00000000 --- a/app/javascript/gabsocial/components/modal/hotkeys_modal/hotkeys_modal.js +++ /dev/null @@ -1,206 +0,0 @@ -import { defineMessages, injectIntl } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import IconButton from '../../icon_button'; - -const messages = defineMessages({ - heading: { id: 'keyboard_shortcuts.heading', defaultMessage: 'Keyboard Shortcuts' }, - close: { id: 'lightbox.close', defaultMessage: 'Close' }, - hotkey: { id: 'keyboard_shortcuts.hotkey', defaultMessage: 'Hotkey' }, - reply: { id: 'keyboard_shortcuts.reply', defaultMessage: 'reply' }, - mention: { id: 'keyboard_shortcuts.mention', defaultMessage: 'mention author' }, - profile: { id: 'keyboard_shortcuts.profile', defaultMessage: 'open author\'s profile' }, - favourite: { id: 'keyboard_shortcuts.favourite', defaultMessage: 'favorite' }, - boost: { id: 'keyboard_shortcuts.boost', defaultMessage: 'repost' }, - enter: { id: 'keyboard_shortcuts.enter', defaultMessage: 'open status' }, - toggle_hidden: { id: 'keyboard_shortcuts.toggle_hidden', defaultMessage: 'show/hide text behind CW' }, - toggle_sensitivity: { id: 'keyboard_shortcuts.toggle_sensitivity', defaultMessage: 'show/hide media' }, - up: { id: 'keyboard_shortcuts.up', defaultMessage: 'move up in the list' }, - down: { id: 'keyboard_shortcuts.down', defaultMessage: 'move down in the list' }, - column: { id: 'keyboard_shortcuts.column', defaultMessage: 'focus a status in one of the columns' }, - compose: { id: 'keyboard_shortcuts.compose', defaultMessage: 'focus the compose textarea' }, - gab: { id: 'keyboard_shortcuts.toot', defaultMessage: 'start a brand new gab' }, - back: { id: 'keyboard_shortcuts.back', defaultMessage: 'navigate back' }, - search: { id: 'keyboard_shortcuts.search', defaultMessage: 'focus search' }, - unfocus: { id: 'keyboard_shortcuts.unfocus', defaultMessage: 'un-focus compose textarea/search' }, - home: { id: 'keyboard_shortcuts.home', defaultMessage: 'open home timeline' }, - notifications: { id: 'keyboard_shortcuts.notifications', defaultMessage: 'open notifications column' }, - direct: { id: 'keyboard_shortcuts.direct', defaultMessage: 'open direct messages column' }, - start: { id: 'keyboard_shortcuts.start', defaultMessage: 'open "get started" column' }, - favourites: { id: 'keyboard_shortcuts.favourites', defaultMessage: 'open favorites list' }, - pinned: { id: 'keyboard_shortcuts.pinned', defaultMessage: 'open pinned gabs list' }, - my_profile: { id: 'keyboard_shortcuts.my_profile', defaultMessage: 'open your profile' }, - blocked: { id: 'keyboard_shortcuts.blocked', defaultMessage: 'open blocked users list' }, - muted: { id: 'keyboard_shortcuts.muted', defaultMessage: 'open muted users list' }, - requests: { id: 'keyboard_shortcuts.requests', defaultMessage: 'open follow requests list' }, - legend: { id: 'keyboard_shortcuts.legend', defaultMessage: 'display this legend' }, -}); - -export default @injectIntl -class HotkeysModal extends ImmutablePureComponent { - - static propTypes = { - intl: PropTypes.object.isRequired, - onClose: PropTypes.func.isRequired, - }; - - render () { - const { intl, onClose } = this.props; - - return ( -
-
-
-

- {intl.formatMessage(messages.heading)} -

- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{intl.formatMessage(messages.hotkey)}
r{intl.formatMessage(messages.reply)}
m{intl.formatMessage(messages.mention)}
p{intl.formatMessage(messages.profile)}
f{intl.formatMessage(messages.favourite)}
b{intl.formatMessage(messages.boost)}
enter, o{intl.formatMessage(messages.enter)}
x{intl.formatMessage(messages.toggle_hidden)}
h{intl.formatMessage(messages.toggle_sensitivity)}
up, k{intl.formatMessage(messages.up)}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{intl.formatMessage(messages.hotkey)}
down, j{intl.formatMessage(messages.down)}
1 - 9{intl.formatMessage(messages.column)}
n{intl.formatMessage(messages.compose)}
alt + n{intl.formatMessage(messages.gab)}
backspace{intl.formatMessage(messages.back)}
s{intl.formatMessage(messages.search)}
esc{intl.formatMessage(messages.unfocus)}
g + h{intl.formatMessage(messages.home)}
g + n{intl.formatMessage(messages.notifications)}
g + d{intl.formatMessage(messages.direct)}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
{intl.formatMessage(messages.hotkey)}
g + s{intl.formatMessage(messages.start)}
g + f{intl.formatMessage(messages.favourites)}
g + p{intl.formatMessage(messages.pinned)}
g + u{intl.formatMessage(messages.my_profile)}
g + b{intl.formatMessage(messages.blocked)}
g + m{intl.formatMessage(messages.muted)}
g + r{intl.formatMessage(messages.requests)}
?{intl.formatMessage(messages.legend)}
-
-
-
- ); - } - -} diff --git a/app/javascript/gabsocial/components/modal/hotkeys_modal/hotkeys_modal.scss b/app/javascript/gabsocial/components/modal/hotkeys_modal/hotkeys_modal.scss deleted file mode 100644 index 26b1165a..00000000 --- a/app/javascript/gabsocial/components/modal/hotkeys_modal/hotkeys_modal.scss +++ /dev/null @@ -1,72 +0,0 @@ -.keyboard-shortcuts { - padding: 8px 0 0; - overflow: hidden; - background-color: $classic-base-color; - border-radius: 6px; - - @media screen and (max-width: 960px) { - height: 90vh; - } - - &__header { - display: block; - position: relative; - border-bottom: 1px solid lighten($classic-base-color, 8%); - border-radius: 6px 6px 0 0; - padding: 12px 0; - - &__title { - display: block; - width: 80%; - color: $primary-text-color; - - @include text-sizing(18px, 700, 24px, center); - @include margin-center; - } - } - - &__close { - @include abs-position(10px, 10px); - } - - &__content { - display: flex; - flex-direction: row; - padding: 15px; - - @media screen and (max-width: 960px) { - flex-direction: column; - overflow: hidden; - overflow-y: scroll; - height: calc(100% - 80px); - -webkit-overflow-scrolling: touch; - } - } - - table { - thead { - display: block; - padding-left: 10px; - margin-bottom: 10px; - color: $primary-text-color; - - @include text-sizing(16px, 600); - } - - tr { - font-size: 12px; - } - - td { - padding: 0 10px 8px; - } - - kbd { - display: inline-block; - padding: 2px 8px; - background-color: lighten($ui-base-color, 8%); - - @include border-design(darken($ui-base-color, 4%), 1px, 4px); - } - } -} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/modal/index.js b/app/javascript/gabsocial/components/modal/index.js index c2eb25af..933ff1fb 100644 --- a/app/javascript/gabsocial/components/modal/index.js +++ b/app/javascript/gabsocial/components/modal/index.js @@ -4,11 +4,11 @@ import ComposeModal from './compose_modal/compose_modal'; import ConfirmationModal from './confirmation_modal/confirmation_modal'; import EmbedModal from './embed_modal/embed_modal'; import FocalPointModal from './focal_point_modal/focal_point_modal'; -import HotkeysModal from './hotkeys_modal/hotkeys_modal'; +import HotkeysModal from './hotkeys_modal'; import MediaModal from './media_modal/media_modal'; import MuteModal from './mute_modal/mute_modal'; import ReportModal from './report_modal/report_modal'; -import UnauthorizedModal from './unauthorized_modal/unauthorized_modal'; +import UnauthorizedModal from './unauthorized_modal'; import VideoModal from './video_modal/video_modal'; export { diff --git a/app/javascript/gabsocial/components/modal/modal.scss b/app/javascript/gabsocial/components/modal/modal.scss deleted file mode 100644 index 2f01f948..00000000 --- a/app/javascript/gabsocial/components/modal/modal.scss +++ /dev/null @@ -1,44 +0,0 @@ -.modal { - padding: 8px 0 0; - overflow: hidden; - background-color: $classic-base-color; - border-radius: 6px; - flex-direction: column; - margin: 10px 0; - - &__content { - display: flex; - flex-direction: row; - flex: 1; - padding: 10px; - overflow-y: hidden; - } - - @media screen and (max-width:895px) { - margin: 0; - - @include size(98vw, 98vh); - } -} - -.modal-header { - display: block; - position: relative; - border-bottom: 1px solid lighten($classic-base-color, 8%); - border-radius: 6px 6px 0 0; - - @include vertical-padding(12px); - - &__title { - display: block; - width: 80%; - color: $gab-background-base-light; - - @include text-sizing(18px, 700, 24px, center); - @include margin-center; - } - - &__close { - @include abs-position(10px, 10px); - } -} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/modal_base/modal_base.js b/app/javascript/gabsocial/components/modal/modal_base.js similarity index 57% rename from app/javascript/gabsocial/components/modal_base/modal_base.js rename to app/javascript/gabsocial/components/modal/modal_base.js index b056b513..245aaab5 100644 --- a/app/javascript/gabsocial/components/modal_base/modal_base.js +++ b/app/javascript/gabsocial/components/modal/modal_base.js @@ -1,25 +1,28 @@ -import { injectIntl, FormattedMessage, defineMessages } from 'react-intl'; -import classNames from 'classnames'; -import { openModal } from '../../actions/modal'; -import { cancelReplyCompose } from '../../actions/compose'; +import { Fragment } from 'react' +import { injectIntl, FormattedMessage, defineMessages } from 'react-intl' +import classNames from 'classnames/bind' +import { openModal } from '../../actions/modal' +import { cancelReplyCompose } from '../../actions/compose' const messages = defineMessages({ confirm: { id: 'confirmations.delete.confirm', defaultMessage: 'Delete' }, -}); +}) const mapStateToProps = state => ({ composeId: state.getIn(['compose', 'id']), composeText: state.getIn(['compose', 'text']), -}); +}) const mapDispatchToProps = (dispatch) => ({ onOpenModal(type, opts) { - dispatch(openModal(type, opts)); + dispatch(openModal(type, opts)) }, onCancelReplyCompose() { - dispatch(cancelReplyCompose()); + dispatch(cancelReplyCompose()) }, -}); +}) + +const cx = classNames.bind(_s) export default @connect(mapStateToProps, mapDispatchToProps) @injectIntl @@ -34,23 +37,23 @@ class ModalBase extends PureComponent { composeId: PropTypes.string, composeText: PropTypes.string, type: PropTypes.string, - }; + } state = { revealed: !!this.props.children, - }; + } - activeElement = this.state.revealed ? document.activeElement : null; + activeElement = this.state.revealed ? document.activeElement : null handleKeyUp = (e) => { if ((e.key === 'Escape' || e.key === 'Esc' || e.keyCode === 27) && !!this.props.children) { - this.handleOnClose(); + this.handleOnClose() } } handleOnClose = () => { - const { onOpenModal, composeText, composeId, onClose, intl, type, onCancelReplyCompose } = this.props; + const { onOpenModal, composeText, composeId, onClose, intl, type, onCancelReplyCompose } = this.props if (!composeId && composeText && type == 'COMPOSE') { onOpenModal('CONFIRM', { @@ -58,80 +61,86 @@ class ModalBase extends PureComponent { confirm: intl.formatMessage(messages.confirm), onConfirm: () => onCancelReplyCompose(), onCancel: () => onOpenModal('COMPOSE'), - }); + }) } else { - onClose(); + onClose() } - }; + } componentDidMount () { - window.addEventListener('keyup', this.handleKeyUp, false); + window.addEventListener('keyup', this.handleKeyUp, false) } componentWillReceiveProps (nextProps) { if (!!nextProps.children && !this.props.children) { - this.activeElement = document.activeElement; + this.activeElement = document.activeElement - this.getSiblings().forEach(sibling => sibling.setAttribute('inert', true)); + this.getSiblings().forEach(sibling => sibling.setAttribute('inert', true)) } else if (!nextProps.children) { - this.setState({ revealed: false }); + this.setState({ revealed: false }) } if (!nextProps.children && !!this.props.children) { - this.activeElement.focus(); - this.activeElement = null; + this.activeElement.focus() + this.activeElement = null } } componentDidUpdate (prevProps) { if (!this.props.children && !!prevProps.children) { - this.getSiblings().forEach(sibling => sibling.removeAttribute('inert')); + this.getSiblings().forEach(sibling => sibling.removeAttribute('inert')) } if (this.props.children) { requestAnimationFrame(() => { - this.setState({ revealed: true }); - }); + this.setState({ revealed: true }) + }) } } componentWillUnmount () { - window.removeEventListener('keyup', this.handleKeyUp); + window.removeEventListener('keyup', this.handleKeyUp) } getSiblings = () => { - return Array(...this.node.parentElement.childNodes).filter(node => node !== this.node); + return Array(...this.node.parentElement.childNodes).filter(node => node !== this.node) } setRef = ref => { - this.node = ref; + this.node = ref } render () { - const { children } = this.props; - const { revealed } = this.state; - const visible = !!children; + const { children } = this.props - if (!visible) { - return ( -
- ); - } + const visible = !!children - const classes = classNames('modal-base', { - 'modal-base--hidden': !revealed, - }); + const containerClasses = cx({ + default: 1, + z4: 1, + displayNone: !visible, + }) return ( -
-
-
this.handleOnClose()} /> -
- {children} -
-
+
+ { + !!visible && + +
+
+ {children} +
+ + }
- ); + ) } } \ No newline at end of file diff --git a/app/javascript/gabsocial/components/modal/modal_layout.js b/app/javascript/gabsocial/components/modal/modal_layout.js index 97da11a1..3e8452f6 100644 --- a/app/javascript/gabsocial/components/modal/modal_layout.js +++ b/app/javascript/gabsocial/components/modal/modal_layout.js @@ -1,40 +1,46 @@ -import { defineMessages, injectIntl } from 'react-intl'; -import IconButton from '../icon_button'; - -import './modal_layout'; +import { defineMessages, injectIntl } from 'react-intl' +import Button from '../button' +import Block from '../block' +import Heading from '../heading' const messages = defineMessages({ close: { id: 'lightbox.close', defaultMessage: 'Close' }, -}); +}) -export default @injectIntl +export default +@injectIntl class ModalLayout extends PureComponent { static propTypes = { title: PropTypes.string, children: PropTypes.node, onClose: PropTypes.func.isRequired, - }; + } render() { - const { title, children, intl, onClose } = this.props; + const { title, children, intl, onClose } = this.props return ( -
-
-

{title}

- -
-
- {children} -
+
+ +
+ + {title} + +
+
+ {children} +
+
) - }; + } } \ No newline at end of file diff --git a/app/javascript/gabsocial/components/modal_root/modal_root.js b/app/javascript/gabsocial/components/modal/modal_root.js similarity index 61% rename from app/javascript/gabsocial/components/modal_root/modal_root.js rename to app/javascript/gabsocial/components/modal/modal_root.js index dde0443e..31e56395 100644 --- a/app/javascript/gabsocial/components/modal_root/modal_root.js +++ b/app/javascript/gabsocial/components/modal/modal_root.js @@ -1,6 +1,6 @@ -import Base from '../modal_base'; -import Bundle from '../../features/ui/util/bundle'; -import BundleModalError from '../bundle_modal_error'; +import ModalBase from './modal_base' +import Bundle from '../../features/ui/util/bundle' +import BundleModalError from '../bundle_modal_error' import { ActionsModal, MediaModal, @@ -11,7 +11,8 @@ import { HotkeysModal, ComposeModal, UnauthorizedModal, -} from '../modal'; + ProUpgradeModal, +} from '.' import { MuteModal, ReportModal, @@ -19,8 +20,8 @@ import { ListEditor, ListAdder, StatusRevisionModal, -} from '../../features/ui/util/async-components'; -import ModalLoading from '../modal_loading'; +} from '../../features/ui/util/async-components' +import ModalLoading from '../modal_loading' const MODAL_COMPONENTS = { 'MEDIA': () => Promise.resolve({ default: MediaModal }), @@ -39,7 +40,7 @@ const MODAL_COMPONENTS = { 'COMPOSE': () => Promise.resolve({ default: ComposeModal }), 'UNAUTHORIZED': () => Promise.resolve({ default: UnauthorizedModal }), 'PRO_UPGRADE': () => Promise.resolve({ default: ProUpgradeModal }), -}; +} export default class ModalRoot extends PureComponent { @@ -47,46 +48,54 @@ export default class ModalRoot extends PureComponent { type: PropTypes.string, props: PropTypes.object, onClose: PropTypes.func.isRequired, - }; + } getSnapshotBeforeUpdate () { - return { visible: !!this.props.type }; + return { visible: !!this.props.type } } componentDidUpdate (prevProps, prevState, { visible }) { if (visible) { - document.body.classList.add('with-modals--active'); + document.body.classList.add('with-modals--active') } else { - document.body.classList.remove('with-modals--active'); + document.body.classList.remove('with-modals--active') } } renderLoading = modalId => () => { - return ['MEDIA', 'VIDEO', 'BOOST', 'CONFIRM', 'ACTIONS'].indexOf(modalId) === -1 ? : null; + return ['MEDIA', 'VIDEO', 'BOOST', 'CONFIRM', 'ACTIONS'].indexOf(modalId) === -1 ? : null } renderError = (props) => { - return ; + return } onClickClose = () => { - const { onClose, type } = this.props; - onClose(type); + const { onClose, type } = this.props + onClose(type) } render () { - const { type, props } = this.props; - const visible = !!type; + const { type, props } = this.props + const visible = !!type return ( - - {visible && ( - - {(SpecificComponent) => } + + { + visible && + + { + (SpecificComponent) => + } - )} - - ); + } + + ) } } diff --git a/app/javascript/gabsocial/components/modal/pro_upgrade_modal/pro_upgrade_modal.js b/app/javascript/gabsocial/components/modal/pro_upgrade_modal.js similarity index 100% rename from app/javascript/gabsocial/components/modal/pro_upgrade_modal/pro_upgrade_modal.js rename to app/javascript/gabsocial/components/modal/pro_upgrade_modal.js diff --git a/app/javascript/gabsocial/components/modal/pro_upgrade_modal/index.js b/app/javascript/gabsocial/components/modal/pro_upgrade_modal/index.js deleted file mode 100644 index e69de29b..00000000 diff --git a/app/javascript/gabsocial/components/modal/unauthorized_modal.js b/app/javascript/gabsocial/components/modal/unauthorized_modal.js new file mode 100644 index 00000000..fcc0a5ec --- /dev/null +++ b/app/javascript/gabsocial/components/modal/unauthorized_modal.js @@ -0,0 +1,53 @@ +import { defineMessages, injectIntl } from 'react-intl' +import ImmutablePureComponent from 'react-immutable-pure-component' +import ModalLayout from './modal_layout' +import Text from '../text' +import Button from '../button' + +const messages = defineMessages({ + close: { id: 'lightbox.close', defaultMessage: 'Close' }, + signup: { id: 'unauthorized_modal.title', defaultMessage: 'Sign up for Gab' }, + text: { id: 'unauthorized_modal.text', defaultMessage: 'You need to be logged in to do that.' }, + register: { id: 'account.register', defaultMessage: 'Sign up' }, + alreadyHaveAccount: { id: 'unauthorized_modal.footer', defaultMessage: 'Already have an account? {login}.' }, + login: { id: 'account.login', defaultMessage: 'Log in' }, +}) + +export default +@injectIntl +class UnauthorizedModal extends ImmutablePureComponent { + + static propTypes = { + intl: PropTypes.object.isRequired, + } + + render() { + const { intl } = this.props + + return ( + +
+ + {intl.formatMessage(messages.text)} + + +
+
+ + { + intl.formatMessage(messages.login, { + login: ( + + ) + }) + } + +
+
+ ) + } +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/modal/unauthorized_modal/unauthorized_modal.js b/app/javascript/gabsocial/components/modal/unauthorized_modal/unauthorized_modal.js deleted file mode 100644 index a67e4fd0..00000000 --- a/app/javascript/gabsocial/components/modal/unauthorized_modal/unauthorized_modal.js +++ /dev/null @@ -1,49 +0,0 @@ -import { defineMessages, injectIntl } from 'react-intl'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -import IconButton from '../../icon_button'; - -const messages = defineMessages({ - close: { id: 'lightbox.close', defaultMessage: 'Close' }, - signup: {id: 'unauthorized_modal.title', defaultMessage: 'Sign up for Gab' }, - text: { id: 'unauthorized_modal.text', defaultMessage: 'You need to be logged in to do that.' }, - register: { id: 'account.register', defaultMessage: 'Sign up' }, - alreadyHaveAccount: { id: 'unauthorized_modal.footer', defaultMessage: 'Already have an account? {login}.' }, - login: { id: 'account.login', defaultMessage: 'Log in' }, -}); - -export default @injectIntl -class UnauthorizedModal extends ImmutablePureComponent { - - static propTypes = { - intl: PropTypes.object.isRequired, - onClose: PropTypes.func.isRequired, - }; - - onClickClose = () => { - this.props.onClose('UNAUTHORIZED'); - }; - - render () { - const { intl } = this.props; - - return ( -
-
-

{intl.formatMessage(messages.signup)}

- -
-
-
- {intl.formatMessage(messages.text)} - {intl.formatMessage(messages.register)} -
-
-
- {intl.formatMessage(messages.login, { - login: {intl.formatMessage(messages.login)} - })} -
-
- ); - } -} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/modal/unauthorized_modal/unauthorized_modal.scss b/app/javascript/gabsocial/components/modal/unauthorized_modal/unauthorized_modal.scss deleted file mode 100644 index 2def50dc..00000000 --- a/app/javascript/gabsocial/components/modal/unauthorized_modal/unauthorized_modal.scss +++ /dev/null @@ -1,41 +0,0 @@ -.unauthorized-modal { - width: 440px !important; - - @media screen and (max-width:895px) { - @include size(330px, 270px); - } - - &__content { - @include size(100%, 150px); - @include flex(center, center, column); - } - - &__footer { - border-top: 1px solid #666; - padding: 10px; - - @include flex(center, center); - - >span { - font-size: 14px; - color: $secondary-text-color; - - a { - color: $gab-brand-default !important; - } - } - } -} - -.unauthorized-modal-content { - &__text { - display: block; - margin-bottom: 18px; - color: #fff; - font-size: 14px; - } - - &__button { - width: 200px; - } -} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/modal_base/index.js b/app/javascript/gabsocial/components/modal_base/index.js deleted file mode 100644 index 4c462fd8..00000000 --- a/app/javascript/gabsocial/components/modal_base/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './modal_base'; \ No newline at end of file diff --git a/app/javascript/gabsocial/components/modal_base/modal_base.scss b/app/javascript/gabsocial/components/modal_base/modal_base.scss deleted file mode 100644 index b2127a42..00000000 --- a/app/javascript/gabsocial/components/modal_base/modal_base.scss +++ /dev/null @@ -1,34 +0,0 @@ -.modal-base { - position: relative; - z-index: 9999; - - &--hidden { - display: none; - } - - &__overlay { - position: fixed; - background: rgba($base-overlay-background, 0.7); - - @include abs-position(0, 0, 0, 0, false); - } - - &__container { - position: fixed; - align-content: space-around; - z-index: 9999; - - @include size(100%); - @include flex(center, center, column); - @include abs-position(0, auto, auto, 0, false); - @include unselectable; - } -} - -// .modal-base__modal { -// pointer-events: auto; -// display: flex; -// z-index: 9999; -// max-height: 100%; -// overflow-y: hidden; -// } \ No newline at end of file diff --git a/app/javascript/gabsocial/components/modal_root/index.js b/app/javascript/gabsocial/components/modal_root/index.js deleted file mode 100644 index aef205be..00000000 --- a/app/javascript/gabsocial/components/modal_root/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './modal_root'; \ No newline at end of file diff --git a/app/javascript/gabsocial/components/panel/media_gallery_panel.js b/app/javascript/gabsocial/components/panel/media_gallery_panel.js new file mode 100644 index 00000000..a030088b --- /dev/null +++ b/app/javascript/gabsocial/components/panel/media_gallery_panel.js @@ -0,0 +1,70 @@ +import { defineMessages, injectIntl } from 'react-intl'; +import { fetchSuggestions, dismissSuggestion } from '../../actions/suggestions'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import AccountContainer from '../../containers/account_container'; +import PanelLayout from './panel_layout'; + +const messages = defineMessages({ + dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' }, + title: { id: 'who_to_follow.title', defaultMessage: 'Who to Follow' }, + show_more: { id: 'who_to_follow.more', defaultMessage: 'Show more' }, +}); + +const mapStateToProps = state => ({ + suggestions: state.getIn(['suggestions', 'items']), +}); + +const mapDispatchToProps = dispatch => { + return { + fetchSuggestions: () => dispatch(fetchSuggestions()), + dismissSuggestion: account => dispatch(dismissSuggestion(account.get('id'))), + } +}; + +export default @connect(mapStateToProps, mapDispatchToProps) +@injectIntl +class WhoToFollowPanel extends ImmutablePureComponent { + + static propTypes = { + suggestions: ImmutablePropTypes.list.isRequired, + fetchSuggestions: PropTypes.func.isRequired, + dismissSuggestion: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + }; + + componentDidMount () { + this.props.fetchSuggestions(); + } + + render() { + const { intl, /* suggestions, */ dismissSuggestion } = this.props; + // : testing!!! : + const suggestions = [ + "1", + ] + // if (suggestions.isEmpty()) { + // return null; + // } + + return ( + +
+ {suggestions && suggestions.map(accountId => ( + + ))} +
+
+ ); + }; +}; \ No newline at end of file diff --git a/app/javascript/gabsocial/components/panel/profile_info_panel.js b/app/javascript/gabsocial/components/panel/profile_info_panel.js new file mode 100644 index 00000000..a030088b --- /dev/null +++ b/app/javascript/gabsocial/components/panel/profile_info_panel.js @@ -0,0 +1,70 @@ +import { defineMessages, injectIntl } from 'react-intl'; +import { fetchSuggestions, dismissSuggestion } from '../../actions/suggestions'; +import ImmutablePureComponent from 'react-immutable-pure-component'; +import ImmutablePropTypes from 'react-immutable-proptypes'; +import AccountContainer from '../../containers/account_container'; +import PanelLayout from './panel_layout'; + +const messages = defineMessages({ + dismissSuggestion: { id: 'suggestions.dismiss', defaultMessage: 'Dismiss suggestion' }, + title: { id: 'who_to_follow.title', defaultMessage: 'Who to Follow' }, + show_more: { id: 'who_to_follow.more', defaultMessage: 'Show more' }, +}); + +const mapStateToProps = state => ({ + suggestions: state.getIn(['suggestions', 'items']), +}); + +const mapDispatchToProps = dispatch => { + return { + fetchSuggestions: () => dispatch(fetchSuggestions()), + dismissSuggestion: account => dispatch(dismissSuggestion(account.get('id'))), + } +}; + +export default @connect(mapStateToProps, mapDispatchToProps) +@injectIntl +class WhoToFollowPanel extends ImmutablePureComponent { + + static propTypes = { + suggestions: ImmutablePropTypes.list.isRequired, + fetchSuggestions: PropTypes.func.isRequired, + dismissSuggestion: PropTypes.func.isRequired, + intl: PropTypes.object.isRequired, + }; + + componentDidMount () { + this.props.fetchSuggestions(); + } + + render() { + const { intl, /* suggestions, */ dismissSuggestion } = this.props; + // : testing!!! : + const suggestions = [ + "1", + ] + // if (suggestions.isEmpty()) { + // return null; + // } + + return ( + +
+ {suggestions && suggestions.map(accountId => ( + + ))} +
+
+ ); + }; +}; \ No newline at end of file diff --git a/app/javascript/gabsocial/components/permalink/index.js b/app/javascript/gabsocial/components/permalink/index.js deleted file mode 100644 index 27745e0a..00000000 --- a/app/javascript/gabsocial/components/permalink/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './permalink'; \ No newline at end of file diff --git a/app/javascript/gabsocial/components/permalink/permalink.js b/app/javascript/gabsocial/components/permalink/permalink.js deleted file mode 100644 index 626a22b3..00000000 --- a/app/javascript/gabsocial/components/permalink/permalink.js +++ /dev/null @@ -1,37 +0,0 @@ -import classNames from 'classnames'; - -export default class Permalink extends PureComponent { - - static contextTypes = { - router: PropTypes.object, - }; - - static propTypes = { - className: PropTypes.string, - href: PropTypes.string.isRequired, - children: PropTypes.node, - blank: PropTypes.bool, - button: PropTypes.bool, - }; - - handleClick = e => { - if (this.context.router && e.button === 0 && !(e.ctrlKey || e.metaKey)) { - e.preventDefault(); - this.context.router.history.push(this.props.href); - } - } - - render () { - const { href, children, className, blank, ...other } = this.props; - - const classes = classNames('permalink', className); - const target = blank ? '_blank' : null; - - return ( - - {children} - - ); - } - -} diff --git a/app/javascript/gabsocial/components/popover/content_warning_popover.js b/app/javascript/gabsocial/components/popover/content_warning_popover.js new file mode 100644 index 00000000..98b0d619 --- /dev/null +++ b/app/javascript/gabsocial/components/popover/content_warning_popover.js @@ -0,0 +1,9 @@ +export default class Popover extends PureComponent { + render() { + return ( +
+ { /* */ } +
+ ) + } +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/popover/date_picker_popover.js b/app/javascript/gabsocial/components/popover/date_picker_popover.js new file mode 100644 index 00000000..98b0d619 --- /dev/null +++ b/app/javascript/gabsocial/components/popover/date_picker_popover.js @@ -0,0 +1,9 @@ +export default class Popover extends PureComponent { + render() { + return ( +
+ { /* */ } +
+ ) + } +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/popover/popover.js b/app/javascript/gabsocial/components/popover/popover.js new file mode 100644 index 00000000..98b0d619 --- /dev/null +++ b/app/javascript/gabsocial/components/popover/popover.js @@ -0,0 +1,9 @@ +export default class Popover extends PureComponent { + render() { + return ( +
+ { /* */ } +
+ ) + } +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/popover/search_popover.js b/app/javascript/gabsocial/components/popover/search_popover.js new file mode 100644 index 00000000..98b0d619 --- /dev/null +++ b/app/javascript/gabsocial/components/popover/search_popover.js @@ -0,0 +1,9 @@ +export default class Popover extends PureComponent { + render() { + return ( +
+ { /* */ } +
+ ) + } +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/popover/sidebar_more_popover.js b/app/javascript/gabsocial/components/popover/sidebar_more_popover.js new file mode 100644 index 00000000..98b0d619 --- /dev/null +++ b/app/javascript/gabsocial/components/popover/sidebar_more_popover.js @@ -0,0 +1,9 @@ +export default class Popover extends PureComponent { + render() { + return ( +
+ { /* */ } +
+ ) + } +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/popover/status_options_popover.js b/app/javascript/gabsocial/components/popover/status_options_popover.js new file mode 100644 index 00000000..98b0d619 --- /dev/null +++ b/app/javascript/gabsocial/components/popover/status_options_popover.js @@ -0,0 +1,9 @@ +export default class Popover extends PureComponent { + render() { + return ( +
+ { /* */ } +
+ ) + } +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/popover/status_visibility_popover.js b/app/javascript/gabsocial/components/popover/status_visibility_popover.js new file mode 100644 index 00000000..98b0d619 --- /dev/null +++ b/app/javascript/gabsocial/components/popover/status_visibility_popover.js @@ -0,0 +1,9 @@ +export default class Popover extends PureComponent { + render() { + return ( +
+ { /* */ } +
+ ) + } +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/popover/user_popover.js b/app/javascript/gabsocial/components/popover/user_popover.js new file mode 100644 index 00000000..98b0d619 --- /dev/null +++ b/app/javascript/gabsocial/components/popover/user_popover.js @@ -0,0 +1,9 @@ +export default class Popover extends PureComponent { + render() { + return ( +
+ { /* */ } +
+ ) + } +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/relative_timestamp/relative_timestamp.js b/app/javascript/gabsocial/components/relative_timestamp.js similarity index 63% rename from app/javascript/gabsocial/components/relative_timestamp/relative_timestamp.js rename to app/javascript/gabsocial/components/relative_timestamp.js index 3f1c0007..9b85ae7c 100644 --- a/app/javascript/gabsocial/components/relative_timestamp/relative_timestamp.js +++ b/app/javascript/gabsocial/components/relative_timestamp.js @@ -1,5 +1,4 @@ -import { injectIntl, defineMessages } from 'react-intl'; -import moment from 'moment'; +import { injectIntl, defineMessages } from 'react-intl' const messages = defineMessages({ just_now: { id: 'relative_time.just_now', defaultMessage: 'now' }, @@ -12,7 +11,7 @@ const messages = defineMessages({ minutes_remaining: { id: 'time_remaining.minutes', defaultMessage: '{number, plural, one {# minute} other {# minutes}} left' }, hours_remaining: { id: 'time_remaining.hours', defaultMessage: '{number, plural, one {# hour} other {# hours}} left' }, days_remaining: { id: 'time_remaining.days', defaultMessage: '{number, plural, one {# day} other {# days}} left' }, -}); +}) const dateFormatOptions = { hour12: false, @@ -21,94 +20,94 @@ const dateFormatOptions = { day: '2-digit', hour: '2-digit', minute: '2-digit', -}; +} const shortDateFormatOptions = { month: 'short', day: 'numeric', -}; +} -const SECOND = 1000; -const MINUTE = 1000 * 60; -const HOUR = 1000 * 60 * 60; -const DAY = 1000 * 60 * 60 * 24; +const SECOND = 1000 +const MINUTE = 1000 * 60 +const HOUR = 1000 * 60 * 60 +const DAY = 1000 * 60 * 60 * 24 -const MAX_DELAY = 2147483647; +const MAX_DELAY = 2147483647 const selectUnits = delta => { - const absDelta = Math.abs(delta); + const absDelta = Math.abs(delta) if (absDelta < MINUTE) { - return 'second'; + return 'second' } else if (absDelta < HOUR) { - return 'minute'; + return 'minute' } else if (absDelta < DAY) { - return 'hour'; + return 'hour' } - return 'day'; -}; + return 'day' +} const getUnitDelay = units => { switch (units) { - case 'second': - return SECOND; - case 'minute': - return MINUTE; - case 'hour': - return HOUR; - case 'day': - return DAY; - default: - return MAX_DELAY; + case 'second': + return SECOND + case 'minute': + return MINUTE + case 'hour': + return HOUR + case 'day': + return DAY + default: + return MAX_DELAY } -}; +} export const timeAgoString = (intl, date, now, year) => { - const delta = now - date.getTime(); + const delta = now - date.getTime() - let relativeTime; + let relativeTime if (delta < 10 * SECOND) { - relativeTime = intl.formatMessage(messages.just_now); + relativeTime = intl.formatMessage(messages.just_now) } else if (delta < 7 * DAY) { if (delta < MINUTE) { - relativeTime = intl.formatMessage(messages.seconds, { number: Math.floor(delta / SECOND) }); + relativeTime = intl.formatMessage(messages.seconds, { number: Math.floor(delta / SECOND) }) } else if (delta < HOUR) { - relativeTime = intl.formatMessage(messages.minutes, { number: Math.floor(delta / MINUTE) }); + relativeTime = intl.formatMessage(messages.minutes, { number: Math.floor(delta / MINUTE) }) } else if (delta < DAY) { - relativeTime = intl.formatMessage(messages.hours, { number: Math.floor(delta / HOUR) }); + relativeTime = intl.formatMessage(messages.hours, { number: Math.floor(delta / HOUR) }) } else { - relativeTime = intl.formatMessage(messages.days, { number: Math.floor(delta / DAY) }); + relativeTime = intl.formatMessage(messages.days, { number: Math.floor(delta / DAY) }) } } else if (date.getFullYear() === year) { - relativeTime = intl.formatDate(date, shortDateFormatOptions); + relativeTime = intl.formatDate(date, shortDateFormatOptions) } else { - relativeTime = intl.formatDate(date, { ...shortDateFormatOptions, year: 'numeric' }); + relativeTime = intl.formatDate(date, { ...shortDateFormatOptions, year: 'numeric' }) } - return relativeTime; -}; + return relativeTime +} const timeRemainingString = (intl, date, now) => { - const delta = date.getTime() - now; + const delta = date.getTime() - now - let relativeTime; + let relativeTime if (delta < 10 * SECOND) { - relativeTime = intl.formatMessage(messages.moments_remaining); + relativeTime = intl.formatMessage(messages.moments_remaining) } else if (delta < MINUTE) { - relativeTime = intl.formatMessage(messages.seconds_remaining, { number: Math.floor(delta / SECOND) }); + relativeTime = intl.formatMessage(messages.seconds_remaining, { number: Math.floor(delta / SECOND) }) } else if (delta < HOUR) { - relativeTime = intl.formatMessage(messages.minutes_remaining, { number: Math.floor(delta / MINUTE) }); + relativeTime = intl.formatMessage(messages.minutes_remaining, { number: Math.floor(delta / MINUTE) }) } else if (delta < DAY) { - relativeTime = intl.formatMessage(messages.hours_remaining, { number: Math.floor(delta / HOUR) }); + relativeTime = intl.formatMessage(messages.hours_remaining, { number: Math.floor(delta / HOUR) }) } else { - relativeTime = intl.formatMessage(messages.days_remaining, { number: Math.floor(delta / DAY) }); + relativeTime = intl.formatMessage(messages.days_remaining, { number: Math.floor(delta / DAY) }) } - return relativeTime; -}; + return relativeTime +} export default @injectIntl class RelativeTimestamp extends Component { @@ -118,68 +117,68 @@ class RelativeTimestamp extends Component { timestamp: PropTypes.string.isRequired, year: PropTypes.number.isRequired, futureDate: PropTypes.bool, - }; + } state = { now: this.props.intl.now(), - }; + } static defaultProps = { year: (new Date()).getFullYear(), - }; + } - shouldComponentUpdate (nextProps, nextState) { + shouldComponentUpdate(nextProps, nextState) { // As of right now the locale doesn't change without a new page load, // but we might as well check in case that ever changes. return this.props.timestamp !== nextProps.timestamp || this.props.intl.locale !== nextProps.intl.locale || - this.state.now !== nextState.now; + this.state.now !== nextState.now } - componentWillReceiveProps (nextProps) { + componentWillReceiveProps(nextProps) { if (this.props.timestamp !== nextProps.timestamp) { - this.setState({ now: this.props.intl.now() }); + this.setState({ now: this.props.intl.now() }) } } - componentDidMount () { - this._scheduleNextUpdate(this.props, this.state); + componentDidMount() { + this._scheduleNextUpdate(this.props, this.state) } - componentWillUpdate (nextProps, nextState) { - this._scheduleNextUpdate(nextProps, nextState); + componentWillUpdate(nextProps, nextState) { + this._scheduleNextUpdate(nextProps, nextState) } - componentWillUnmount () { - clearTimeout(this._timer); + componentWillUnmount() { + clearTimeout(this._timer) } - _scheduleNextUpdate (props, state) { - clearTimeout(this._timer); + _scheduleNextUpdate(props, state) { + clearTimeout(this._timer) - const { timestamp } = props; - const delta = (new Date(timestamp)).getTime() - state.now; - const unitDelay = getUnitDelay(selectUnits(delta)); - const unitRemainder = Math.abs(delta % unitDelay); - const updateInterval = 1000 * 10; - const delay = delta < 0 ? Math.max(updateInterval, unitDelay - unitRemainder) : Math.max(updateInterval, unitRemainder); + const { timestamp } = props + const delta = (new Date(timestamp)).getTime() - state.now + const unitDelay = getUnitDelay(selectUnits(delta)) + const unitRemainder = Math.abs(delta % unitDelay) + const updateInterval = 1000 * 10 + const delay = delta < 0 ? Math.max(updateInterval, unitDelay - unitRemainder) : Math.max(updateInterval, unitRemainder) this._timer = setTimeout(() => { - this.setState({ now: this.props.intl.now() }); - }, delay); + this.setState({ now: this.props.intl.now() }) + }, delay) } - render () { - const { timestamp, intl, year, futureDate } = this.props; + render() { + const { timestamp, intl, year, futureDate } = this.props - const date = new Date(timestamp); - const relativeTime = futureDate ? timeRemainingString(intl, date, this.state.now) : timeAgoString(intl, date, this.state.now, year); + const date = new Date(timestamp) + const relativeTime = futureDate ? timeRemainingString(intl, date, this.state.now) : timeAgoString(intl, date, this.state.now, year) return ( - ); + ) } } diff --git a/app/javascript/gabsocial/components/relative_timestamp/index.js b/app/javascript/gabsocial/components/relative_timestamp/index.js deleted file mode 100644 index 2c1b0d1c..00000000 --- a/app/javascript/gabsocial/components/relative_timestamp/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './relative_timestamp'; \ No newline at end of file diff --git a/app/javascript/gabsocial/components/sidebar.js b/app/javascript/gabsocial/components/sidebar.js index 6843345d..b0df96e3 100644 --- a/app/javascript/gabsocial/components/sidebar.js +++ b/app/javascript/gabsocial/components/sidebar.js @@ -1,9 +1,9 @@ -import { NavLink } from 'react-router-dom' import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePureComponent from 'react-immutable-pure-component' import { injectIntl, defineMessages } from 'react-intl' import Button from './button' import { closeSidebar } from '../actions/sidebar' +import { openModal } from '../actions/modal' import { me } from '../initial_state' import { makeGetAccount } from '../selectors' import SidebarSectionTitle from './sidebar_section_title' @@ -44,9 +44,13 @@ const mapDispatchToProps = (dispatch) => ({ onClose() { dispatch(closeSidebar()) }, + onOpenComposeModal() { + dispatch(openModal('PRO_UPGRADE')) + }, }) -export default @connect(mapStateToProps, mapDispatchToProps) +export default +@connect(mapStateToProps, mapDispatchToProps) @injectIntl class Sidebar extends ImmutablePureComponent { @@ -55,6 +59,7 @@ class Sidebar extends ImmutablePureComponent { account: ImmutablePropTypes.map, sidebarOpen: PropTypes.bool, onClose: PropTypes.func.isRequired, + onOpenComposeModal: PropTypes.func.isRequired, } state = { @@ -84,6 +89,11 @@ class Sidebar extends ImmutablePureComponent { }) } + handleOpenComposeModal = () => { + console.log("handleOpenComposeModal") + this.props.onOpenComposeModal() + } + render() { const { sidebarOpen, intl, account } = this.props const { moreOpen } = this.state @@ -114,6 +124,11 @@ class Sidebar extends ImmutablePureComponent { to: '/notifications', count: 40, }, + { + title: 'Bookmarks', + icon: 'bookmarks', + to: '/bookmarks', + }, { title: 'Groups', icon: 'group', @@ -210,6 +225,7 @@ class Sidebar extends ImmutablePureComponent { )).reduce((aggregate, item) => [...aggregate, item, ' '], []); const toggleText = intl.formatMessage(hidden ? messages.showMore : messages.showLess); diff --git a/app/javascript/gabsocial/components/upload_area.js b/app/javascript/gabsocial/components/upload_area.js new file mode 100644 index 00000000..c3e7dc28 --- /dev/null +++ b/app/javascript/gabsocial/components/upload_area.js @@ -0,0 +1,82 @@ +import { defineMessages, injectIntl } from 'react-intl' +import spring from 'react-motion/lib/spring' +import Motion from '../features/ui/util/optional_motion' +import Text from './text' + +const messages = defineMessages({ + title: { id: 'upload_area.title', defaultMessage: 'Drag & drop to upload' }, +}) + +export default +@injectIntl +class UploadArea extends PureComponent { + + static propTypes = { + active: PropTypes.bool, + onClose: PropTypes.func, + intl: PropTypes.object.isRequired, + } + + handleKeyUp = (e) => { + if (!this.props.active) return + + const keyCode = e.keyCode + switch(keyCode) { + case 27: + e.preventDefault() + e.stopPropagation() + this.props.onClose() + break + } + } + + componentDidMount () { + window.addEventListener('keyup', this.handleKeyUp, false) + } + + componentWillUnmount () { + window.removeEventListener('keyup', this.handleKeyUp) + } + + render () { + const { active, intl } = this.props + + return ( + + {({ backgroundOpacity, backgroundScale }) => ( +
+
+
+
+ + {intl.formatMessage(messages.title)} + +
+
+
+ )} + + ) + } + +} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/upload_area/index.js b/app/javascript/gabsocial/components/upload_area/index.js deleted file mode 100644 index c50c704a..00000000 --- a/app/javascript/gabsocial/components/upload_area/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default } from './upload_area'; \ No newline at end of file diff --git a/app/javascript/gabsocial/components/upload_area/upload_area.js b/app/javascript/gabsocial/components/upload_area/upload_area.js deleted file mode 100644 index 53b1b6d0..00000000 --- a/app/javascript/gabsocial/components/upload_area/upload_area.js +++ /dev/null @@ -1,50 +0,0 @@ -import { FormattedMessage } from 'react-intl'; -import spring from 'react-motion/lib/spring'; -import Motion from '../../features/ui/util/optional_motion'; - -export default class UploadArea extends PureComponent { - - static propTypes = { - active: PropTypes.bool, - onClose: PropTypes.func, - }; - - handleKeyUp = (e) => { - if (!this.props.active) return; - - const keyCode = e.keyCode; - switch(keyCode) { - case 27: - e.preventDefault(); - e.stopPropagation(); - this.props.onClose(); - break; - } - } - - componentDidMount () { - window.addEventListener('keyup', this.handleKeyUp, false); - } - - componentWillUnmount () { - window.removeEventListener('keyup', this.handleKeyUp); - } - - render () { - const { active } = this.props; - - return ( - - {({ backgroundOpacity, backgroundScale }) => ( -
-
-
-
-
-
- )} - - ); - } - -} \ No newline at end of file diff --git a/app/javascript/gabsocial/components/upload_area/upload_area.scss b/app/javascript/gabsocial/components/upload_area/upload_area.scss deleted file mode 100644 index 1c7969c0..00000000 --- a/app/javascript/gabsocial/components/upload_area/upload_area.scss +++ /dev/null @@ -1,42 +0,0 @@ -.upload-area { - background: rgba($base-overlay-background, 0.8); - opacity: 0; - visibility: hidden; - z-index: 9999; - - @include flex(center, center); - @include size(100%); - @include abs-position(0, auto, auto, 0); - - * { - pointer-events: none; - } - - &__drop { - display: flex; - box-sizing: border-box; - position: relative; - padding: 8px; - - @include size(320px, 160px); - } - - &__background { - z-index: -1; - border-radius: 4px; - background: $ui-base-color; - box-shadow: 0 0 5px rgba($base-shadow-color, 0.2); - - @include abs-position(0, 0, 0, 0); - } - - &__content { - flex: 1; - color: $secondary-text-color; - border: 2px dashed $ui-base-lighter-color; - border-radius: 4px; - - @include flex(center, center); - @include text-sizing(18px, 500); - } -} \ No newline at end of file diff --git a/app/javascript/gabsocial/containers/dropdown_menu_container.js b/app/javascript/gabsocial/containers/dropdown_menu_container.js deleted file mode 100644 index 7aa30ffc..00000000 --- a/app/javascript/gabsocial/containers/dropdown_menu_container.js +++ /dev/null @@ -1,27 +0,0 @@ -import { openDropdownMenu, closeDropdownMenu } from '../actions/dropdown_menu'; -import { openModal, closeModal } from '../actions/modal'; -import { isUserTouching } from '../utils/is_mobile'; -import DropdownMenu from '../components/dropdown_menu'; - -const mapStateToProps = state => ({ - isModalOpen: state.get('modal').modalType === 'ACTIONS', - dropdownPlacement: state.getIn(['dropdown_menu', 'placement']), - openDropdownId: state.getIn(['dropdown_menu', 'openId']), - openedViaKeyboard: state.getIn(['dropdown_menu', 'keyboard']), -}); - -const mapDispatchToProps = (dispatch, { status, items }) => ({ - onOpen(id, onItemClick, dropdownPlacement, keyboard) { - dispatch(isUserTouching() ? openModal('ACTIONS', { - status, - actions: items, - onClick: onItemClick, - }) : openDropdownMenu(id, dropdownPlacement, keyboard)); - }, - onClose(id) { - dispatch(closeModal()); - dispatch(closeDropdownMenu(id)); - }, -}); - -export default connect(mapStateToProps, mapDispatchToProps)(DropdownMenu); diff --git a/app/javascript/gabsocial/containers/media_container.js b/app/javascript/gabsocial/containers/media_container.js index 6f48e9ed..ca779324 100644 --- a/app/javascript/gabsocial/containers/media_container.js +++ b/app/javascript/gabsocial/containers/media_container.js @@ -7,7 +7,7 @@ import Video from '../features/video'; import Card from '../features/status/components/card'; import Poll from '../components/poll'; import MediaGallery from '../components/media_gallery'; -import ModalRoot from '../components/modal_root'; +import ModalRoot from '../components/modal/modal_root'; import { MediaModal } from '../components/modal'; const { localeData, messages } = getLocale(); diff --git a/app/javascript/gabsocial/containers/modal_container.js b/app/javascript/gabsocial/containers/modal_container.js index 06c4183a..26631b85 100644 --- a/app/javascript/gabsocial/containers/modal_container.js +++ b/app/javascript/gabsocial/containers/modal_container.js @@ -1,6 +1,6 @@ import { closeModal } from '../actions/modal'; import { cancelReplyCompose } from '../actions/compose'; -import ModalRoot from '../components/modal_root'; +import ModalRoot from '../components/modal/modal_root'; const mapStateToProps = state => ({ type: state.get('modal').modalType, diff --git a/app/javascript/gabsocial/containers/notifications_container.js b/app/javascript/gabsocial/containers/notifications_container.js index c0510fa8..fe18186f 100644 --- a/app/javascript/gabsocial/containers/notifications_container.js +++ b/app/javascript/gabsocial/containers/notifications_container.js @@ -1,28 +1,28 @@ -import { injectIntl } from 'react-intl'; -import { NotificationStack } from 'react-notification'; -import { dismissAlert } from '../actions/alerts'; -import { getAlerts } from '../selectors'; +import { injectIntl } from 'react-intl' +import { NotificationStack } from 'react-notification' +import { dismissAlert } from '../actions/alerts' +import { getAlerts } from '../selectors' const mapStateToProps = (state, { intl }) => { - const notifications = getAlerts(state); + const notifications = getAlerts(state) notifications.forEach(notification => ['title', 'message'].forEach(key => { - const value = notification[key]; + const value = notification[key] if (typeof value === 'object') { - notification[key] = intl.formatMessage(value); + notification[key] = intl.formatMessage(value) } - })); + })) - return { notifications }; -}; + return { notifications } +} const mapDispatchToProps = (dispatch) => { return { onDismiss: alert => { - dispatch(dismissAlert(alert)); + dispatch(dismissAlert(alert)) }, - }; -}; + } +} -export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(NotificationStack)); +export default injectIntl(connect(mapStateToProps, mapDispatchToProps)(NotificationStack)) diff --git a/app/javascript/gabsocial/features/account_timeline/components/inner_header/inner_header.js b/app/javascript/gabsocial/features/account_timeline/components/inner_header/inner_header.js index 54a89a9f..2a3d089f 100644 --- a/app/javascript/gabsocial/features/account_timeline/components/inner_header/inner_header.js +++ b/app/javascript/gabsocial/features/account_timeline/components/inner_header/inner_header.js @@ -8,7 +8,7 @@ import Button from '../../../components/button'; import { autoPlayGif, me, isStaff } from '../../../initial_state'; import Avatar from '../../../components/avatar'; import { shortNumberFormat } from '../../../utils/numbers'; -import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; +import Dropdown from '../../../components/dropdown_menu' import ProfileInfoPanel from './profile_info_panel/profile_info_panel'; const messages = defineMessages({ diff --git a/app/javascript/gabsocial/features/community_timeline/community_timeline.js b/app/javascript/gabsocial/features/community_timeline/community_timeline.js index dd985a36..ef341368 100644 --- a/app/javascript/gabsocial/features/community_timeline/community_timeline.js +++ b/app/javascript/gabsocial/features/community_timeline/community_timeline.js @@ -1,112 +1,111 @@ -import { defineMessages, injectIntl, FormattedMessage } from 'react-intl'; +import { defineMessages, injectIntl } from 'react-intl' import { expandCommunityTimeline, expandPublicTimeline, -} from '../../actions/timelines'; +} from '../../actions/timelines' import { connectCommunityStream, connectPublicStream, -} from '../../actions/streaming'; -import StatusListContainer from '../../containers/status_list_container';; -// import ColumnSettingsContainer from '.containers/column_settings_container'; -import Column from '../../components/column'; +} from '../../actions/streaming' +import StatusListContainer from '../../containers/status_list_container' const messages = defineMessages({ - title: { id: 'column.community', defaultMessage: 'Community timeline' }, -}); + empty: { id: 'empty_column.community', defaultMessage: 'The community timeline is empty. Write something publicly to get the ball rolling!' }, +}) const mapStateToProps = state => { - const allFediverse = state.getIn(['settings', 'community', 'other', 'allFediverse']); - const onlyMedia = state.getIn(['settings', 'community', 'other', 'onlyMedia']); + const allFediverse = state.getIn(['settings', 'community', 'other', 'allFediverse']) + const onlyMedia = state.getIn(['settings', 'community', 'other', 'onlyMedia']) - const timelineId = allFediverse ? 'public' : 'community'; + const timelineId = allFediverse ? 'public' : 'community' return { timelineId, allFediverse, onlyMedia, - hasUnread: state.getIn(['timelines', `${timelineId}${onlyMedia ? ':media' : ''}`, 'unread']) > 0, - }; -}; + // hasUnread: state.getIn(['timelines', `${timelineId}${onlyMedia ? ':media' : ''}`, 'unread']) > 0, + } +} -export default @connect(mapStateToProps) +export default +@connect(mapStateToProps) @injectIntl class CommunityTimeline extends PureComponent { static contextTypes = { router: PropTypes.object, - }; + } static propTypes = { dispatch: PropTypes.func.isRequired, intl: PropTypes.object.isRequired, - hasUnread: PropTypes.bool, + // hasUnread: PropTypes.bool, onlyMedia: PropTypes.bool, allFediverse: PropTypes.bool, timelineId: PropTypes.string, - }; + } componentDidMount () { - const { dispatch, onlyMedia, allFediverse } = this.props; + const { dispatch, onlyMedia, allFediverse } = this.props if (allFediverse) { - dispatch(expandPublicTimeline({ onlyMedia })); - this.disconnect = dispatch(connectPublicStream({ onlyMedia })); + dispatch(expandPublicTimeline({ onlyMedia })) + this.disconnect = dispatch(connectPublicStream({ onlyMedia })) } else { - dispatch(expandCommunityTimeline({ onlyMedia })); - this.disconnect = dispatch(connectCommunityStream({ onlyMedia })); + dispatch(expandCommunityTimeline({ onlyMedia })) + this.disconnect = dispatch(connectCommunityStream({ onlyMedia })) } } componentDidUpdate (prevProps) { if (prevProps.onlyMedia !== this.props.onlyMedia || prevProps.allFediverse !== this.props.allFediverse) { - const { dispatch, onlyMedia, allFediverse } = this.props; + const { dispatch, onlyMedia, allFediverse } = this.props - this.disconnect(); + this.disconnect() if (allFediverse) { - dispatch(expandPublicTimeline({ onlyMedia })); - this.disconnect = dispatch(connectPublicStream({ onlyMedia })); + dispatch(expandPublicTimeline({ onlyMedia })) + this.disconnect = dispatch(connectPublicStream({ onlyMedia })) } else { - dispatch(expandCommunityTimeline({ onlyMedia })); - this.disconnect = dispatch(connectCommunityStream({ onlyMedia })); + dispatch(expandCommunityTimeline({ onlyMedia })) + this.disconnect = dispatch(connectCommunityStream({ onlyMedia })) } } } componentWillUnmount () { if (this.disconnect) { - this.disconnect(); - this.disconnect = null; + this.disconnect() + this.disconnect = null } } handleLoadMore = maxId => { - const { dispatch, onlyMedia, allFediverse } = this.props; + const { dispatch, onlyMedia, allFediverse } = this.props if (allFediverse) { - dispatch(expandPublicTimeline({ maxId, onlyMedia })); + dispatch(expandPublicTimeline({ maxId, onlyMedia })) } else { - dispatch(expandCommunityTimeline({ maxId, onlyMedia })); + dispatch(expandCommunityTimeline({ maxId, onlyMedia })) } } render () { - const { intl, hasUnread, onlyMedia, timelineId, allFediverse } = this.props; + const { intl, onlyMedia, timelineId } = this.props + + const emptyMessage = intl.formatMessage(messages.empty) return ( - - } - /> - - ); + + ) } } 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 index cf3c663f..5ea55df3 100644 --- a/app/javascript/gabsocial/features/compose/components/action_bar/action_bar.js +++ b/app/javascript/gabsocial/features/compose/components/action_bar/action_bar.js @@ -1,6 +1,6 @@ import { defineMessages, injectIntl } from 'react-intl'; import { openModal } from '../../../../actions/modal'; -import DropdownMenuContainer from '../../../../containers/dropdown_menu_container'; +import Dropdown from '../../../../components/dropdown_menu' import { meUsername } from '../../../../initial_state'; const messages = defineMessages({ 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 59914a19..20aca985 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 @@ -3,7 +3,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import { FormattedMessage } from 'react-intl'; import ActionBar from '../action_bar'; import Avatar from '../../../../components/avatar'; -import Permalink from '../../../../components/permalink'; +import Button from '../../../../components/button' import IconButton from '../../../../components/icon_button'; import { me } from '../../../../initial_state'; @@ -26,15 +26,15 @@ class NavigationBar extends ImmutablePureComponent { return (
- +
- + diff --git a/app/javascript/gabsocial/features/follow_requests/components/account_authorize/account_authorize.js b/app/javascript/gabsocial/features/follow_requests/components/account_authorize/account_authorize.js index 53b220cb..f4dcddec 100644 --- a/app/javascript/gabsocial/features/follow_requests/components/account_authorize/account_authorize.js +++ b/app/javascript/gabsocial/features/follow_requests/components/account_authorize/account_authorize.js @@ -3,7 +3,7 @@ import ImmutablePureComponent from 'react-immutable-pure-component'; import ImmutablePropTypes from 'react-immutable-proptypes'; import { authorizeFollowRequest, rejectFollowRequest } from '../../../../actions/accounts'; import { makeGetAccount } from '../../../../selectors'; -import Permalink from '../../../../components/permalink'; +import Button from '../../../../components/button' import Avatar from '../../../../components/avatar'; import DisplayName from '../../../../components/display_name'; import IconButton from '../../../../components/icon_button'; @@ -51,12 +51,12 @@ class AccountAuthorize extends ImmutablePureComponent { return (
- +
diff --git a/app/javascript/gabsocial/features/groups/members/index.js b/app/javascript/gabsocial/features/groups/members/index.js index e07410d4..a7346601 100644 --- a/app/javascript/gabsocial/features/groups/members/index.js +++ b/app/javascript/gabsocial/features/groups/members/index.js @@ -12,7 +12,7 @@ import { FormattedMessage } from 'react-intl'; import AccountContainer from '../../../containers/account_container'; import Column from '../../../components/column'; import ScrollableList from '../../../components/scrollable_list'; -import DropdownMenuContainer from '../../../containers/dropdown_menu_container'; +import Dropdown from '../../../components/dropdown_menu' const mapStateToProps = (state, { params: { id } }) => ({ group: state.getIn(['groups', id]), diff --git a/app/javascript/gabsocial/features/groups/timeline/components/header.js b/app/javascript/gabsocial/features/groups/timeline/components/header.js index 488c10df..0022774e 100644 --- a/app/javascript/gabsocial/features/groups/timeline/components/header.js +++ b/app/javascript/gabsocial/features/groups/timeline/components/header.js @@ -2,7 +2,7 @@ import ImmutablePropTypes from 'react-immutable-proptypes'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { defineMessages, injectIntl } from 'react-intl'; import { NavLink } from 'react-router-dom'; -import DropdownMenuContainer from '../../../../containers/dropdown_menu_container'; +import Dropdown from '../../../../components/dropdown_menu' import Button from '../../../../components/button'; const messages = defineMessages({ @@ -24,7 +24,7 @@ class Header extends ImmutablePureComponent { router: PropTypes.object, }; - getActionButton() { +getActionButton() { const { group, relationships, toggleMembership, intl } = this.props; const toggle = () => toggleMembership(group, relationships); diff --git a/app/javascript/gabsocial/features/home_timeline/index.js b/app/javascript/gabsocial/features/home_timeline/index.js index 260d1350..dc2e74da 100644 --- a/app/javascript/gabsocial/features/home_timeline/index.js +++ b/app/javascript/gabsocial/features/home_timeline/index.js @@ -11,7 +11,8 @@ const mapStateToProps = state => ({ isPartial: state.getIn(['timelines', 'home', 'isPartial']), }) -export default @connect(mapStateToProps) +export default +@connect(mapStateToProps) @injectIntl class HomeTimeline extends PureComponent { diff --git a/app/javascript/gabsocial/features/notifications/components/notification/notification.js b/app/javascript/gabsocial/features/notifications/components/notification/notification.js index 66310aac..eaa5e4bb 100644 --- a/app/javascript/gabsocial/features/notifications/components/notification/notification.js +++ b/app/javascript/gabsocial/features/notifications/components/notification/notification.js @@ -4,7 +4,7 @@ import { HotKeys } from 'react-hotkeys'; import ImmutablePropTypes from 'react-immutable-proptypes'; import StatusContainer from '../../../../containers/status_container'; import AccountContainer from '../../../../containers/account_container'; -import Permalink from '../../../../components/permalink'; +import Button from '../../../../components/button' import Icon from '../../../../components/icon'; const notificationForScreenReader = (intl, message, timestamp) => { @@ -240,7 +240,7 @@ class Notification extends ImmutablePureComponent { const { notification } = this.props; const account = notification.get('account'); const displayNameHtml = { __html: account.get('display_name_html') }; - const link = ; + const link =
- ); + ) } } diff --git a/app/javascript/gabsocial/components/layouts/default_layout.js b/app/javascript/gabsocial/layouts/default_layout.js similarity index 94% rename from app/javascript/gabsocial/components/layouts/default_layout.js rename to app/javascript/gabsocial/layouts/default_layout.js index e363823f..ff324c35 100644 --- a/app/javascript/gabsocial/components/layouts/default_layout.js +++ b/app/javascript/gabsocial/layouts/default_layout.js @@ -1,7 +1,7 @@ import Sticky from 'react-stickynode' -import Search from '../search' -import ColumnHeader from '../column_header' -import Sidebar from '../sidebar' +import Search from '../components/search' +import ColumnHeader from '../components/column_header' +import Sidebar from '../components/sidebar' export default class DefaultLayout extends PureComponent { static propTypes = { diff --git a/app/javascript/gabsocial/layouts/profile_layout.js b/app/javascript/gabsocial/layouts/profile_layout.js new file mode 100644 index 00000000..47be07f6 --- /dev/null +++ b/app/javascript/gabsocial/layouts/profile_layout.js @@ -0,0 +1,55 @@ +import Sticky from 'react-stickynode' +import Sidebar from '../components/sidebar' +import Image from '../components/image' + +export default class ProfileLayout extends PureComponent { + static propTypes = { + layout: PropTypes.object, + title: PropTypes.string, + showBackBtn: PropTypes.bool, + } + + render() { + const { children, layout } = this.props + + return ( +
+ + + +
+ +
+
+
+ +
+
+ +
+ +
+
+
+ {children} +
+
+ +
+ +
+ {layout} +
+
+
+
+
+
+ +
+ +
+ ) + } + +} diff --git a/app/javascript/gabsocial/components/layouts/search_layout.js b/app/javascript/gabsocial/layouts/search_layout.js similarity index 94% rename from app/javascript/gabsocial/components/layouts/search_layout.js rename to app/javascript/gabsocial/layouts/search_layout.js index e42d007f..d142cf86 100644 --- a/app/javascript/gabsocial/components/layouts/search_layout.js +++ b/app/javascript/gabsocial/layouts/search_layout.js @@ -1,7 +1,7 @@ import Sticky from 'react-stickynode' -import Search from '../search' -import ColumnHeader from '../column_header' -import Sidebar from '../sidebar' +import Search from '../components/search' +import ColumnHeader from '../components/column_header' +import Sidebar from '../components/sidebar' export default class SearchLayout extends PureComponent { static propTypes = { diff --git a/app/javascript/gabsocial/pages/group_page.js b/app/javascript/gabsocial/pages/group_page.js index efb34bc4..6ea0fdcf 100644 --- a/app/javascript/gabsocial/pages/group_page.js +++ b/app/javascript/gabsocial/pages/group_page.js @@ -5,7 +5,7 @@ import { fetchGroup } from '../actions/groups'; import HeaderContainer from '../features/groups/timeline/containers/header_container'; import GroupPanel from '../features/groups/timeline/components/panel'; // import GroupSidebarPanel from '../features/groups/sidebar_panel'; -import DefaultLayout from '../components/layouts/default_layout'; +import DefaultLayout from '../layouts/default_layout'; import { WhoToFollowPanel } from '../components/panel'; import LinkFooter from '../components/link_footer'; diff --git a/app/javascript/gabsocial/pages/groups_page.js b/app/javascript/gabsocial/pages/groups_page.js index a978f428..ffad1734 100644 --- a/app/javascript/gabsocial/pages/groups_page.js +++ b/app/javascript/gabsocial/pages/groups_page.js @@ -1,7 +1,7 @@ import { Fragment } from 'react' import LinkFooter from '../components/link_footer' import GroupsPanel from '../components/panel/groups_panel' -import DefaultLayout from '../components/layouts/default_layout' +import DefaultLayout from '../layouts/default_layout' export default class GroupsPage extends PureComponent { diff --git a/app/javascript/gabsocial/pages/home_page.js b/app/javascript/gabsocial/pages/home_page.js index 1f0e297b..aac70c4f 100644 --- a/app/javascript/gabsocial/pages/home_page.js +++ b/app/javascript/gabsocial/pages/home_page.js @@ -6,7 +6,7 @@ import ProgressPanel from '../components/panel/progress_panel' import UserPanel from '../components/panel/user_panel' import TrendsPanel from '../components/panel/trends_panel' import HashtagsPanel from '../components/panel/hashtags_panel' -import DefaultLayout from '../components/layouts/default_layout' +import DefaultLayout from '../layouts/default_layout' import TimelineComposeBlock from '../components/timeline_compose_block' import Divider from '../components/divider' diff --git a/app/javascript/gabsocial/pages/list_page.js b/app/javascript/gabsocial/pages/list_page.js index 78c5dbd7..1c5cf573 100644 --- a/app/javascript/gabsocial/pages/list_page.js +++ b/app/javascript/gabsocial/pages/list_page.js @@ -2,7 +2,7 @@ import { Fragment } from 'react' import ImmutablePropTypes from 'react-immutable-proptypes' import ImmutablePureComponent from 'react-immutable-pure-component' import LinkFooter from '../components/link_footer' -import DefaultLayout from '../components/layouts/default_layout' +import DefaultLayout from '../layouts/default_layout' import ListDetailsPanel from '../components/panel/list_details_panel' const mapStateToProps = (state, props) => ({ diff --git a/app/javascript/gabsocial/pages/lists_page.js b/app/javascript/gabsocial/pages/lists_page.js index 1d14a7a1..32c1a918 100644 --- a/app/javascript/gabsocial/pages/lists_page.js +++ b/app/javascript/gabsocial/pages/lists_page.js @@ -2,7 +2,7 @@ import { Fragment } from 'react' import LinkFooter from '../components/link_footer' import WhoToFollowPanel from '../components/panel/who_to_follow_panel' import TrendsPanel from '../components/panel/trends_panel' -import DefaultLayout from '../components/layouts/default_layout' +import DefaultLayout from '../layouts/default_layout' export default class ListsPage extends PureComponent { diff --git a/app/javascript/gabsocial/pages/notifications_page.js b/app/javascript/gabsocial/pages/notifications_page.js index 84927002..f00f7d29 100644 --- a/app/javascript/gabsocial/pages/notifications_page.js +++ b/app/javascript/gabsocial/pages/notifications_page.js @@ -2,7 +2,7 @@ import { Fragment } from 'react' import LinkFooter from '../components/link_footer' import WhoToFollowPanel from '../components/panel/who_to_follow_panel' import TrendsPanel from '../components/panel/trends_panel' -import DefaultLayout from '../components/layouts/default_layout' +import DefaultLayout from '../layouts/default_layout' export default class NotificationsPage extends PureComponent { render() { diff --git a/app/javascript/gabsocial/pages/profile_page.js b/app/javascript/gabsocial/pages/profile_page.js index 48844f9f..aa154b33 100644 --- a/app/javascript/gabsocial/pages/profile_page.js +++ b/app/javascript/gabsocial/pages/profile_page.js @@ -1,26 +1,25 @@ -import { Fragment } from 'react'; -import ImmutablePropTypes from 'react-immutable-proptypes'; -import ImmutablePureComponent from 'react-immutable-pure-component'; -// import HeaderContainer from '../features/account_timeline/containers/header_container'; -// import ProfileInfoPanel from '../features/account_timeline/components/profile_info_panel/profile_info_panel'; -// import { WhoToFollowPanel, SignUpPanel } from '../components/panel'; -// import LinkFooter from '../components/link_footer'; -import ProfileLayout from '../components/layouts/profile_layout'; +import { Fragment } from 'react' +import ImmutablePropTypes from 'react-immutable-proptypes' +import ImmutablePureComponent from 'react-immutable-pure-component' +import LinkFooter from '../components/link_footer' +import ProfileInfoPanel from '../components/panel/profile_info_panel' +import MediaGalleryPanel from '../components/panel/media_gallery_panel' +import ProfileLayout from '../layouts/profile_layout' const mapStateToProps = (state, { params: { username }, withReplies = false }) => { - const accounts = state.getIn(['accounts']); - const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() == username.toLowerCase()); + const accounts = state.getIn(['accounts']) + const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() == username.toLowerCase()) - let accountId = -1; - let account = null; - let accountUsername = username; + let accountId = -1 + let account = null + let accountUsername = username if (accountFetchError) { - accountId = null; + accountId = null } else { - account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase()); - accountId = account ? account.getIn(['id'], null) : -1; - accountUsername = account ? account.getIn(['acct'], '') : ''; + account = accounts.find(acct => username.toLowerCase() == acct.getIn(['acct'], '').toLowerCase()) + accountId = account ? account.getIn(['id'], null) : -1 + accountUsername = account ? account.getIn(['acct'], '') : '' } //Children components fetch information @@ -29,10 +28,11 @@ const mapStateToProps = (state, { params: { username }, withReplies = false }) = account, accountId, accountUsername, - }; -}; + } +} -export default @connect(mapStateToProps) +export default +@connect(mapStateToProps) class ProfilePage extends ImmutablePureComponent { static propTypes = { account: ImmutablePropTypes.map, @@ -42,14 +42,23 @@ class ProfilePage extends ImmutablePureComponent { PropTypes.number, ]).isRequired, children: PropTypes.node, - }; + } render() { - const { accountId, account, accountUsername } = this.props; + const { accountId, account, accountUsername } = this.props return ( - - { /*this.props.children */ } + + + + + + )} + > + { /* this.props.children */ } ) } diff --git a/app/javascript/gabsocial/pages/search_page.js b/app/javascript/gabsocial/pages/search_page.js index 78cd8924..104c0100 100644 --- a/app/javascript/gabsocial/pages/search_page.js +++ b/app/javascript/gabsocial/pages/search_page.js @@ -2,7 +2,7 @@ import { Fragment } from 'react' import LinkFooter from '../components/link_footer' import WhoToFollowPanel from '../components/panel/who_to_follow_panel' import TrendsPanel from '../components/panel/trends_panel' -import SearchLayout from '../components/layouts/search_layout' +import SearchLayout from '../layouts/search_layout' export default class SearchPage extends PureComponent { render() { diff --git a/app/javascript/gabsocial/pages/settings_page.js b/app/javascript/gabsocial/pages/settings_page.js new file mode 100644 index 00000000..f872d2ee --- /dev/null +++ b/app/javascript/gabsocial/pages/settings_page.js @@ -0,0 +1,12 @@ +export default class SettingsPage extends PureComponent { + + render() { + const { children } = this.props; + + return ( +
+ {children} +
+ ) + } +} \ No newline at end of file diff --git a/app/javascript/styles/global.css b/app/javascript/styles/global.css index 3db5d120..97893375 100644 --- a/app/javascript/styles/global.css +++ b/app/javascript/styles/global.css @@ -115,6 +115,8 @@ body { .border2PX { border-width: 2px; } .borderBottom2PX { border-bottom-width: 2px; } +.borderDashed { border-style: dashed; } + .marginAuto { margin: auto; } .displayNone { display: none; } @@ -136,6 +138,7 @@ body { .backgroundSubtle2Dark_onHover:hover { background-color: #d9e0e5; } .backgroundcolorSecondary3 { background-color: #F6F6F9; } .backgroundColorPrimary { background-color: #fff; } +.backgroundColorPrimaryOpaque { background-color: rgba(255,255,255,0.8); } .backgroundColorBrandLightOpaque { background-color: rgba(54, 233, 145, 0.1); } .backgroundColorOpaque { background-color: rgba(0,0,0, 0.4); } .backgroundColorBrandLight { background-color: #36e991; } @@ -154,8 +157,10 @@ body { .fillcolorSecondary { fill: #666; } .bottom0 { bottom: 0; } +.bottomAuto { bottom: auto; } .left0 { left: 0px; } .right0 { right: 0px; } +.rightAuto { right: auto; } .top0 { top: 0px; } .lineHeight125 { line-height: 1.25em; } @@ -253,6 +258,7 @@ body { .z1 { z-index: 1; } .z2 { z-index: 2; } .z3 { z-index: 3; } +.z4 { z-index: 4; } .marginVertical5PX { margin-top: 5px;