diff --git a/app/javascript/gabsocial/components/deck_column.js b/app/javascript/gabsocial/components/deck_column.js index 82235816..92dae99b 100644 --- a/app/javascript/gabsocial/components/deck_column.js +++ b/app/javascript/gabsocial/components/deck_column.js @@ -11,12 +11,19 @@ class DeckColumn extends React.PureComponent { icon, children, index, + noButtons, } = this.props return (
- +
{children}
@@ -32,6 +39,7 @@ DeckColumn.propTypes = { subtitle: PropTypes.string, icon: PropTypes.string, index: PropTypes.number, + noButtons: PropTypes.bool, } export default DeckColumn \ No newline at end of file diff --git a/app/javascript/gabsocial/components/deck_column_header.js b/app/javascript/gabsocial/components/deck_column_header.js index 0abd5440..c5ffb763 100644 --- a/app/javascript/gabsocial/components/deck_column_header.js +++ b/app/javascript/gabsocial/components/deck_column_header.js @@ -22,6 +22,7 @@ class DeckColumnHeader extends React.PureComponent { subtitle, icon, children, + noButtons, } = this.props return ( @@ -40,7 +41,7 @@ class DeckColumnHeader extends React.PureComponent { { !!subtitle && {subtitle} }
{ - !!title && + !!title && !noButtons &&
-
+
this.onAdd('pro')} /> this.onAdd('compose')} /> this.onAdd('group')} />
+
+ this.onAdd('hashtag')} /> + this.onAdd('explore')} /> + this.onAdd('news')} /> +
) diff --git a/app/javascript/gabsocial/components/sidebar/deck_sidebar.js b/app/javascript/gabsocial/components/sidebar/deck_sidebar.js index 5644844e..9bac560c 100644 --- a/app/javascript/gabsocial/components/sidebar/deck_sidebar.js +++ b/app/javascript/gabsocial/components/sidebar/deck_sidebar.js @@ -49,6 +49,8 @@ class DeckSidebar extends ImmutablePureComponent { render() { const { account, logoDisabled } = this.props + + const isPro = !!account ? account.get('is_pro') : false return (
@@ -83,7 +85,7 @@ class DeckSidebar extends ImmutablePureComponent { - + { isPro && }
diff --git a/app/javascript/gabsocial/constants.js b/app/javascript/gabsocial/constants.js index 747879d2..0449f04a 100644 --- a/app/javascript/gabsocial/constants.js +++ b/app/javascript/gabsocial/constants.js @@ -166,7 +166,8 @@ export const TIMELINE_INJECTION_WEIGHT_MULTIPLIER = 100 export const TIMELINE_INJECTION_WEIGHT_SUBTRACTOR = 0.005 export const TIMELINE_INJECTION_WEIGHT_MIN = 0.01 -export const GAB_DECK_OPTIONS = ['home', 'user.id', 'notifications', 'list.id', 'likes', 'bookmarks', 'pro', 'compose', 'group.id'] +export const GAB_DECK_MAX_ITEMS = 8 +export const GAB_DECK_OPTIONS = ['home', 'user.id', 'notifications', 'list.id', 'likes', 'bookmarks', 'pro', 'compose', 'group.id', 'explore', 'news', 'news.id', 'hashtag.id'] export const TRENDS_RSS_SOURCES = [ {'id':'5daf64b18e955e2433b0f5ce','title':'Breitbart'}, diff --git a/app/javascript/gabsocial/features/deck.js b/app/javascript/gabsocial/features/deck.js index bd116664..3cbf881c 100644 --- a/app/javascript/gabsocial/features/deck.js +++ b/app/javascript/gabsocial/features/deck.js @@ -8,16 +8,20 @@ import { sortableElement, } from 'react-sortable-hoc' import { me, meUsername} from '../initial_state' +import { + GAB_DECK_MAX_ITEMS, + MODAL_PRO_UPGRADE, +} from '../constants' import { deckConnect, deckDisconnect, updateDeckColumnAtIndex, } from '../actions/deck' -import { - saveSettings, -} from '../actions/settings' +import { saveSettings } from '../actions/settings' +import { openModal } from '../actions/modal' import WrappedBundle from './ui/util/wrapped_bundle' import DeckColumn from '../components/deck_column' +import Text from '../components/text' import { AccountTimeline, Compose, @@ -27,6 +31,8 @@ import { HashtagTimeline, BookmarkedStatuses, ProTimeline, + News, + ExploreTimeline, } from './ui/util/async_components' class Deck extends React.PureComponent { @@ -35,22 +41,21 @@ class Deck extends React.PureComponent { router: PropTypes.object, } - componentDidMount () { - this.props.connectDeck() - } - - componentWillUnmount() { - this.props.disconnectDeck() - } - componentDidMount () { this.props.dispatch(deckConnect()) + console.log("this.props.isPro:", this.props) + if (!this.props.isPro) this.handleOnOpenProUpgradeModal() } componentWillUnmount() { this.props.dispatch(deckDisconnect()) } + handleOnOpenProUpgradeModal = () => { + console.log("handleOnOpenProUpgradeModal") + this.props.dispatch(openModal(MODAL_PRO_UPGRADE)) + } + onSortEnd = ({oldIndex, newIndex}) => { this.props.dispatch(updateDeckColumnAtIndex(oldIndex, newIndex)) } @@ -66,7 +71,7 @@ class Deck extends React.PureComponent { } getDeckColumn = (deckColumn, index) => { - if (!deckColumn) return null + if (!deckColumn || !isPro) return null let Component = null let componentParams = {} @@ -105,10 +110,22 @@ class Deck extends React.PureComponent { icon = 'pro' Component = ProTimeline break + case 'news': + title = 'News' + icon = 'news' + Component = News + componentParams = { isSmall: true } + break + case 'explore': + title = 'Explore' + icon = 'explore' + Component = ExploreTimeline + break default: break } + // : todo : if (!Component) { if (deckColumn.indexOf('user.') > -1) { @@ -116,6 +133,10 @@ class Deck extends React.PureComponent { } else if (deckColumn.indexOf('group.') > -1) { + } else if (deckColumn.indexOf('news.') > -1) { + + } else if (deckColumn.indexOf('hashtag.') > -1) { + } } @@ -135,12 +156,9 @@ class Deck extends React.PureComponent { } render () { - const { gabDeckOrder } = this.props - - console.log("gabDeckOrder:", gabDeckOrder) + const { gabDeckOrder, isPro } = this.props const isEmpty = gabDeckOrder.size === 0 - // : todo : max: 12 return ( { - isEmpty && + (isEmpty || !isPro) && - + + { + !isPro && + +
+ + Gab Deck for GabPRO + +
+
+ }
} { - !isEmpty && - gabDeckOrder.map((deckOption, i) => this.getDeckColumn(deckOption, i)) + !isEmpty && isPro && + gabDeckOrder.splice(0, GAB_DECK_MAX_ITEMS).map((deckOption, i) => this.getDeckColumn(deckOption, i)) }
) @@ -181,10 +209,12 @@ const SortableContainer = sortableContainer(({children}) => ( )) const mapStateToProps = (state) => ({ + isPro: state.getIn(['accounts', me, 'is_pro']), gabDeckOrder: state.getIn(['settings', 'gabDeckOrder']), }) Deck.propTypes = { + isPro: PropTypes.bool.isRequired, gabDeckOrder: ImmutablePropTypes.list, } diff --git a/app/javascript/gabsocial/features/messages/components/chat_message_header.js b/app/javascript/gabsocial/features/messages/components/chat_message_header.js index 1d806d6f..92100178 100644 --- a/app/javascript/gabsocial/features/messages/components/chat_message_header.js +++ b/app/javascript/gabsocial/features/messages/components/chat_message_header.js @@ -86,7 +86,7 @@ const mapDispatchToProps = (dispatch) => ({ dispatch(openPopover(POPOVER_CHAT_CONVERSATION_OPTIONS, { chatConversationId, targetRef, - position: 'bottom', + position: 'left-end', })) }, }) diff --git a/app/javascript/gabsocial/features/news.js b/app/javascript/gabsocial/features/news.js index 067627cc..776b5980 100644 --- a/app/javascript/gabsocial/features/news.js +++ b/app/javascript/gabsocial/features/news.js @@ -11,8 +11,6 @@ import Button from '../components/button' import Text from '../components/text' import TrendsItem from '../components/trends_item' import PreviewCardItem from '../components/preview_card_item' -import ResponsiveClassesComponent from './ui/util/responsive_classes_component' -import Responsive from './ui/util/responsive_component' import WrappedBundle from './ui/util/wrapped_bundle' import { GabNewsPanel, @@ -23,11 +21,15 @@ import { TrendsHeadlinesPanel, TrendsRSSPanel, } from './ui/util/async_components' +import { getWindowDimension } from '../utils/is_mobile' + +const initialState = getWindowDimension() class News extends React.PureComponent { state = { lazyLoaded: false, + width: initialState.width, } componentDidMount() { @@ -35,10 +37,22 @@ class News extends React.PureComponent { this.documentElement = document.scrollingElement || document.documentElement this.window.addEventListener('scroll', this.handleScroll) + + this.handleResize() + window.addEventListener('keyup', this.handleKeyUp, false) + window.addEventListener('resize', this.handleResize, false) } componentWillUnmount() { this.detachScrollListener() + window.removeEventListener('keyup', this.handleKeyUp) + window.removeEventListener('resize', this.handleResize, false) + } + + handleResize = () => { + const { width } = getWindowDimension() + + this.setState({ width }) } detachScrollListener = () => { @@ -57,56 +71,50 @@ class News extends React.PureComponent { }, 150, { trailing: true }) render() { - const { children } = this.props - const { lazyLoaded } = this.state + const { children, isSmall } = this.props + const { lazyLoaded, width } = this.state - // const orderXS = ['headlines', 'breaking', 'trending_links', 'latest_from_gab', 'gab_news', 'trends_feeds'] + const isXS = width <= BREAKPOINT_EXTRA_SMALL - return ( -
- - - - - { /* DESKTOP */ } - - - - - - { /* MOBILE */ } - + if (isXS || isSmall) { + return ( +
+
+
- - - - - { /* DESKTOP */ } - -
- - -
-
- - +
+
+ ) + } + return ( +
+
+
+ + + +
+
+ + + +
+
) } } +News.propTypes = { + isSmall: PropTypes.bool, +} + export default News \ No newline at end of file diff --git a/app/javascript/gabsocial/reducers/settings.js b/app/javascript/gabsocial/reducers/settings.js index 2f0d77de..4080a673 100644 --- a/app/javascript/gabsocial/reducers/settings.js +++ b/app/javascript/gabsocial/reducers/settings.js @@ -18,6 +18,7 @@ import { TIMELINE_INJECTION_PWA, TIMELINE_INJECTION_SHOP, TIMELINE_INJECTION_USER_SUGGESTIONS, + GAB_DECK_MAX_ITEMS, } from '../constants' import { Map as ImmutableMap, List as ImmutableList, fromJS } from 'immutable' import uuid from '../utils/uuid' @@ -92,9 +93,8 @@ export default function settings(state = initialState, action) { case LIST_DELETE_SUCCESS: return filterDeadListColumns(state, action.id) case DECK_SET_COLUMN_AT_INDEX: - // : todo : max: 12 const sizeOfDeck = state.get('gabDeckOrder', ImmutableList()).size - const newIndex = Math.max(action.index || 0, sizeOfDeck) + const newIndex = Math.min(Math.max(action.index || 0, sizeOfDeck), GAB_DECK_MAX_ITEMS) return state.setIn(['gabDeckOrder', newIndex + 1], action.column).set('saved', false) case DECK_DELETE_COLUMN_AT_INDEX: return state.deleteIn(['gabDeckOrder', action.index]) diff --git a/package.json b/package.json index d31855c7..e62712d8 100644 --- a/package.json +++ b/package.json @@ -56,7 +56,7 @@ "cssnano": "^4.1.10", "detect-passive-events": "^1.0.2", "dotenv": "^8.0.0", - "draft-js": "^0.11.4", + "draft-js": "^0.11.7", "draftjs-to-markdown": "^0.6.0", "emoji-mart": "Gargron/emoji-mart#build", "es6-symbol": "^3.1.1", @@ -113,6 +113,7 @@ "react-redux-loading-bar": "^4.0.8", "react-router-dom": "^4.1.1", "react-router-scroll-4": "^1.0.0-beta.2", + "react-sortable-hoc": "^1.11.0", "react-stickynode": "^3.0.4", "react-swipeable-views": "^0.13.9", "react-textarea-autosize": "^7.1.0",