diff --git a/app/javascript/gabsocial/actions/news.js b/app/javascript/gabsocial/actions/news.js index 84736ffc..db108c38 100644 --- a/app/javascript/gabsocial/actions/news.js +++ b/app/javascript/gabsocial/actions/news.js @@ -1,6 +1,7 @@ import api from '../api' import axios from 'axios' import { importFetchedStatuses } from './importer' +import { TRENDS_RSS_SOURCES } from '../constants' export const GAB_TRENDS_FETCH_REQUEST = 'GAB_TRENDS_FETCH_REQUEST' export const GAB_TRENDS_FETCH_SUCCESS = 'GAB_TRENDS_FETCH_SUCCESS' @@ -54,36 +55,40 @@ const fetchGabTrendsFail = (error) => ({ /** * */ -export const expandGabTrendsFeed = (feedId, page = 0) => (dispatch, getState) => { - dispatch(expandGabTrendsFeedRequest(feedId, page)) +export const expandGabTrendsFeed = (feedId) => (dispatch, getState) => { + if (!feedId) return + const exists = !!TRENDS_RSS_SOURCES.find((block) => block.id === feedId) + if (!exists) return - // const url = `http://trends.gab.com/feed/${feedId}?fmt=json` - api(getState).get(`/api/v1/gab_trends?type=rss`).then((response) => { + const page = getState().getIn(['news', 'trends_feeds', `${feedId}`, 'curPage'], 0) + 1 + + dispatch(expandGabTrendsFeedRequest(feedId)) + + // const url = `http://trends.gab.com/feed/${feedId}?fmt=json&p=${page}` + api(getState).get(`/api/v1/gab_trends?type=rss&page=${page}&feedId=${feedId}`).then((response) => { // axios.get(url).then((response) => { - dispatch(expandGabTrendsFeedSuccess(response.data, feedId, page)) + dispatch(expandGabTrendsFeedSuccess(response.data.rssFeedItems, feedId, response.data.pagination.p)) }).catch((error) => { - dispatch(expandGabTrendsFeedFail(error, feedId, page)) + dispatch(expandGabTrendsFeedFail(error, feedId)) }) } -const expandGabTrendsFeedRequest = (feedId, page) => ({ +const expandGabTrendsFeedRequest = (feedId) => ({ type: GAB_TREND_FEED_EXPAND_REQUEST, feedId, - page, }) -const expandGabTrendsFeedSuccess = (items, feedId, page) => ({ +const expandGabTrendsFeedSuccess = (items, feedId, curPage) => ({ type: GAB_TREND_FEED_EXPAND_SUCCESS, items, feedId, - page, + curPage, }) -const expandGabTrendsFeedFail = (error, feedId, page) => ({ +const expandGabTrendsFeedFail = (error, feedId) => ({ type: GAB_TREND_FEED_EXPAND_FAIL, error, feedId, - page, }) /** diff --git a/app/javascript/gabsocial/components/panel/trends_headlines_panel.js b/app/javascript/gabsocial/components/panel/trends_headlines_panel.js index ed1c92e4..4c589315 100644 --- a/app/javascript/gabsocial/components/panel/trends_headlines_panel.js +++ b/app/javascript/gabsocial/components/panel/trends_headlines_panel.js @@ -21,11 +21,11 @@ class TrendsHeadlinesPanel extends ImmutablePureComponent { } = this.props const count = !!items ? items.count() : 0 - const trendsLeadlineTitle = trendsLeadline.get('title') - const trendsLeadlineImage = trendsLeadline.get('image') - const trendsLeadlineUrl = trendsLeadline.get('trends_url') + const trendsLeadlineTitle = trendsLeadline ? trendsLeadline.get('title') : null + const trendsLeadlineImage = trendsLeadline ? trendsLeadline.get('image') : null + const trendsLeadlineUrl = trendsLeadline ? trendsLeadline.get('trends_url') : null - if ((count === 0 && isFetched) && (!trendsLeadlineTitle || !trendsLeadlineTitle || !trendsLeadlineTitle)) return null + if ((count === 0 && isFetched) && (!trendsLeadlineImage || !trendsLeadlineTitle || !trendsLeadlineTitle)) return null const leadlineButtonClasses = CX({ d: 1, @@ -64,18 +64,21 @@ class TrendsHeadlinesPanel extends ImmutablePureComponent { )) } - + { + !!trendsLeadlineImage && !!trendsLeadlineTitle && trendsLeadlineUrl && + + } ) } @@ -85,7 +88,7 @@ const mapStateToProps = (state) => ({ isLoading: state.getIn(['news', 'trends_headlines', 'isLoading']), isFetched: state.getIn(['news', 'trends_headlines', 'isFetched']), items: state.getIn(['news', 'trends_headlines', 'items']), - trendsLeadline: state.getIn(['news', 'trends_leadline']), + trendsLeadline: state.getIn(['news', 'trends_leadline', 'items']), }) TrendsHeadlinesPanel.propTypes = { diff --git a/app/javascript/gabsocial/components/panel/trends_rss_panel.js b/app/javascript/gabsocial/components/panel/trends_rss_panel.js index f30e82c0..6b107aa0 100644 --- a/app/javascript/gabsocial/components/panel/trends_rss_panel.js +++ b/app/javascript/gabsocial/components/panel/trends_rss_panel.js @@ -1,33 +1,143 @@ import React from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' +import { List as ImmutableList } from 'immutable' import ImmutablePureComponent from 'react-immutable-pure-component' import ImmutablePropTypes from 'react-immutable-proptypes' +import { expandGabTrendsFeed } from '../../actions/news' +import { + CX, + BREAKPOINT_EXTRA_SMALL, +} from '../../constants' +import { getWindowDimension } from '../../utils/is_mobile' import PanelLayout from './panel_layout' +import TrendsCard from '../trends_card' +import Button from '../button' +import LoadMore from '../load_more' +import ScrollableList from '../scrollable_list' + +const initialState = getWindowDimension() class TrendsRSSPanel extends ImmutablePureComponent { + state = { + viewType: 0, + fetched: false, + isXS: initialState.width <= BREAKPOINT_EXTRA_SMALL, + } + + static getDerivedStateFromProps(nextProps, prevState) { + if (nextProps.shouldLoad && !prevState.fetched) { + return { fetched: true } + } + + return null + } + + componentDidUpdate(prevProps, prevState) { + if ((!prevState.fetched && this.state.fetched && this.props.isLazy) || + ((prevProps.trendsRSSId !== this.props.trendsRSSId) && !!prevProps.trendsRSSId)) { + this.handleOnExpand() + } + } + + componentDidMount() { + if (!this.props.isLazy) { + this.handleOnExpand() + this.setState({ fetched: true }) + } + + this.handleResize() + window.addEventListener('keyup', this.handleKeyUp, false) + window.addEventListener('resize', this.handleResize, false) + } + + handleResize = () => { + const { width } = getWindowDimension() + + this.setState({ isXS: width <= BREAKPOINT_EXTRA_SMALL }) + } + + componentWillUnmount() { + window.removeEventListener('keyup', this.handleKeyUp) + window.removeEventListener('resize', this.handleResize, false) + } + + onItemViewClick = () => { + this.setState({ viewType: this.state.viewType === 0 ? 1 : 0 }) + } + + handleOnExpand = () => { + this.props.dispatch(expandGabTrendsFeed(this.props.trendsRSSId)) + } + render() { const { - intl, - onChange, - settings, + trendsRSSId, + isLoading, + isFetched, + items, + hideReadMore, + feed, } = this.props + const { + fetched, + viewType, + isXS, + } = this.state + + const count = !!items ? items.count() : 0 + if (count === 0 && fetched) return null + const hasMore = count % 10 === 0 + + const containerClasses = CX({ + d: 1, + w100PC: 1, + flexRow: viewType === 1, + flexWrap: viewType === 1, + }) return ( - - TrendsRSSPanel - +
+
+ + { + items.map((trend, i) => ( + + )) + } + +
+
) } } -const mapStateToProps = (state) => ({ - // +const mapStateToProps = (state, { trendsRSSId }) => ({ + isLoading: state.getIn(['news', 'trends_feeds', `${trendsRSSId}`, 'isLoading'], false), + isFetched: state.getIn(['news', 'trends_feeds', `${trendsRSSId}`, 'isFetched'], false), + items: state.getIn(['news', 'trends_feeds', `${trendsRSSId}`, 'items'], ImmutableList()), }) -TrendsFeedsPanel.propTypes = { - // +TrendsRSSPanel.propTypes = { + isLazy: PropTypes.bool, + isLoading: PropTypes.bool, + isFetched: PropTypes.bool, + trendsRSSId: PropTypes.string.isRequired, + items: ImmutablePropTypes.list, + isPage: PropTypes.bool, } export default connect(mapStateToProps)(TrendsRSSPanel) \ No newline at end of file diff --git a/app/javascript/gabsocial/features/news_view.js b/app/javascript/gabsocial/features/news_view.js index ebce00e0..a16ba03d 100644 --- a/app/javascript/gabsocial/features/news_view.js +++ b/app/javascript/gabsocial/features/news_view.js @@ -4,20 +4,78 @@ import { connect } from 'react-redux' import { TRENDS_RSS_SOURCES } from '../constants' import WrappedBundle from './ui/util/wrapped_bundle' import { TrendsRSSPanel } from './ui/util/async_components' +import Button from '../components/button' import ColumnIndicator from '../components/column_indicator' +import Text from '../components/text' class NewsView extends React.PureComponent { + state = { + exists: false, + orderedSources: [], + } + + componentDidMount() { + const { params: { trendsRSSId } } = this.props + this.setState({ + exists: this.getExists(trendsRSSId), + orderedSources: this.getOrderedSources(trendsRSSId) + }) + } + + componentDidUpdate(prevProps) { + const { params: { trendsRSSId } } = this.props + if (prevProps.params.trendsRSSId !== trendsRSSId) { + this.setState({ + exists: this.getExists(trendsRSSId), + orderedSources: this.getOrderedSources(trendsRSSId), + }) + } + } + + getExists = (trendsRSSId) => { + return !!TRENDS_RSS_SOURCES.find((source) => source.id === trendsRSSId) + } + + getOrderedSources = (trendsRSSId) => { + const source = TRENDS_RSS_SOURCES.find((source) => source.id === trendsRSSId) + const sourceIndex = TRENDS_RSS_SOURCES.findIndex((source) => source.id === trendsRSSId) + if (!source) return [] + let orderedSources = TRENDS_RSS_SOURCES.filter((source) => source.id !== trendsRSSId); + const activeSource = { ...source, isActive: 1 } + orderedSources[sourceIndex] = activeSource + orderedSources.unshift(activeSource); + return orderedSources + } + render() { const { params: { trendsRSSId } } = this.props - console.log("trendsRSSId:", trendsRSSId) - const exists = !!TRENDS_RSS_SOURCES.find((block) => block.id === trendsRSSId) + const { orderedSources, exists } = this.state if (!exists) return return (
- +
+ { + orderedSources.map((block, i) => ( + + )) + } +
+ +
) } diff --git a/app/javascript/gabsocial/reducers/news.js b/app/javascript/gabsocial/reducers/news.js index 6d951ef3..184f769b 100644 --- a/app/javascript/gabsocial/reducers/news.js +++ b/app/javascript/gabsocial/reducers/news.js @@ -25,11 +25,7 @@ const defaultMap = ImmutableMap({ }) const initialState = ImmutableMap({ - trends_leadline: ImmutableMap({ - title: null, - image: null, - trends_url: null, - }), + trends_leadline: ImmutableMap(), trends_headlines: defaultMap, trends_breaking: defaultMap, gab_news: defaultMap, @@ -72,7 +68,9 @@ const normalizeNewsItem = (item) => { const setStateKeysOnRequest = (state, keys) => { return state.withMutations((map) => { - keys.map((key) => map.setIn([key, 'isLoading'], true)) + keys.map((key) => { + map.setIn([key, 'isLoading'], true) + }) }) } @@ -107,19 +105,18 @@ export default function (state = initialState, action) { try { trendsFetchData.trends_headlines = ImmutableList(action.items.trends.leadHeadlines.map((item) => normalizeHeadlineItem(item))) trendsFetchData.trends_breaking = ImmutableList(action.items.trends.rssFeedItems.map((item) => normalizeTrendsItem(item))) + trendsFetchData.trends_leadline = ImmutableMap({ + title: action.items.trends.headline.title, + image: `https://trends.gab.com/image/${action.items.trends.headline.image._id}`, + trends_url: `https://trends.gab.com/trend?url=${action.items.trends.headline.href}`, + }) } catch (error) { trendsFetchData = { breakingItems: ImmutableList(), headlineItems: ImmutableList(), + trends_leadline: ImmutableMap(), } } - // : todo : - // trends_leadline: ImmutableMap({ - // title: null, - // image: null, - // trends_url: null, - // }), - return setStateKeysOnSuccess(state, trendsFetchData) // @@ -148,13 +145,48 @@ export default function (state = initialState, action) { try { latestGabNewsData.gab_news = ImmutableList(action.items.map((item) => normalizeNewsItem(item))) } catch (error) { - console.log("news reducer error: ", error) latestGabNewsData = { gab_news: ImmutableList(), } } return setStateKeysOnSuccess(state, latestGabNewsData) + // + case GAB_TREND_FEED_EXPAND_REQUEST: + return state.withMutations((map) => { + const exists = !!map.getIn(['trends_feeds', `${action.feedId}`], null) + if (!exists) { + map.setIn(['trends_feeds', `${action.feedId}`], ImmutableMap({ + isLoading: false, + isFetched: false, + items: ImmutableList(), + })) + } else { + map.setIn(['trends_feeds', `${action.feedId}`, 'isLoading'], true) + } + }) + case GAB_TREND_FEED_EXPAND_FAIL: + return state.withMutations((map) => { + map.setIn(['trends_feeds', `${action.feedId}`], ImmutableMap({ + isLoading: false, + isFetched: true, + items: ImmutableList(), + })) + }) + case GAB_TREND_FEED_EXPAND_SUCCESS: + let latestGabTrendFeedData = [] + try { + latestGabTrendFeedData = state.getIn(['trends_feeds', `${action.feedId}`, 'items']).concat(action.items.map((item) => normalizeTrendsItem(item))) + } catch (error) { + latestGabTrendFeedData = ImmutableList() + } + + return state.withMutations((map) => { + map.setIn(['trends_feeds', `${action.feedId}`, 'isLoading'], false) + map.setIn(['trends_feeds', `${action.feedId}`, 'isFetched'], true) + map.setIn(['trends_feeds', `${action.feedId}`, 'curPage'], action.curPage) + map.setIn(['trends_feeds', `${action.feedId}`, 'items'], latestGabTrendFeedData) + }) default: return state }