diff --git a/app/soapbox/actions/favourites.js b/app/soapbox/actions/favourites.js index 44c40cd81..ee884ad17 100644 --- a/app/soapbox/actions/favourites.js +++ b/app/soapbox/actions/favourites.js @@ -10,6 +10,14 @@ export const FAVOURITED_STATUSES_EXPAND_REQUEST = 'FAVOURITED_STATUSES_EXPAND_RE export const FAVOURITED_STATUSES_EXPAND_SUCCESS = 'FAVOURITED_STATUSES_EXPAND_SUCCESS'; export const FAVOURITED_STATUSES_EXPAND_FAIL = 'FAVOURITED_STATUSES_EXPAND_FAIL'; +export const USER_FAVOURITED_STATUSES_FETCH_REQUEST = 'USER_FAVOURITED_STATUSES_FETCH_REQUEST'; +export const USER_FAVOURITED_STATUSES_FETCH_SUCCESS = 'USER_FAVOURITED_STATUSES_FETCH_SUCCESS'; +export const USER_FAVOURITED_STATUSES_FETCH_FAIL = 'USER_FAVOURITED_STATUSES_FETCH_FAIL'; + +export const USER_FAVOURITED_STATUSES_EXPAND_REQUEST = 'USER_FAVOURITED_STATUSES_EXPAND_REQUEST'; +export const USER_FAVOURITED_STATUSES_EXPAND_SUCCESS = 'USER_FAVOURITED_STATUSES_EXPAND_SUCCESS'; +export const USER_FAVOURITED_STATUSES_EXPAND_FAIL = 'USER_FAVOURITED_STATUSES_EXPAND_FAIL'; + export function fetchFavouritedStatuses() { return (dispatch, getState) => { if (!isLoggedIn(getState)) return; @@ -96,3 +104,96 @@ export function expandFavouritedStatusesFail(error) { error, }; } + +export function fetchUserFavouritedStatuses(accountId) { + return (dispatch, getState) => { + if (!isLoggedIn(getState)) return; + + if (getState().getIn(['status_lists', `favourites:${accountId}`, 'isLoading'])) { + return; + } + + dispatch(fetchUserFavouritedStatusesRequest(accountId)); + + api(getState).get(`/api/v1/pleroma/accounts/${accountId}/favourites`).then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(importFetchedStatuses(response.data)); + dispatch(fetchUserFavouritedStatusesSuccess(accountId, response.data, next ? next.uri : null)); + }).catch(error => { + dispatch(fetchUserFavouritedStatusesFail(accountId, error)); + }); + }; +} + +export function fetchUserFavouritedStatusesRequest(accountId) { + return { + type: USER_FAVOURITED_STATUSES_FETCH_REQUEST, + accountId, + skipLoading: true, + }; +} + +export function fetchUserFavouritedStatusesSuccess(accountId, statuses, next) { + return { + type: USER_FAVOURITED_STATUSES_FETCH_SUCCESS, + accountId, + statuses, + next, + skipLoading: true, + }; +} + +export function fetchUserFavouritedStatusesFail(accountId, error) { + return { + type: USER_FAVOURITED_STATUSES_FETCH_FAIL, + accountId, + error, + skipLoading: true, + }; +} + +export function expandUserFavouritedStatuses(accountId) { + return (dispatch, getState) => { + if (!isLoggedIn(getState)) return; + + const url = getState().getIn(['status_lists', `favourites:${accountId}`, 'next'], null); + + if (url === null || getState().getIn(['status_lists', `favourites:${accountId}`, 'isLoading'])) { + return; + } + + dispatch(expandUserFavouritedStatusesRequest(accountId)); + + api(getState).get(url).then(response => { + const next = getLinks(response).refs.find(link => link.rel === 'next'); + dispatch(importFetchedStatuses(response.data)); + dispatch(expandUserFavouritedStatusesSuccess(accountId, response.data, next ? next.uri : null)); + }).catch(error => { + dispatch(expandUserFavouritedStatusesFail(accountId, error)); + }); + }; +} + +export function expandUserFavouritedStatusesRequest(accountId) { + return { + type: USER_FAVOURITED_STATUSES_EXPAND_REQUEST, + accountId, + }; +} + +export function expandUserFavouritedStatusesSuccess(accountId, statuses, next) { + return { + type: USER_FAVOURITED_STATUSES_EXPAND_SUCCESS, + accountId, + statuses, + next, + }; +} + +export function expandUserFavouritedStatusesFail(accountId, error) { + return { + type: USER_FAVOURITED_STATUSES_EXPAND_FAIL, + accountId, + error, + }; +} diff --git a/app/soapbox/features/account/components/header.js b/app/soapbox/features/account/components/header.js index e477306e1..426486d80 100644 --- a/app/soapbox/features/account/components/header.js +++ b/app/soapbox/features/account/components/header.js @@ -356,24 +356,20 @@ class Header extends ImmutablePureComponent { } - { - ownAccount && -
- - { /* : TODO : shortNumberFormat(account.get('favourite_count')) */ } - - - - - { /* : TODO : shortNumberFormat(account.get('pinned_count')) */ } - - - -
+ {(ownAccount || !account.getIn(['pleroma', 'hide_favorites'], true)) && + { /* : TODO : shortNumberFormat(account.get('favourite_count')) */ } + + + } + + {ownAccount && + + { /* : TODO : shortNumberFormat(account.get('pinned_count')) */ } + + + } diff --git a/app/soapbox/features/favourited_statuses/index.js b/app/soapbox/features/favourited_statuses/index.js index 233acf640..7324a853a 100644 --- a/app/soapbox/features/favourited_statuses/index.js +++ b/app/soapbox/features/favourited_statuses/index.js @@ -2,23 +2,55 @@ import React from 'react'; import { connect } from 'react-redux'; import PropTypes from 'prop-types'; import ImmutablePropTypes from 'react-immutable-proptypes'; -import { fetchFavouritedStatuses, expandFavouritedStatuses } from '../../actions/favourites'; +import { fetchFavouritedStatuses, expandFavouritedStatuses, fetchUserFavouritedStatuses, expandUserFavouritedStatuses } from '../../actions/favourites'; import Column from '../ui/components/column'; import StatusList from '../../components/status_list'; import { injectIntl, FormattedMessage } from 'react-intl'; import ImmutablePureComponent from 'react-immutable-pure-component'; import { debounce } from 'lodash'; import MissingIndicator from 'soapbox/components/missing_indicator'; +import { fetchAccount, fetchAccountByUsername } from '../../actions/accounts'; +import LoadingIndicator from '../../components/loading_indicator'; const mapStateToProps = (state, { params }) => { const username = params.username || ''; const me = state.get('me'); const meUsername = state.getIn(['accounts', me, 'username']); + + const isMyAccount = (username.toLowerCase() === meUsername.toLowerCase()); + + if (isMyAccount) { + return { + isMyAccount, + statusIds: state.getIn(['status_lists', 'favourites', 'items']), + isLoading: state.getIn(['status_lists', 'favourites', 'isLoading'], true), + hasMore: !!state.getIn(['status_lists', 'favourites', 'next']), + }; + } + + const accounts = state.getIn(['accounts']); + const accountFetchError = (state.getIn(['accounts', -1, 'username'], '').toLowerCase() === username.toLowerCase()); + + let accountId = -1; + if (accountFetchError) { + accountId = null; + } else { + const account = accounts.find(acct => username.toLowerCase() === acct.getIn(['acct'], '').toLowerCase()); + accountId = account ? account.getIn(['id'], null) : -1; + } + + const isBlocked = state.getIn(['relationships', accountId, 'blocked_by'], false); + const unavailable = (me === accountId) ? false : isBlocked; + return { - isMyAccount: (username.toLowerCase() === meUsername.toLowerCase()), - statusIds: state.getIn(['status_lists', 'favourites', 'items']), - isLoading: state.getIn(['status_lists', 'favourites', 'isLoading'], true), - hasMore: !!state.getIn(['status_lists', 'favourites', 'next']), + isMyAccount, + accountId, + unavailable, + username, + isAccount: !!state.getIn(['accounts', accountId]), + statusIds: state.getIn(['status_lists', `favourites:${accountId}`, 'items'], []), + isLoading: state.getIn(['status_lists', `favourites:${accountId}`, 'isLoading'], true), + hasMore: !!state.getIn(['status_lists', `favourites:${accountId}`, 'next']), }; }; @@ -36,17 +68,43 @@ class Favourites extends ImmutablePureComponent { }; componentDidMount() { - this.props.dispatch(fetchFavouritedStatuses()); + const { accountId, isMyAccount, username } = this.props; + + if (isMyAccount) + this.props.dispatch(fetchFavouritedStatuses()); + else { + if (accountId && accountId !== -1) { + this.props.dispatch(fetchAccount(accountId)); + this.props.dispatch(fetchUserFavouritedStatuses(accountId)); + } else { + this.props.dispatch(fetchAccountByUsername(username)); + } + } + } + + componentDidUpdate(prevProps) { + const { accountId, isMyAccount } = this.props; + + if (!isMyAccount && accountId && accountId !== -1 && (accountId !== prevProps.accountId && accountId)) { + this.props.dispatch(fetchAccount(accountId)); + this.props.dispatch(fetchUserFavouritedStatuses(accountId)); + } } handleLoadMore = debounce(() => { - this.props.dispatch(expandFavouritedStatuses()); + const { accountId, isMyAccount } = this.props; + + if (isMyAccount) { + this.props.dispatch(expandFavouritedStatuses()); + } else { + this.props.dispatch(expandUserFavouritedStatuses(accountId)); + } }, 300, { leading: true }) render() { - const { statusIds, hasMore, isLoading, isMyAccount } = this.props; + const { statusIds, isLoading, hasMore, isMyAccount, isAccount, accountId, unavailable } = this.props; - if (!isMyAccount) { + if (!isMyAccount && !isAccount && accountId !== -1) { return ( @@ -54,7 +112,27 @@ class Favourites extends ImmutablePureComponent { ); } - const emptyMessage = ; + if (accountId === -1) { + return ( + + + + ); + } + + if (unavailable) { + return ( + +
+ +
+
+ ); + } + + const emptyMessage = isMyAccount + ? + : ; return ( diff --git a/app/soapbox/reducers/status_lists.js b/app/soapbox/reducers/status_lists.js index 7ac8184ac..8a7ba60dc 100644 --- a/app/soapbox/reducers/status_lists.js +++ b/app/soapbox/reducers/status_lists.js @@ -5,6 +5,12 @@ import { FAVOURITED_STATUSES_EXPAND_REQUEST, FAVOURITED_STATUSES_EXPAND_SUCCESS, FAVOURITED_STATUSES_EXPAND_FAIL, + USER_FAVOURITED_STATUSES_FETCH_REQUEST, + USER_FAVOURITED_STATUSES_FETCH_SUCCESS, + USER_FAVOURITED_STATUSES_FETCH_FAIL, + USER_FAVOURITED_STATUSES_EXPAND_REQUEST, + USER_FAVOURITED_STATUSES_EXPAND_SUCCESS, + USER_FAVOURITED_STATUSES_EXPAND_FAIL, } from '../actions/favourites'; import { BOOKMARKED_STATUSES_FETCH_REQUEST, @@ -101,6 +107,16 @@ export default function statusLists(state = initialState, action) { return normalizeList(state, 'favourites', action.statuses, action.next); case FAVOURITED_STATUSES_EXPAND_SUCCESS: return appendToList(state, 'favourites', action.statuses, action.next); + case USER_FAVOURITED_STATUSES_FETCH_REQUEST: + case USER_FAVOURITED_STATUSES_EXPAND_REQUEST: + return setLoading(state, `favourites:${action.accountId}`, true); + case USER_FAVOURITED_STATUSES_FETCH_FAIL: + case USER_FAVOURITED_STATUSES_EXPAND_FAIL: + return setLoading(state, `favourites:${action.accountId}`, false); + case USER_FAVOURITED_STATUSES_FETCH_SUCCESS: + return normalizeList(state, `favourites:${action.accountId}`, action.statuses, action.next); + case USER_FAVOURITED_STATUSES_EXPAND_SUCCESS: + return appendToList(state, `favourites:${action.accountId}`, action.statuses, action.next); case BOOKMARKED_STATUSES_FETCH_REQUEST: case BOOKMARKED_STATUSES_EXPAND_REQUEST: return setLoading(state, 'bookmarks', true);